diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 182d2dd82..0f1eb56ce 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -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 \ No newline at end of file + required: false diff --git a/bukkit/src/main/java/com/viaversion/viaversion/bukkit/providers/BukkitAckSequenceProvider.java b/bukkit/src/main/java/com/viaversion/viaversion/bukkit/providers/BukkitAckSequenceProvider.java index 64965e488..5e3f4fc3b 100644 --- a/bukkit/src/main/java/com/viaversion/viaversion/bukkit/providers/BukkitAckSequenceProvider.java +++ b/bukkit/src/main/java/com/viaversion/viaversion/bukkit/providers/BukkitAckSequenceProvider.java @@ -36,7 +36,7 @@ public final class BukkitAckSequenceProvider extends AckSequenceProvider { final SequenceStorage sequenceStorage = connection.get(SequenceStorage.class); final int previousSequence = sequenceStorage.setSequenceId(sequence); if (previousSequence == -1) { - plugin.getServer().getScheduler().runTask(plugin, new AckSequenceTask(connection, sequenceStorage)); + plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new AckSequenceTask(connection, sequenceStorage), 1); } } } \ No newline at end of file diff --git a/common/src/main/java/com/viaversion/viaversion/configuration/AbstractViaConfig.java b/common/src/main/java/com/viaversion/viaversion/configuration/AbstractViaConfig.java index 2a26ebeca..5c45c5f86 100644 --- a/common/src/main/java/com/viaversion/viaversion/configuration/AbstractViaConfig.java +++ b/common/src/main/java/com/viaversion/viaversion/configuration/AbstractViaConfig.java @@ -31,6 +31,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import java.io.File; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.function.IntPredicate; @@ -160,10 +161,12 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf } private BlockedProtocolVersions loadBlockedProtocolVersions() { - IntSet blockedProtocols = new IntOpenHashSet(getIntegerList("block-protocols")); + List blockProtocols = getListSafe("block-protocols", Integer.class, "Invalid blocked version protocol found in config: '%s'"); + List blockVersions = getListSafe("block-versions", String.class, "Invalid blocked version found in config: '%s'"); + IntSet blockedProtocols = new IntOpenHashSet(blockProtocols); int lowerBound = -1; int upperBound = -1; - for (String s : getStringList("block-versions")) { + for (String s : blockVersions) { if (s.isEmpty()) { continue; } diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_19to1_18_2/packets/EntityPackets.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_19to1_18_2/packets/EntityPackets.java index 07babe406..e8e857994 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_19to1_18_2/packets/EntityPackets.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_19to1_18_2/packets/EntityPackets.java @@ -21,6 +21,7 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.google.common.collect.Maps; import com.viaversion.viaversion.api.Via; import com.viaversion.viaversion.api.data.entity.DimensionData; import com.viaversion.viaversion.api.minecraft.Position; @@ -39,12 +40,10 @@ import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.ClientboundPacke import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.Protocol1_19To1_18_2; import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.storage.DimensionRegistryStorage; import com.viaversion.viaversion.rewriter.EntityRewriter; +import com.viaversion.viaversion.util.Pair; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public final class EntityPackets extends EntityRewriter { @@ -308,15 +307,21 @@ public final class EntityPackets extends EntityRewriter { private static void writeDimensionKey(final PacketWrapper wrapper, final DimensionRegistryStorage registryStorage) throws Exception { // Find dimension key by data final CompoundTag currentDimension = wrapper.read(Type.NBT); - final String dimensionKey = registryStorage.dimensionKey(currentDimension); + String dimensionKey = registryStorage.dimensionKey(currentDimension); if (dimensionKey == null) { - Via.getPlatform().getLogger().severe("The server tried to send dimension data from a dimension the client wasn't told about on join. " + - "Plugins and mods have to make sure they are not creating new dimension types while players are online, and proxies need to make sure they don't scramble dimension data." + - " Known dimensions:"); - for (final Map.Entry entry : registryStorage.dimensions().entrySet()) { - Via.getPlatform().getLogger().severe(entry.getValue() + ": " + entry.getKey()); + if (!Via.getConfig().isSuppressConversionWarnings()) { + Via.getPlatform().getLogger().warning("The server tried to send dimension data from a dimension the client wasn't told about on join. " + + "Plugins and mods have to make sure they are not creating new dimension types while players are online, and proxies need to make sure they don't scramble dimension data." + + " Received dimension: " + currentDimension + ". Known dimensions: " + registryStorage.dimensions()); } - throw new IllegalArgumentException("Dimension not found in registry data from join packet: " + currentDimension); + + // Try to find the most similar dimension + dimensionKey = registryStorage.dimensions().entrySet().stream() + .map(it -> new Pair<>(it, Maps.difference(currentDimension.getValue(), it.getKey().getValue()).entriesInCommon())) + .filter(it -> it.value().containsKey("min_y") && it.value().containsKey("height")) + .max(Comparator.comparingInt(it -> it.value().size())) + .orElseThrow(() -> new IllegalArgumentException("Dimension not found in registry data from join packet: " + currentDimension)) + .key().getValue(); } wrapper.write(Type.STRING, dimensionKey); diff --git a/common/src/main/java/com/viaversion/viaversion/util/Config.java b/common/src/main/java/com/viaversion/viaversion/util/Config.java index 37432644f..9838b29e7 100644 --- a/common/src/main/java/com/viaversion/viaversion/util/Config.java +++ b/common/src/main/java/com/viaversion/viaversion/util/Config.java @@ -18,6 +18,7 @@ package com.viaversion.viaversion.util; import com.google.gson.JsonElement; +import com.viaversion.viaversion.api.Via; import com.viaversion.viaversion.api.configuration.ConfigurationProvider; import com.viaversion.viaversion.libs.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import com.viaversion.viaversion.libs.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; @@ -26,11 +27,7 @@ import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.representer.Representer; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; @@ -214,6 +211,23 @@ public abstract class Config implements ConfigurationProvider { return o != null ? (List) o : new ArrayList<>(); } + public List getListSafe(String key, Class type, String invalidValueMessage) { + Object o = this.config.get(key); + if (o instanceof List) { + List list = (List) o; + List filteredValues = new ArrayList<>(); + for (Object o1 : list) { + if (type.isInstance(o1)) { + filteredValues.add(type.cast(o1)); + } else if (invalidValueMessage != null) { + Via.getPlatform().getLogger().warning(String.format(invalidValueMessage, o1)); + } + } + return filteredValues; + } + return new ArrayList<>(); + } + public @Nullable JsonElement getSerializedComponent(String key) { final Object o = this.config.get(key); if (o != null && !((String) o).isEmpty()) {