Start working on 23w40a

This commit is contained in:
Nassim Jahnke 2023-10-05 18:22:13 +10:00
parent a8acae2d5f
commit cb1b33b3e7
No known key found for this signature in database
GPG Key ID: EF6771C01F6EF02F
11 changed files with 403 additions and 2 deletions

View File

@ -88,6 +88,7 @@ public class ProtocolVersion {
public static final ProtocolVersion v1_19_4 = register(762, "1.19.4");
public static final ProtocolVersion v1_20 = register(763, "1.20/1.20.1", new VersionRange("1.20", 0, 1));
public static final ProtocolVersion v1_20_2 = register(764, "1.20.2");
public static final ProtocolVersion v1_20_3 = register(765, "1.20.3");
public static final ProtocolVersion unknown = register(-1, "UNKNOWN");
public static ProtocolVersion register(int version, String name) {

View File

@ -0,0 +1,64 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.metadata.types;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.minecraft.ParticleType;
public final class MetaTypes1_20_3 extends AbstractMetaTypes {
public final MetaType byteType = add(0, Type.BYTE);
public final MetaType varIntType = add(1, Type.VAR_INT);
public final MetaType longType = add(2, Type.VAR_LONG);
public final MetaType floatType = add(3, Type.FLOAT);
public final MetaType stringType = add(4, Type.STRING);
public final MetaType componentType = add(5, Type.NAMELESS_NBT);
public final MetaType optionalComponentType = add(6, Type.OPTIONAL_NAMELESS_NBT);
public final MetaType itemType = add(7, Type.ITEM1_20_2);
public final MetaType booleanType = add(8, Type.BOOLEAN);
public final MetaType rotationType = add(9, Type.ROTATION);
public final MetaType positionType = add(10, Type.POSITION1_14);
public final MetaType optionalPositionType = add(11, Type.OPTIONAL_POSITION_1_14);
public final MetaType directionType = add(12, Type.VAR_INT);
public final MetaType optionalUUIDType = add(13, Type.OPTIONAL_UUID);
public final MetaType blockStateType = add(14, Type.VAR_INT);
public final MetaType optionalBlockStateType = add(15, Type.VAR_INT);
public final MetaType nbtType = add(16, Type.NAMELESS_NBT);
public final MetaType particleType;
public final MetaType villagerDatatType = add(18, Type.VILLAGER_DATA);
public final MetaType optionalVarIntType = add(19, Type.OPTIONAL_VAR_INT);
public final MetaType poseType = add(20, Type.VAR_INT);
public final MetaType catVariantType = add(21, Type.VAR_INT);
public final MetaType frogVariantType = add(22, Type.VAR_INT);
public final MetaType optionalGlobalPosition = add(23, Type.OPTIONAL_GLOBAL_POSITION);
public final MetaType paintingVariantType = add(24, Type.VAR_INT);
public final MetaType snifferState = add(25, Type.VAR_INT);
public final MetaType vectorType = add(26, Type.VECTOR3F);
public final MetaType quaternionType = add(27, Type.QUATERNION);
public MetaTypes1_20_3(final ParticleType particleType) {
super(28);
this.particleType = add(17, particleType);
}
}

View File

@ -460,7 +460,7 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
}
protected PacketHandler setServerStateHandler(final State state) {
return wrapper -> wrapper.user().getProtocolInfo().setClientState(state);
return wrapper -> wrapper.user().getProtocolInfo().setServerState(state);
}
@Override

View File

@ -85,6 +85,7 @@ public class ProtocolVersion {
public static final ProtocolVersion v1_19_4 = register(762, "1.19.4");
public static final ProtocolVersion v1_20 = register(763, "1.20/1.20.1", new VersionRange("1.20", 0, 1));
public static final ProtocolVersion v1_20_2 = register(764, "1.20.2");
public static final ProtocolVersion v1_20_3 = register(765, 154, "1.20.3");
public static final ProtocolVersion unknown = register(-1, "UNKNOWN");
public static ProtocolVersion register(int version, String name) {

View File

@ -167,6 +167,7 @@ public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T> {
public static final Type<Quaternion> QUATERNION = new QuaternionType();
public static final Type<CompoundTag> NBT = new NBTType();
public static final Type<CompoundTag> NAMELESS_NBT = new NamelessNBTType();
public static final Type<CompoundTag> OPTIONAL_NAMELESS_NBT = new NamelessNBTType.OptionalNamelessNBTType();
public static final Type<CompoundTag[]> NBT_ARRAY = new ArrayType<>(Type.NBT);
public static final Type<GlobalPosition> GLOBAL_POSITION = new GlobalPositionType();
public static final Type<GlobalPosition> OPTIONAL_GLOBAL_POSITION = new GlobalPositionType.OptionalGlobalPositionType();

View File

@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.type.types.minecraft;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.api.type.OptionalType;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
@ -41,4 +42,11 @@ public class NamelessNBTType extends Type<CompoundTag> {
public void write(final ByteBuf buffer, final CompoundTag tag) throws Exception {
NBTType.write(buffer, tag, null);
}
public static final class OptionalNamelessNBTType extends OptionalType<CompoundTag> {
public OptionalNamelessNBTType() {
super(Type.NAMELESS_NBT);
}
}
}

View File

@ -0,0 +1,38 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.version;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaTypes1_20_3;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.minecraft.MetaListType;
import com.viaversion.viaversion.api.type.types.minecraft.ParticleType;
import java.util.List;
public final class Types1_20_3 {
public static final ParticleType PARTICLE = Types1_20.PARTICLE; // Only safe to use after protocol loading
public static final MetaTypes1_20_3 META_TYPES = new MetaTypes1_20_3(PARTICLE);
public static final Type<Metadata> METADATA = new MetadataType(META_TYPES);
public static final Type<List<Metadata>> METADATA_LIST = new MetaListType(METADATA);
}

View File

@ -71,6 +71,7 @@ import com.viaversion.viaversion.protocols.protocol1_19_3to1_19_1.Protocol1_19_3
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.Protocol1_19_4To1_19_3;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.Protocol1_19To1_18_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.Protocol1_20_2To1_20;
import com.viaversion.viaversion.protocols.protocol1_20_3to1_20_2.Protocol1_20_3To1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20to1_19_4.Protocol1_20To1_19_4;
import com.viaversion.viaversion.protocols.protocol1_9_1to1_9.Protocol1_9_1To1_9;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.Protocol1_9_3To1_9_1_2;
@ -182,6 +183,7 @@ public class ProtocolManagerImpl implements ProtocolManager {
registerProtocol(new Protocol1_20To1_19_4(), ProtocolVersion.v1_20, ProtocolVersion.v1_19_4);
registerProtocol(new Protocol1_20_2To1_20(), ProtocolVersion.v1_20_2, ProtocolVersion.v1_20);
registerProtocol(new Protocol1_20_3To1_20_2(), ProtocolVersion.v1_20_3, ProtocolVersion.v1_20_2);
}
@Override

View File

@ -0,0 +1,201 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2023 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.viaversion.protocols.protocol1_20_3to1_20_2;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_19_4Types;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.BitSetType;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ClientboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ClientboundPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ServerboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ServerboundPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_3to1_20_2.rewriter.EntityPacketRewriter1_20_3;
import java.util.BitSet;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class Protocol1_20_3To1_20_2 extends AbstractProtocol<ClientboundPackets1_20_2, ClientboundPackets1_20_2, ServerboundPackets1_20_2, ServerboundPackets1_20_2> {
private static final BitSetType PROFILE_ACTIONS_ENUM_TYPE = new BitSetType(6);
private final EntityPacketRewriter1_20_3 entityRewriter = new EntityPacketRewriter1_20_3(this);
public Protocol1_20_3To1_20_2() {
super(ClientboundPackets1_20_2.class, ClientboundPackets1_20_2.class, ServerboundPackets1_20_2.class, ServerboundPackets1_20_2.class);
}
@Override
protected void registerPackets() {
super.registerPackets();
// Components are now (mostly) written as nbt instead of json strings
// TODO
registerClientbound(ClientboundPackets1_20_2.ADVANCEMENTS, wrapper -> {
wrapper.cancel();
});
registerClientbound(ClientboundPackets1_20_2.TAB_COMPLETE, wrapper -> {
wrapper.cancel();
});
registerClientbound(ClientboundPackets1_20_2.MAP_DATA, wrapper -> {
wrapper.cancel();
});
registerClientbound(ClientboundPackets1_20_2.PLAYER_CHAT, wrapper -> {
wrapper.cancel();
});
registerClientbound(ClientboundPackets1_20_2.SCOREBOARD_OBJECTIVE, wrapper -> {
wrapper.cancel();
});
registerClientbound(ClientboundPackets1_20_2.TEAMS, wrapper -> {
wrapper.cancel();
});
registerClientbound(State.CONFIGURATION, ClientboundConfigurationPackets1_20_2.DISCONNECT.getId(), ClientboundConfigurationPackets1_20_2.DISCONNECT.getId(), this::convertComponent);
registerClientbound(State.CONFIGURATION, ClientboundConfigurationPackets1_20_2.RESOURCE_PACK.getId(), ClientboundConfigurationPackets1_20_2.RESOURCE_PACK.getId(), resourcePackHandler());
registerClientbound(ClientboundPackets1_20_2.DISCONNECT, this::convertComponent);
registerClientbound(ClientboundPackets1_20_2.RESOURCE_PACK, resourcePackHandler());
registerClientbound(ClientboundPackets1_20_2.SERVER_DATA, this::convertComponent);
registerClientbound(ClientboundPackets1_20_2.ACTIONBAR, this::convertComponent);
registerClientbound(ClientboundPackets1_20_2.TITLE_TEXT, this::convertComponent);
registerClientbound(ClientboundPackets1_20_2.TITLE_SUBTITLE, this::convertComponent);
registerClientbound(ClientboundPackets1_20_2.DISGUISED_CHAT, this::convertComponent);
registerClientbound(ClientboundPackets1_20_2.SYSTEM_CHAT, this::convertComponent);
registerClientbound(ClientboundPackets1_20_2.OPEN_WINDOW, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Id
map(Type.VAR_INT); // Window Type
handler(wrapper -> convertComponent(wrapper));
}
});
registerClientbound(ClientboundPackets1_20_2.TAB_LIST, wrapper -> {
convertComponent(wrapper);
convertComponent(wrapper);
});
registerClientbound(ClientboundPackets1_20_2.COMBAT_KILL, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Duration
handler(wrapper -> convertComponent(wrapper));
}
});
registerClientbound(ClientboundPackets1_20_2.PLAYER_INFO_UPDATE, wrapper -> {
wrapper.cancel();
final BitSet actions = wrapper.passthrough(PROFILE_ACTIONS_ENUM_TYPE);
final int entries = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < entries; i++) {
wrapper.passthrough(Type.UUID);
if (actions.get(0)) {
wrapper.passthrough(Type.STRING); // Player Name
final int properties = wrapper.passthrough(Type.VAR_INT);
for (int j = 0; j < properties; j++) {
wrapper.passthrough(Type.STRING); // Name
wrapper.passthrough(Type.STRING); // Value
wrapper.passthrough(Type.OPTIONAL_STRING); // Signature
}
}
if (actions.get(1) && wrapper.passthrough(Type.BOOLEAN)) {
wrapper.passthrough(Type.UUID); // Session UUID
wrapper.passthrough(Type.PROFILE_KEY);
}
if (actions.get(2)) {
wrapper.passthrough(Type.VAR_INT); // Gamemode
}
if (actions.get(3)) {
wrapper.passthrough(Type.BOOLEAN); // Listed
}
if (actions.get(4)) {
wrapper.passthrough(Type.VAR_INT); // Latency
}
if (actions.get(5)) {
convertOptionalComponent(wrapper); // Display name
}
}
});
}
private PacketHandler resourcePackHandler() {
return wrapper -> {
wrapper.passthrough(Type.STRING); // Url
wrapper.passthrough(Type.STRING); // Hash
wrapper.passthrough(Type.BOOLEAN); // Required
convertOptionalComponent(wrapper);
};
}
private void convertComponent(final PacketWrapper wrapper) throws Exception {
wrapper.write(Type.NAMELESS_NBT, jsonComponentToTag(wrapper.read(Type.COMPONENT)));
}
private void convertOptionalComponent(final PacketWrapper wrapper) throws Exception {
wrapper.write(Type.OPTIONAL_NAMELESS_NBT, jsonComponentToTag(wrapper.read(Type.OPTIONAL_COMPONENT)));
}
public static @Nullable JsonElement tagComponentToJson(@Nullable final CompoundTag tag) {
if (tag == null) {
return null;
}
final JsonObject object = new JsonObject();
// TODO
object.addProperty("text", "Subscribe to ViaVersion+ to see this message");
return object;
}
public static @Nullable CompoundTag jsonComponentToTag(@Nullable final JsonElement component) {
if (component == null) {
return null;
}
final CompoundTag tag = new CompoundTag();
// TODO
tag.put("text", new StringTag("Subscribe to ViaVersion+ to see this message"));
return tag;
}
@Override
public void init(final UserConnection connection) {
addEntityTracker(connection, new EntityTrackerBase(connection, Entity1_19_4Types.PLAYER));
}
@Override
protected ServerboundPacketType serverboundFinishConfigurationPacket() {
return ServerboundConfigurationPackets1_20_2.FINISH_CONFIGURATION;
}
@Override
protected ClientboundPacketType clientboundFinishConfigurationPacket() {
return ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION;
}
@Override
public EntityPacketRewriter1_20_3 getEntityRewriter() {
return entityRewriter;
}
}

