Compare commits

...
10 Commits
Author SHA1 Message Date
Nassim Jahnke 3826be4f5f 4.3.1 Release 2022-07-02 19:34:07 +02:00
Myles 4dd7d384c8 Add feature request label to issue templates 2022-06-27 13:37:20 +01:00
Nassim Jahnke a1da3dc11c Fix writing books
Fixes #2959
2022-06-17 08:38:23 +02:00
Nassim Jahnke 87c37b08e8 Fix 1.18.0/1 client on 1.19 server
Fixes #454
2022-06-16 20:06:10 +02:00
Gero 187b79f4e1 Fix NPE for chat messages before join game (#456) 2022-06-14 10:39:35 +02:00
Gero b84cda54c3 Fully implement chat types (#455) 2022-06-09 20:49:27 +02:00
Nassim Jahnke f474067eb2 Don't forget to clear 2022-06-09 20:13:36 +02:00
Nassim Jahnke 6a700d228d Properly deal with custom chat type registries 2022-06-09 20:07:58 +02:00
Nassim Jahnke f08223d1e9 Fix trade offers 2022-06-08 10:10:12 +02:00
Nassim Jahnke a5e3a6b563 Bump version to 4.3.1-SNAPSHOT 2022-06-08 10:08:21 +02:00
12 changed files with 190 additions and 62 deletions

No files matched your search

+2 -1
View File
@@ -1,5 +1,6 @@
name: Feature Request
description: Suggest a feature to be added
labels: [Feature Request]
body:
- type: textarea
@@ -34,4 +35,4 @@ body:
description: |
Does the feature apply to any specific version or environment?
validations:
required: false
required: false
+1 -1
View File
@@ -11,7 +11,7 @@ Supported Versions
**Green** = ViaVersion\
**Purple** = ViaBackwards addition
![supported_versions](https://i.imgur.com/O2KAFFL.png)
![supported_versions](https://i.imgur.com/KpLsMHj.png)
Releases / Dev Builds
-
+1 -1
View File
@@ -5,7 +5,7 @@ plugins {
allprojects {
group = "com.viaversion"
version = "4.3.0"
version = "4.3.1"
description = "Allow older clients to join newer server versions."
}
@@ -51,7 +51,7 @@ public class BackwardsMappings extends MappingDataBase {
}
@Override
protected void loadExtras(JsonObject oldMappings, JsonObject newMappings, @Nullable JsonObject diffMappings) {
protected final void loadExtras(JsonObject oldMappings, JsonObject newMappings, @Nullable JsonObject diffMappings) {
if (diffMappings != null) {
JsonObject diffItems = diffMappings.getAsJsonObject("items");
if (diffItems != null) {
@@ -29,6 +29,7 @@ import com.viaversion.viaversion.libs.gson.JsonObject;
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
import com.viaversion.viaversion.libs.gson.JsonSyntaxException;
import com.viaversion.viaversion.util.GsonUtil;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.io.File;
import java.io.FileReader;
@@ -58,10 +59,14 @@ public final class VBMappingDataLoader {
return null;
}
public static @Nullable InputStream getResource(String name) {
return VBMappingDataLoader.class.getClassLoader().getResourceAsStream("assets/viabackwards/data/" + name);
}
public static JsonObject loadData(String name) {
InputStream stream = VBMappingDataLoader.class.getClassLoader().getResourceAsStream("assets/viabackwards/data/" + name);
try (InputStreamReader reader = new InputStreamReader(stream)) {
return GsonUtil.getGson().fromJson(reader, JsonObject.class);
try (InputStream stream = getResource(name)) {
if (stream == null) return null;
return GsonUtil.getGson().fromJson(new InputStreamReader(stream), JsonObject.class);
} catch (IOException e) {
e.printStackTrace();
return null;
@@ -135,12 +140,12 @@ public final class VBMappingDataLoader {
public static Int2ObjectMap<MappedItem> loadItemMappings(JsonObject oldMapping, JsonObject newMapping, JsonObject diffMapping, boolean warnOnMissing) {
Int2ObjectMap<MappedItem> itemMapping = new Int2ObjectOpenHashMap<>(diffMapping.size(), 0.99F);
Object2IntMap<String> newIdenfierMap = MappingDataLoader.indexedObjectToMap(newMapping);
Object2IntMap<String> oldIdenfierMap = MappingDataLoader.indexedObjectToMap(oldMapping);
Object2IntMap<String> newIdentifierMap = MappingDataLoader.indexedObjectToMap(newMapping);
Object2IntMap<String> oldIdentifierMap = MappingDataLoader.indexedObjectToMap(oldMapping);
for (Map.Entry<String, JsonElement> entry : diffMapping.entrySet()) {
JsonObject object = entry.getValue().getAsJsonObject();
String mappedIdName = object.getAsJsonPrimitive("id").getAsString();
int mappedId = newIdenfierMap.getInt(mappedIdName);
int mappedId = newIdentifierMap.getInt(mappedIdName);
if (mappedId == -1) {
if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {
ViaBackwards.getPlatform().getLogger().warning("No key for " + mappedIdName + " :( ");
@@ -148,7 +153,7 @@ public final class VBMappingDataLoader {
continue;
}
int oldId = oldIdenfierMap.getInt(entry.getKey());
int oldId = oldIdentifierMap.getInt(entry.getKey());
if (oldId == -1) {
if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {
ViaBackwards.getPlatform().getLogger().warning("No old entry for " + mappedIdName + " :( ");
@@ -162,8 +167,8 @@ public final class VBMappingDataLoader {
// Look for missing keys
if (warnOnMissing && !Via.getConfig().isSuppressConversionWarnings()) {
for (Object2IntMap.Entry<String> entry : oldIdenfierMap.object2IntEntrySet()) {
if (!newIdenfierMap.containsKey(entry.getKey()) && !itemMapping.containsKey(entry.getIntValue())) {
for (Object2IntMap.Entry<String> entry : oldIdentifierMap.object2IntEntrySet()) {
if (!newIdentifierMap.containsKey(entry.getKey()) && !itemMapping.containsKey(entry.getIntValue())) {
ViaBackwards.getPlatform().getLogger().warning("No item mapping for " + entry.getKey() + " :( ");
}
}
@@ -41,6 +41,9 @@ import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.kyori.adventure.text.Component;
import com.viaversion.viaversion.libs.kyori.adventure.text.TextReplacementConfig;
import com.viaversion.viaversion.libs.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
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.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;
@@ -53,6 +56,7 @@ import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import java.time.Instant;
import java.util.Map;
import java.util.UUID;
public final class Protocol1_18_2To1_19 extends BackwardsProtocol<ClientboundPackets1_19, ClientboundPackets1_18, ServerboundPackets1_19, ServerboundPackets1_17> {
@@ -138,6 +142,7 @@ public final class Protocol1_18_2To1_19 extends BackwardsProtocol<ClientboundPac
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");
@@ -308,26 +313,72 @@ public final class Protocol1_18_2To1_19 extends BackwardsProtocol<ClientboundPac
return TextReplacementConfig.builder().matchLiteral("%s").replacement(GsonComponentSerializer.gson().deserializeFromTree(replacement)).once().build();
}
private void handleChatType(final PacketWrapper wrapper, final JsonElement senderName, final JsonElement teamName, final JsonElement text) throws Exception {
translatableRewriter.processText(text);
private void handleChatType(final PacketWrapper wrapper, final JsonElement senderName, final JsonElement teamName, final JsonElement message) throws Exception {
translatableRewriter.processText(message);
final byte type = wrapper.get(Type.BYTE, 0);
if (type > 2) {
wrapper.set(Type.BYTE, 0, (byte) 0); // Chat type
final byte id = wrapper.get(Type.BYTE, 0);
CompoundTag chatType = wrapper.user().get(DimensionRegistryStorage.class).chatType(id);
CompoundTag handlers = chatType.get("element");
boolean handled = false;
for (Map.Entry<String, Tag> handler : handlers) {
byte oldId;
switch (handler.getKey()) {
case "chat":
oldId = 1;
break;
case "overlay":
oldId = 2;
break;
default:
continue;
}
CompoundTag decoration = ((CompoundTag) handler.getValue()).get("decoration");
JsonElement formattedMessage;
if (decoration != null) {
String translationKey = (String) decoration.get("translation_key").getValue();
String rawTranslation = ViaBackwards.getConfig().chatTypeFormat(translationKey);
if (rawTranslation == null) {
ViaBackwards.getPlatform().getLogger().warning("Missing chat type translation for key " + translationKey);
continue;
}
Component component = Component.text(rawTranslation);
ListTag parameters = decoration.get("parameters");
if (parameters != null) for (Tag element : parameters) {
switch ((String) element.getValue()) {
case "sender":
component = component.replaceText(replace(senderName));
break;
case "content":
component = component.replaceText(replace(message));
break;
case "team_name":
Preconditions.checkNotNull(teamName, "Team name is null");
component = component.replaceText(replace(teamName));
break;
default:
ViaBackwards.getPlatform().getLogger().warning("Unknown parameter for chat decoration: " + element.getValue());
}
}
formattedMessage = GsonComponentSerializer.gson().serializeToTree(component);
} else {
formattedMessage = message;
}
if (!handled) {
handled = true;
wrapper.set(Type.BYTE, 0, oldId);
wrapper.set(Type.COMPONENT, 0, formattedMessage);
} else {
PacketWrapper extra = wrapper.create(ClientboundPackets1_18.CHAT_MESSAGE);
extra.write(Type.COMPONENT, formattedMessage);
extra.write(Type.BYTE, oldId);
extra.write(Type.UUID, wrapper.get(Type.UUID, 0));
}
}
final String key = CHAT_KEYS[type];
if (key != null) {
Component component = Component.text(ViaBackwards.getConfig().chatTypeFormat(key));
if (key.equals("chat.type.team.text")) {
Preconditions.checkNotNull(teamName, "Team name is null");
component = component.replaceText(replace(teamName));
}
if (senderName != null) {
component = component.replaceText(replace(senderName));
}
component = component.replaceText(replace(text));
wrapper.set(Type.COMPONENT, 0, GsonComponentSerializer.gson().serializeToTree(component));
}
if (!handled) wrapper.cancel();
}
}
@@ -17,23 +17,33 @@
*/
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;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;
import com.viaversion.viaversion.libs.gson.JsonArray;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonObject;
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.Tag;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.Protocol1_19To1_18_2;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.io.IOException;
public final class BackwardsMappings extends com.viaversion.viabackwards.api.data.BackwardsMappings {
private String[] argumentTypes;
private final Int2ObjectMap<CompoundTag> defaultChatTypes = new Int2ObjectOpenHashMap<>();
public BackwardsMappings() {
super("1.19", "1.18", Protocol1_19To1_18_2.class, true);
}
@Override
protected void loadExtras(final JsonObject oldMappings, final JsonObject newMappings, @Nullable final JsonObject diffMappings) {
super.loadExtras(oldMappings, newMappings, diffMappings);
protected void loadVBExtras(final JsonObject oldMappings, final JsonObject newMappings) {
int i = 0;
final JsonArray types = oldMappings.getAsJsonArray("argumenttypes");
this.argumentTypes = new String[types.size()];
@@ -41,9 +51,24 @@ public final class BackwardsMappings extends com.viaversion.viabackwards.api.dat
final String id = element.getAsString();
this.argumentTypes[i++] = id;
}
try {
ListTag chatTypes = BinaryTagIO.readCompressedInputStream(VBMappingDataLoader.getResource("chat-types-1.19.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) {
e.printStackTrace();
}
}
public @Nullable String argumentType(final int argumentTypeId) {
return argumentTypeId >= 0 && argumentTypeId < argumentTypes.length ? argumentTypes[argumentTypeId] : null;
}
public @Nullable CompoundTag chatType(final int id) {
return defaultChatTypes.get(id);
}
}
@@ -25,6 +25,7 @@ import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
@@ -51,7 +52,6 @@ public final class BlockItemPackets1_19 extends ItemRewriter<Protocol1_18_2To1_1
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);
registerTradeList(ClientboundPackets1_19.TRADE_LIST, 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);
@@ -61,10 +61,36 @@ public final class BlockItemPackets1_19 extends ItemRewriter<Protocol1_18_2To1_1
blockRewriter.registerEffect(ClientboundPackets1_19.EFFECT, 1010, 2001);
registerCreativeInvAction(ServerboundPackets1_17.CREATIVE_INVENTORY_ACTION, Type.FLAT_VAR_INT_ITEM);
protocol.registerServerbound(ServerboundPackets1_17.EDIT_BOOK, new PacketRemapper() {
protocol.registerClientbound(ClientboundPackets1_19.TRADE_LIST, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> handleItemToServer(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)));
map(Type.VAR_INT); // Container id
handler(wrapper -> {
final int size = wrapper.read(Type.VAR_INT);
wrapper.write(Type.UNSIGNED_BYTE, (short) size);
for (int i = 0; i < size; i++) {
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // First item
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
final Item secondItem = wrapper.read(Type.FLAT_VAR_INT_ITEM);
if (secondItem != null) {
handleItemToClient(secondItem);
wrapper.write(Type.BOOLEAN, true);
wrapper.write(Type.FLAT_VAR_INT_ITEM, secondItem);
} else {
wrapper.write(Type.BOOLEAN, false);
}
wrapper.passthrough(Type.BOOLEAN); // Out of stock
wrapper.passthrough(Type.INT); // Uses
wrapper.passthrough(Type.INT); // Max uses
wrapper.passthrough(Type.INT); // Xp
wrapper.passthrough(Type.INT); // Special price diff
wrapper.passthrough(Type.FLOAT); // Price multiplier
wrapper.passthrough(Type.INT); //Demand
}
});
}
});
@@ -35,14 +35,12 @@ import com.viaversion.viaversion.api.type.types.version.Types1_18;
import com.viaversion.viaversion.api.type.types.version.Types1_19;
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.protocol1_18to1_17_1.ClientboundPackets1_18;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.ClientboundPackets1_19;
import java.util.HashMap;
import java.util.Map;
public final class EntityPackets1_19 extends EntityRewriter<Protocol1_18_2To1_19> {
public EntityPackets1_19(final Protocol1_18_2To1_19 protocol) {
@@ -127,27 +125,45 @@ public final class EntityPackets1_19 extends EntityRewriter<Protocol1_18_2To1_19
map(Type.STRING_ARRAY); // Worlds
map(Type.NBT); // Dimension registry
handler(wrapper -> {
final DimensionRegistryStorage dimensionRegistryStorage = wrapper.user().get(DimensionRegistryStorage.class);
dimensionRegistryStorage.clear();
// Cache dimensions and find current dimension
final String dimensionKey = wrapper.read(Type.STRING);
final ListTag dimensions = ((CompoundTag) wrapper.get(Type.NBT, 0).get("minecraft:dimension_type")).get("value");
final Map<String, CompoundTag> dimensionsMap = new HashMap<>(dimensions.size());
final CompoundTag registry = wrapper.get(Type.NBT, 0);
final ListTag dimensions = ((CompoundTag) registry.get("minecraft:dimension_type")).get("value");
boolean found = false;
for (final Tag dimension : dimensions) {
final CompoundTag dimensionCompound = (CompoundTag) dimension;
final StringTag nameTag = dimensionCompound.get("name");
final CompoundTag dimensionData = dimensionCompound.get("element");
dimensionsMap.put(nameTag.getValue(), dimensionData.clone());
dimensionRegistryStorage.addDimension(nameTag.getValue(), dimensionData.clone());
if (!found && nameTag.getValue().equals(dimensionKey)) {
wrapper.write(Type.NBT, dimensionData);
found = true;
}
}
if (!found) {
throw new IllegalStateException("Could not find dimension " + dimensionKey + " in dimension registry");
}
wrapper.user().get(DimensionRegistryStorage.class).setDimensions(dimensionsMap);
// Add biome category and track biomes
final CompoundTag biomeRegistry = registry.get("minecraft:worldgen/biome");
final ListTag biomes = biomeRegistry.get("value");
for (final Tag biome : biomes.getValue()) {
final CompoundTag biomeCompound = ((CompoundTag) biome).get("element");
biomeCompound.put("category", new StringTag("none"));
}
tracker(wrapper.user()).setBiomesSent(biomes.size());
// Cache and remove chat types
final ListTag chatTypes = ((CompoundTag) registry.remove("minecraft:chat_type")).get("value");
for (final Tag chatType : chatTypes) {
final CompoundTag chatTypeCompound = (CompoundTag) chatType;
final NumberTag idTag = chatTypeCompound.get("id");
dimensionRegistryStorage.addChatType(idTag.asInt(), chatTypeCompound);
}
});
map(Type.STRING); // World
map(Type.LONG); // Seed
@@ -161,20 +177,6 @@ public final class EntityPackets1_19 extends EntityRewriter<Protocol1_18_2To1_19
read(Type.OPTIONAL_GLOBAL_POSITION); // Read last death location
handler(worldDataTrackerHandler(1));
handler(playerTrackerHandler());
handler(wrapper -> {
final CompoundTag registry = wrapper.get(Type.NBT, 0);
final CompoundTag biomeRegistry = registry.get("minecraft:worldgen/biome");
final ListTag biomes = biomeRegistry.get("value");
for (final Tag biome : biomes.getValue()) {
final CompoundTag biomeCompound = ((CompoundTag) biome).get("element");
biomeCompound.put("category", new StringTag("none"));
}
registry.remove("minecraft:chat_type");
// Track amount of biomes sent
tracker(wrapper.user()).setBiomesSent(biomes.size());
});
}
});
@@ -17,7 +17,10 @@
*/
package com.viaversion.viabackwards.protocol.protocol1_18_2to1_19.storage;
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;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -26,15 +29,30 @@ import java.util.Map;
public final class DimensionRegistryStorage implements StorableObject {
private Map<String, CompoundTag> dimensions = new HashMap<>();
private final Map<String, CompoundTag> dimensions = new HashMap<>();
private final Int2ObjectMap<CompoundTag> chatTypes = new Int2ObjectOpenHashMap<>();
public @Nullable CompoundTag dimension(final String dimensionKey) {
final CompoundTag compoundTag = dimensions.get(dimensionKey);
return compoundTag != null ? compoundTag.clone() : null;
}
public void setDimensions(final Map<String, CompoundTag> dimensions) {
this.dimensions = dimensions;
public void addDimension(final String dimensionKey, final CompoundTag dimension) {
dimensions.put(dimensionKey, dimension);
}
public @Nullable CompoundTag chatType(final int id) {
if (chatTypes.isEmpty()) return Protocol1_18_2To1_19.MAPPINGS.chatType(id);
return chatTypes.get(id);
}
public void addChatType(final int id, final CompoundTag chatType) {
chatTypes.put(id, chatType);
}
public void clear() {
dimensions.clear();
chatTypes.clear();
}
@Override
+1 -1
View File
@@ -3,7 +3,7 @@ metadata.format.version = "1.1"
[versions]
# ViaVersion
viaver = "4.3.0-1.19-rc2-SNAPSHOT"
viaver = "4.3.1"
# Common provided
netty = "4.0.20.Final"