View File

@ -0,0 +1,85 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2023 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.viaversion.protocols.protocol1_20_3to1_20_2.rewriter;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_19_4Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_20_2;
import com.viaversion.viaversion.api.type.types.version.Types1_20_3;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ClientboundPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_3to1_20_2.Protocol1_20_3To1_20_2;
import com.viaversion.viaversion.rewriter.EntityRewriter;
public final class EntityPacketRewriter1_20_3 extends EntityRewriter<ClientboundPackets1_20_2, Protocol1_20_3To1_20_2> {
public EntityPacketRewriter1_20_3(final Protocol1_20_3To1_20_2 protocol) {
super(protocol);
}
@Override
public void registerPackets() {
registerTrackerWithData1_19(ClientboundPackets1_20_2.SPAWN_ENTITY, Entity1_19_4Types.FALLING_BLOCK);
registerMetadataRewriter(ClientboundPackets1_20_2.ENTITY_METADATA, Types1_20_2.METADATA_LIST, Types1_20_3.METADATA_LIST);
registerRemoveEntities(ClientboundPackets1_20_2.REMOVE_ENTITIES);
protocol.registerClientbound(ClientboundPackets1_20_2.JOIN_GAME, wrapper -> {
wrapper.send(Protocol1_20_3To1_20_2.class);
// Make sure the loading screen is closed, continues old client behavior
final PacketWrapper gameEventPacket = wrapper.create(ClientboundPackets1_20_2.GAME_EVENT);
gameEventPacket.write(Type.UNSIGNED_BYTE, (short) 13);
gameEventPacket.write(Type.FLOAT, 0F);
gameEventPacket.send(Protocol1_20_3To1_20_2.class);
wrapper.cancel();
});
protocol.registerClientbound(ClientboundPackets1_20_2.RESPAWN, wrapper -> {
wrapper.send(Protocol1_20_3To1_20_2.class);
// Make sure the loading screen is closed, continues old client behavior
final PacketWrapper gameEventPacket = wrapper.create(ClientboundPackets1_20_2.GAME_EVENT);
gameEventPacket.write(Type.UNSIGNED_BYTE, (short) 13);
gameEventPacket.write(Type.FLOAT, 0F);
gameEventPacket.send(Protocol1_20_3To1_20_2.class);
wrapper.cancel();
});
}
@Override
protected void registerRewrites() {
filter().handler((event, meta) -> {
final MetaType type = meta.metaType();
if (type == Types1_20_2.META_TYPES.componentType) {
meta.setTypeAndValue(Types1_20_3.META_TYPES.componentType, Protocol1_20_3To1_20_2.jsonComponentToTag(meta.value()));
} else if (type == Types1_20_2.META_TYPES.optionalComponentType) {
meta.setTypeAndValue(Types1_20_3.META_TYPES.optionalComponentType, Protocol1_20_3To1_20_2.jsonComponentToTag(meta.value()));
} else {
meta.setMetaType(Types1_20_3.META_TYPES.byId(type.typeId()));
}
});
}
@Override
public EntityType typeFromId(final int type) {
return Entity1_19_4Types.getTypeFromId(type);
}
}

View File

@ -1,5 +1,5 @@
# Project properties - we put these here so they can be modified without causing a recompile of the build scripts
projectVersion=4.8.1
projectVersion=4.9.0-23w40a-SNAPSHOT
# Smile emoji
mcVersions=1.20.2, 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2, 1.18.1, 1.18, 1.17.1, 1.17, 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16, 1.15.2, 1.15.1, 1.15, 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14, 1.13.2, 1.13.1, 1.13, 1.12.2, 1.12.1, 1.12, 1.11.2, 1.11.1, 1.11, 1.10.2, 1.10.1, 1.10, 1.9.4, 1.9.3, 1.9.2, 1.9.1, 1.9, 1.8.9