mirror of
https://github.com/ViaVersion/ViaVersion.git
synced 2026-11-08 10:35:24 -05:00
Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
075181f06f | ||
|
|
b712c0055d | ||
|
|
08776de832 | ||
|
|
77b7054629 | ||
|
|
63769b3661 | ||
|
|
12d75daf04 | ||
|
|
413268eb15 | ||
|
|
b27e2a5514 | ||
|
|
c59dfb4d93 | ||
|
|
f66cbd6941 | ||
|
|
1574f343f7 | ||
|
|
022fb96f83 | ||
|
|
7cbc751fea |
No files matched your search
@@ -14,18 +14,23 @@ or as [a standalone proxy](https://github.com/ViaVersion/ViaProxy) to join from
|
||||
any server version from the past decade. **See [HERE](https://viaversion.com) for an overview of the different Via\*
|
||||
projects.**
|
||||
|
||||
Note that ViaVersion will be able to **run best on either Paper servers or
|
||||
through [ViaFabricPlus](https://github.com/ViaVersion/ViaFabricPlus?tab=readme-ov-file#viafabricplus)** due to having
|
||||
direct access to client/server state and more extensive API.
|
||||
**Note:** While ViaVersion works reliably across all listed platforms, it has the highest performance and state accuracy on **Paper** servers and through **[ViaFabricPlus](https://github.com/ViaVersion/ViaFabricPlus)** on clients, since both offer more extensive APIs and direct access to client/server state.
|
||||
|
||||
Supported Versions:
|
||||
### Supported Versions
|
||||
|
||||

|
||||
| Players joining with… | Install |
|
||||
| :--- | :--- |
|
||||
| **Newer** versions than the server | ViaVersion |
|
||||
| **Older** versions than the server, down to 1.9 | ViaVersion + [ViaBackwards](https://github.com/ViaVersion/ViaBackwards) |
|
||||
| **1.7.x – 1.8.x** | ViaVersion + [ViaBackwards](https://github.com/ViaVersion/ViaBackwards) + [ViaRewind](https://github.com/ViaVersion/ViaRewind) |
|
||||
|
||||
**User Docs:** https://docs.viaversion.com
|
||||
If you're stuck, try [this tool](https://viaversion.com/setup) to work out what plugins you need.
|
||||
|
||||
**User Docs:** [docs.viaversion.com](https://docs.viaversion.com)
|
||||
|
||||
Snapshot Support
|
||||
----------
|
||||
|
||||
Snapshot support
|
||||
--------
|
||||
**ViaVersion will only be released a few days *after* a Minecraft update** unless the protocol changes of the update
|
||||
were trivial. If you want early-access, usually days or even weeks before the final release, you can subscribe to
|
||||
either:
|
||||
|
||||
@@ -39,4 +39,11 @@ public record SoundEvent(String identifier, @Nullable Float fixedRange) {
|
||||
}
|
||||
return holder.updateId(soundRewriteFunction, () -> UNKNOWN);
|
||||
}
|
||||
|
||||
public static @Nullable Holder<SoundEvent> rewriteOptionalHolder(@Nullable final Holder<SoundEvent> holder, final Int2IntFunction soundRewriteFunction) {
|
||||
if (holder == null) {
|
||||
return null;
|
||||
}
|
||||
return holder.updateId(soundRewriteFunction, () -> null);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -30,7 +30,6 @@ import com.viaversion.viaversion.api.minecraft.Holder;
|
||||
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
|
||||
import com.viaversion.viaversion.api.minecraft.RegistryKey;
|
||||
import com.viaversion.viaversion.api.minecraft.ResolvableProfile;
|
||||
import com.viaversion.viaversion.api.minecraft.SoundEvent;
|
||||
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_20_5;
|
||||
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_11;
|
||||
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_2;
|
||||
@@ -48,6 +47,7 @@ import com.viaversion.viaversion.api.minecraft.item.data.Bee;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.BlockEntityData;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.BlockStateProperties;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.BlocksAttacks;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.BreakSound;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.BrewingFuel;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.Compostable;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.consumable.Consumable1_21_2;
|
||||
@@ -239,7 +239,7 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
|
||||
public static final StructuredDataKey<Tag> LOCK1_20_5 = new StructuredDataKey<>("lock", Types.TAG);
|
||||
public static final StructuredDataKey<LockCode> LOCK1_21_2 = new StructuredDataKey<>("lock", LockCode.TYPE);
|
||||
public static final StructuredDataKey<CompoundTag> CONTAINER_LOOT = new StructuredDataKey<>("container_loot", Types.COMPOUND_TAG);
|
||||
public static final StructuredDataKey<Holder<SoundEvent>> BREAK_SOUND = new StructuredDataKey<>("break_sound", Types.SOUND_EVENT);
|
||||
public static final StructuredDataKey<BreakSound> BREAK_SOUND = new StructuredDataKey<>("break_sound", BreakSound.TYPE);
|
||||
public static final StructuredDataKey<Compostable> COMPOSTABLE = new StructuredDataKey<>("compostable", Compostable.TYPE);
|
||||
public static final StructuredDataKey<CookingFuel> COOKING_FUEL = new StructuredDataKey<>("cooking_fuel", CookingFuel.TYPE);
|
||||
public static final StructuredDataKey<BrewingFuel> BREWING_FUEL = new StructuredDataKey<>("brewing_fuel", BrewingFuel.TYPE);
|
||||
|
||||
+2
-2
@@ -130,8 +130,8 @@ public record BlocksAttacks(
|
||||
|
||||
@Override
|
||||
public BlocksAttacks rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
|
||||
final Holder<SoundEvent> blockSound = SoundEvent.rewriteHolder(this.blockSound, Rewritable.soundRewriteFunction(protocol, clientbound));
|
||||
final Holder<SoundEvent> disableSound = SoundEvent.rewriteHolder(this.disableSound, Rewritable.soundRewriteFunction(protocol, clientbound));
|
||||
final Holder<SoundEvent> blockSound = SoundEvent.rewriteOptionalHolder(this.blockSound, Rewritable.soundRewriteFunction(protocol, clientbound));
|
||||
final Holder<SoundEvent> disableSound = SoundEvent.rewriteOptionalHolder(this.disableSound, Rewritable.soundRewriteFunction(protocol, clientbound));
|
||||
return new BlocksAttacks(this.blockDelaySeconds, this.disableCooldownScale, this.damageReductions, this.itemDamage, this.bypassedBy, blockSound, disableSound);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 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.item.data;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.Holder;
|
||||
import com.viaversion.viaversion.api.minecraft.SoundEvent;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.type.TransformingType;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.util.Rewritable;
|
||||
|
||||
public record BreakSound(Holder<SoundEvent> sound) implements Rewritable {
|
||||
|
||||
public static final Type<BreakSound> TYPE = TransformingType.of(Types.SOUND_EVENT, BreakSound.class, BreakSound::new, BreakSound::sound);
|
||||
|
||||
@Override
|
||||
public BreakSound rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
|
||||
final Holder<SoundEvent> sound = SoundEvent.rewriteHolder(this.sound, Rewritable.soundRewriteFunction(protocol, clientbound));
|
||||
return this.sound == sound ? this : new BreakSound(sound);
|
||||
}
|
||||
}
|
||||
+10
-1
@@ -22,13 +22,16 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.item.data;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.codec.Ops;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.consumable.ConsumeEffect;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.type.TransformingType;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.util.Copyable;
|
||||
import com.viaversion.viaversion.util.Rewritable;
|
||||
|
||||
public record DeathProtection(ConsumeEffect<?>[] deathEffects) implements Copyable {
|
||||
public record DeathProtection(ConsumeEffect<?>[] deathEffects) implements Copyable, Rewritable {
|
||||
|
||||
public static final Type<DeathProtection> TYPE1_21_2 = new TransformingType<>(ConsumeEffect.ARRAY_TYPE1_21_2, DeathProtection.class, DeathProtection::new, DeathProtection::deathEffects) {
|
||||
@Override
|
||||
@@ -43,6 +46,12 @@ public record DeathProtection(ConsumeEffect<?>[] deathEffects) implements Copyab
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public DeathProtection rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
|
||||
final ConsumeEffect<?>[] deathEffects = ConsumeEffect.rewrite(this.deathEffects, connection, protocol, clientbound);
|
||||
return deathEffects == this.deathEffects ? this : new DeathProtection(deathEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeathProtection copy() {
|
||||
return new DeathProtection(Copyable.copy(deathEffects));
|
||||
|
||||
+11
-1
@@ -22,19 +22,22 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.item.data;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.Holder;
|
||||
import com.viaversion.viaversion.api.minecraft.SoundEvent;
|
||||
import com.viaversion.viaversion.api.minecraft.codec.Ops;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.type.OptionalType;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.util.Rewritable;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public record KineticWeapon(int contactCooldownTicks, int delayTicks, @Nullable Condition dismountConditions,
|
||||
@Nullable Condition knockbackConditions, @Nullable Condition damageConditions,
|
||||
float forwardMovement, float damageMultiplier,
|
||||
@Nullable Holder<SoundEvent> sound, @Nullable Holder<SoundEvent> hitSound) {
|
||||
@Nullable Holder<SoundEvent> sound, @Nullable Holder<SoundEvent> hitSound) implements Rewritable {
|
||||
|
||||
public static final Type<KineticWeapon> TYPE = new Type<>(KineticWeapon.class) {
|
||||
@Override
|
||||
@@ -80,6 +83,13 @@ public record KineticWeapon(int contactCooldownTicks, int delayTicks, @Nullable
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public KineticWeapon rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
|
||||
final Holder<SoundEvent> sound = SoundEvent.rewriteOptionalHolder(this.sound, Rewritable.soundRewriteFunction(protocol, clientbound));
|
||||
final Holder<SoundEvent> hitSound = SoundEvent.rewriteOptionalHolder(this.hitSound, Rewritable.soundRewriteFunction(protocol, clientbound));
|
||||
return sound == this.sound && hitSound == this.hitSound ? this : new KineticWeapon(contactCooldownTicks, delayTicks, dismountConditions, knockbackConditions, damageConditions, forwardMovement, damageMultiplier, sound, hitSound);
|
||||
}
|
||||
|
||||
public record Condition(int maxDurationTicks, float minSpeed, float minRelativeSpeed) {
|
||||
|
||||
public static final Type<Condition> TYPE = new Type<>(Condition.class) {
|
||||
|
||||
+11
-1
@@ -22,16 +22,19 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.item.data;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.Holder;
|
||||
import com.viaversion.viaversion.api.minecraft.SoundEvent;
|
||||
import com.viaversion.viaversion.api.minecraft.codec.Ops;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.util.Rewritable;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public record PiercingWeapon(boolean dealsKnockback, boolean dismounts,
|
||||
@Nullable Holder<SoundEvent> sound, @Nullable Holder<SoundEvent> hitSound) {
|
||||
@Nullable Holder<SoundEvent> sound, @Nullable Holder<SoundEvent> hitSound) implements Rewritable {
|
||||
|
||||
public static final Type<PiercingWeapon> TYPE = new Type<>(PiercingWeapon.class) {
|
||||
@Override
|
||||
@@ -61,4 +64,11 @@ public record PiercingWeapon(boolean dealsKnockback, boolean dismounts,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public PiercingWeapon rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
|
||||
final Holder<SoundEvent> sound = SoundEvent.rewriteOptionalHolder(this.sound, Rewritable.soundRewriteFunction(protocol, clientbound));
|
||||
final Holder<SoundEvent> hitSound = SoundEvent.rewriteOptionalHolder(this.hitSound, Rewritable.soundRewriteFunction(protocol, clientbound));
|
||||
return sound == this.sound && hitSound == this.hitSound ? this : new PiercingWeapon(dealsKnockback, dismounts, sound, hitSound);
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -89,7 +89,9 @@ public record Consumable1_21_2(float consumeSeconds, int animationType, Holder<S
|
||||
@Override
|
||||
public Consumable1_21_2 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
|
||||
final Holder<SoundEvent> soundHolder = SoundEvent.rewriteHolder(this.sound, Rewritable.soundRewriteFunction(protocol, clientbound));
|
||||
return soundHolder == this.sound ? this : new Consumable1_21_2(consumeSeconds, animationType, soundHolder, hasConsumeParticles, consumeEffects);
|
||||
final ConsumeEffect<?>[] consumeEffects = ConsumeEffect.rewrite(this.consumeEffects, connection, protocol, clientbound);
|
||||
return soundHolder == this.sound && consumeEffects == this.consumeEffects ? this
|
||||
: new Consumable1_21_2(consumeSeconds, animationType, soundHolder, hasConsumeParticles, consumeEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+30
-1
@@ -22,20 +22,23 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.item.data.consumable;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.data.MappingData;
|
||||
import com.viaversion.viaversion.api.minecraft.Holder;
|
||||
import com.viaversion.viaversion.api.minecraft.HolderSet;
|
||||
import com.viaversion.viaversion.api.minecraft.SoundEvent;
|
||||
import com.viaversion.viaversion.api.minecraft.codec.Ops;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.EnumTypes;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.ArrayType;
|
||||
import com.viaversion.viaversion.api.type.types.misc.HolderSetType;
|
||||
import com.viaversion.viaversion.api.type.types.misc.HolderType;
|
||||
import com.viaversion.viaversion.util.Rewritable;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public record ConsumeEffect<T>(int id, Type<T> type, T value) {
|
||||
public record ConsumeEffect<T>(int id, Type<T> type, T value) implements Rewritable {
|
||||
|
||||
private static final HolderSetType REMOVE_EFFECTS_TYPE = new HolderSetType() {
|
||||
@Override
|
||||
@@ -123,6 +126,32 @@ public record ConsumeEffect<T>(int id, Type<T> type, T value) {
|
||||
return new ConsumeEffect<>(id, type, (T) value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConsumeEffect<T> rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
|
||||
if (this.type != PLAY_SOUND_TYPE) {
|
||||
return this;
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
final Holder<SoundEvent> sound = (Holder<SoundEvent>) this.value;
|
||||
final Holder<SoundEvent> rewrittenSound = SoundEvent.rewriteHolder(sound, Rewritable.soundRewriteFunction(protocol, clientbound));
|
||||
return rewrittenSound == sound ? this : ConsumeEffect.of(this.id, this.type, rewrittenSound);
|
||||
}
|
||||
|
||||
public static ConsumeEffect<?>[] rewrite(final ConsumeEffect<?>[] effects, final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
|
||||
ConsumeEffect<?>[] rewrittenEffects = effects;
|
||||
for (int i = 0; i < effects.length; i++) {
|
||||
final ConsumeEffect<?> rewrittenEffect = effects[i].rewrite(connection, protocol, clientbound);
|
||||
if (rewrittenEffect != effects[i]) {
|
||||
if (rewrittenEffects == effects) {
|
||||
rewrittenEffects = effects.clone();
|
||||
}
|
||||
rewrittenEffects[i] = rewrittenEffect;
|
||||
}
|
||||
}
|
||||
return rewrittenEffects;
|
||||
}
|
||||
|
||||
void writeValue(final ByteBuf buf) {
|
||||
this.type.write(buf, this.value);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ public interface Rewritable {
|
||||
|
||||
static Int2IntFunction soundRewriteFunction(final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
|
||||
return protocol.getMappingData().getSoundMappings() == null ? Int2IntFunction.identity()
|
||||
: (clientbound ? protocol.getMappingData().getSoundMappings()::getNewId : protocol.getMappingData()::getOldSoundId);
|
||||
: (clientbound ? protocol.getMappingData().getSoundMappings()::getNewId : protocol.getMappingData().getSoundMappings().inverse()::getNewId);
|
||||
}
|
||||
|
||||
static Int2IntFunction entityRewriteFunction(final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
|
||||
|
||||
@@ -233,6 +233,7 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
callOnMappingDataLoaded(getEntityRewriter());
|
||||
callOnMappingDataLoaded(getItemRewriter());
|
||||
callOnMappingDataLoaded(getTagRewriter());
|
||||
callOnMappingDataLoaded(getBlockRewriter());
|
||||
}
|
||||
|
||||
private void callRegister(@Nullable Rewriter<?> rewriter) {
|
||||
|
||||
+15
-3
@@ -494,9 +494,12 @@ public class ItemPacketRewriter1_13 extends ItemRewriter<ClientboundPackets1_12_
|
||||
if (tag == null)
|
||||
item.setTag(tag = new CompoundTag());
|
||||
if (!tag.contains("EntityTag")) {
|
||||
CompoundTag entityTag = new CompoundTag();
|
||||
entityTag.put("id", new StringTag(eggEntityId.get()));
|
||||
tag.put("EntityTag", entityTag);
|
||||
tag.put("EntityTag", new CompoundTag());
|
||||
}
|
||||
// The id is removed from a remaining EntityTag in handleItemToClient
|
||||
CompoundTag entityTag = tag.getCompoundTag("EntityTag");
|
||||
if (entityTag != null && !entityTag.contains("id")) {
|
||||
entityTag.putString("id", eggEntityId.get());
|
||||
}
|
||||
} else {
|
||||
rawId = IdAndData.getId(oldId) << 16 | oldId & 0xF;
|
||||
@@ -548,6 +551,10 @@ public class ItemPacketRewriter1_13 extends ItemRewriter<ClientboundPackets1_12_
|
||||
if (patternsTag != null) {
|
||||
for (CompoundTag pattern : patternsTag) {
|
||||
NumberTag colorTag = pattern.getNumberTag("Color");
|
||||
if (colorTag == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pattern.putInt("Color", 15 - colorTag.asInt()); // Invert color id
|
||||
}
|
||||
}
|
||||
@@ -659,6 +666,11 @@ public class ItemPacketRewriter1_13 extends ItemRewriter<ClientboundPackets1_12_
|
||||
}
|
||||
tag.put("CanDestroy", newCanDestroy);
|
||||
}
|
||||
|
||||
// Damage, map and the original id are stored in a tag created in handleItemToClient
|
||||
if (tag.isEmpty()) {
|
||||
item.setTag(null);
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
+1
@@ -1552,6 +1552,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
|
||||
}
|
||||
}
|
||||
|
||||
tag.remove("Items");
|
||||
data.set(StructuredDataKey.V1_20_5.container, filteredItems);
|
||||
addBlockEntityId(tag, "shulker_box");
|
||||
}
|
||||
|
||||
+49
@@ -19,6 +19,7 @@ package com.viaversion.viaversion.protocols.v1_21_4to1_21_5.rewriter;
|
||||
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.IntTag;
|
||||
import com.viaversion.nbt.tag.ListTag;
|
||||
import com.viaversion.nbt.tag.LongArrayTag;
|
||||
import com.viaversion.nbt.tag.Tag;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
@@ -272,6 +273,7 @@ public final class BlockItemPacketRewriter1_21_5 extends StructuredItemRewriter<
|
||||
|
||||
final StructuredDataContainer dataContainer = item.dataContainer();
|
||||
updateItemDataComponentTypeIds(dataContainer, true);
|
||||
backupHiddenAttributeModifiers(item);
|
||||
handleRewritablesToClient(connection, dataContainer, null);
|
||||
|
||||
updateItemData(item);
|
||||
@@ -298,6 +300,53 @@ public final class BlockItemPacketRewriter1_21_5 extends StructuredItemRewriter<
|
||||
super.handleItemDataComponentsToServer(connection, item, container);
|
||||
}
|
||||
|
||||
private void backupHiddenAttributeModifiers(final Item item) {
|
||||
final AttributeModifiers1_21 attributeModifiers = item.dataContainer().get(StructuredDataKey.ATTRIBUTE_MODIFIERS1_21);
|
||||
if (attributeModifiers == null || attributeModifiers.showInTooltip()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ListTag<CompoundTag> modifiersTag = new ListTag<>(CompoundTag.class);
|
||||
for (final AttributeModifiers1_21.AttributeModifier modifier : attributeModifiers.modifiers()) {
|
||||
final CompoundTag modifierTag = new CompoundTag();
|
||||
modifierTag.putInt("attribute", modifier.attribute());
|
||||
modifierTag.putString("id", modifier.modifier().id());
|
||||
modifierTag.putDouble("amount", modifier.modifier().amount());
|
||||
modifierTag.putInt("operation", modifier.modifier().operation());
|
||||
modifierTag.putInt("slot", modifier.slotType());
|
||||
modifiersTag.add(modifierTag);
|
||||
}
|
||||
saveTag(createCustomTag(item), modifiersTag, "hidden_attribute_modifiers");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void restoreBackupData(final Item item, final StructuredDataContainer container, final CompoundTag customData) {
|
||||
super.restoreBackupData(item, container, customData);
|
||||
|
||||
final ListTag<CompoundTag> modifiersTag = customData.getListTag(nbtTagName("hidden_attribute_modifiers"), CompoundTag.class);
|
||||
if (modifiersTag == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
removeBackupTag(customData, "hidden_attribute_modifiers");
|
||||
if (container.has(StructuredDataKey.ATTRIBUTE_MODIFIERS1_21_5)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final AttributeModifiers1_21.AttributeModifier[] modifiers = new AttributeModifiers1_21.AttributeModifier[modifiersTag.size()];
|
||||
for (int i = 0; i < modifiers.length; i++) {
|
||||
final CompoundTag modifierTag = modifiersTag.get(i);
|
||||
final AttributeModifiers1_21.ModifierData modifierData = new AttributeModifiers1_21.ModifierData(
|
||||
modifierTag.getString("id"),
|
||||
modifierTag.getDouble("amount"),
|
||||
modifierTag.getInt("operation")
|
||||
);
|
||||
modifiers[i] = new AttributeModifiers1_21.AttributeModifier(modifierTag.getInt("attribute"), modifierData, modifierTag.getInt("slot"));
|
||||
}
|
||||
// Show state is applied from tooltip_display afterwards
|
||||
container.set(StructuredDataKey.ATTRIBUTE_MODIFIERS1_21_5, new AttributeModifiers1_21(modifiers, true));
|
||||
}
|
||||
|
||||
public static void updateItemData(final Item item) {
|
||||
final StructuredDataContainer dataContainer = item.dataContainer();
|
||||
dataContainer.replaceKey(StructuredDataKey.TOOL1_20_5, StructuredDataKey.TOOL1_21_5);
|
||||
|
||||
+17
-2
@@ -409,7 +409,10 @@ public class ItemPacketRewriter1_9 extends ItemRewriter<ClientboundPackets1_8, S
|
||||
if (tag == null) {
|
||||
tag = new CompoundTag();
|
||||
}
|
||||
CompoundTag entityTag = new CompoundTag();
|
||||
CompoundTag entityTag = tag.getCompoundTag("EntityTag");
|
||||
if (entityTag == null) {
|
||||
entityTag = new CompoundTag();
|
||||
}
|
||||
String entityName = EntityIds1_8.ENTITY_ID_TO_NAME.get((int) item.data());
|
||||
if (entityName != null) {
|
||||
StringTag id = new StringTag(entityName);
|
||||
@@ -493,7 +496,13 @@ public class ItemPacketRewriter1_9 extends ItemRewriter<ClientboundPackets1_8, S
|
||||
data = EntityIds1_8.ENTITY_NAME_TO_ID.get(id.getValue());
|
||||
}
|
||||
}
|
||||
tag.remove("EntityTag");
|
||||
entityTag.remove("id");
|
||||
if (entityTag.isEmpty()) {
|
||||
tag.remove("EntityTag");
|
||||
}
|
||||
}
|
||||
if (tag != null && tag.isEmpty()) {
|
||||
tag = null;
|
||||
}
|
||||
item.setTag(tag);
|
||||
item.setData((short) data);
|
||||
@@ -509,6 +518,9 @@ public class ItemPacketRewriter1_9 extends ItemRewriter<ClientboundPackets1_8, S
|
||||
}
|
||||
tag.remove("Potion");
|
||||
}
|
||||
if (tag != null && tag.isEmpty()) {
|
||||
tag = null;
|
||||
}
|
||||
item.setTag(tag);
|
||||
item.setData((short) data);
|
||||
}
|
||||
@@ -525,6 +537,9 @@ public class ItemPacketRewriter1_9 extends ItemRewriter<ClientboundPackets1_8, S
|
||||
}
|
||||
tag.remove("Potion");
|
||||
}
|
||||
if (tag != null && tag.isEmpty()) {
|
||||
tag = null;
|
||||
}
|
||||
item.setTag(tag);
|
||||
item.setData((short) data);
|
||||
}
|
||||
|
||||
+7
@@ -40,6 +40,7 @@ import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
|
||||
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
|
||||
import com.viaversion.viaversion.connection.ProtocolStorablesBase;
|
||||
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
|
||||
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPackets26_1;
|
||||
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ServerboundPacket26_1;
|
||||
@@ -58,6 +59,7 @@ import com.viaversion.viaversion.protocols.v26_2to26_3.rewriter.ComponentRewrite
|
||||
import com.viaversion.viaversion.protocols.v26_2to26_3.rewriter.EntityPacketRewriter26_3;
|
||||
import com.viaversion.viaversion.protocols.v26_2to26_3.rewriter.RecipeDisplayRewriter26_3;
|
||||
import com.viaversion.viaversion.protocols.v26_2to26_3.rewriter.RegistryDataRewriter26_3;
|
||||
import com.viaversion.viaversion.protocols.v26_2to26_3.storage.ProtocolStorables26_3;
|
||||
import com.viaversion.viaversion.rewriter.BlockRewriter;
|
||||
import com.viaversion.viaversion.rewriter.ParticleRewriter;
|
||||
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
|
||||
@@ -254,6 +256,11 @@ public final class Protocol26_2To26_3 extends AbstractProtocol<ClientboundPacket
|
||||
super.onMappingDataLoaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtocolStorablesBase createStorables() {
|
||||
return new ProtocolStorables26_3();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(final UserConnection connection) {
|
||||
addEntityTracker(connection);
|
||||
|
||||
+1
-1
@@ -299,7 +299,7 @@ public final class BlockItemPacketRewriter26_3 extends StructuredItemRewriter<Cl
|
||||
for (final Map.Entry<String, Tag> entry : mapDecorations.entrySet()) {
|
||||
final StringTag typeTag = ((CompoundTag) entry.getValue()).getStringTag("type");
|
||||
if (NEW_MAP_DECORATION_TYPES.contains(Key.stripMinecraftNamespace(typeTag.getValue()))) {
|
||||
typeTag.setValue("village_plains");
|
||||
typeTag.setValue("target_x");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+36
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.protocols.v26_2to26_3.rewriter;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.BlockPosition;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes26_3;
|
||||
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes26_3;
|
||||
@@ -30,6 +31,7 @@ import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ServerboundPack
|
||||
import com.viaversion.viaversion.protocols.v26_2to26_3.Protocol26_2To26_3;
|
||||
import com.viaversion.viaversion.protocols.v26_2to26_3.packet.ClientboundPackets26_3;
|
||||
import com.viaversion.viaversion.protocols.v26_2to26_3.packet.ServerboundPackets26_3;
|
||||
import com.viaversion.viaversion.protocols.v26_2to26_3.storage.ProtocolStorables26_3;
|
||||
import com.viaversion.viaversion.rewriter.EntityRewriter;
|
||||
|
||||
public final class EntityPacketRewriter26_3 extends EntityRewriter<ClientboundPacket26_1, Protocol26_2To26_3> {
|
||||
@@ -40,7 +42,12 @@ public final class EntityPacketRewriter26_3 extends EntityRewriter<ClientboundPa
|
||||
private static final int INTERPOLATION_STEP_TICKS = 3;
|
||||
private static final int MAIN_HAND = 0;
|
||||
private static final int OFF_HAND = 1;
|
||||
private static final int START_DESTROY_BLOCK_ACTION = 0;
|
||||
private static final int CHANGE_DESTROY_DIRECTION_ACTION = 1;
|
||||
private static final int ABORT_DESTROY_BLOCK_ACTION = 2;
|
||||
private static final int STOP_DESTROY_BLOCK_ACTION = 3;
|
||||
private static final int DESTROY_PROGRESS_PARTICLES = 2019;
|
||||
private static final int DESTROY_PROGRESS_PARTICLES_AND_SOUND = 2020;
|
||||
private static final SwingAnimation DEFAULT_SWING_ANIMATION = new SwingAnimation(EnumTypes.SWING_ANIMATION1_21_11.idFromName("whack"), 6);
|
||||
|
||||
public EntityPacketRewriter26_3(final Protocol26_2To26_3 protocol) {
|
||||
@@ -139,16 +146,45 @@ public final class EntityPacketRewriter26_3 extends EntityRewriter<ClientboundPa
|
||||
|
||||
protocol.registerServerbound(ServerboundPackets26_3.PUNCH, ServerboundPackets26_1.SWING, wrapper -> {
|
||||
wrapper.write(Types.VAR_INT, 0); // Main hand
|
||||
|
||||
// Sent every tick while destroying a block
|
||||
final ProtocolStorables26_3 storables = wrapper.user().storables(protocol);
|
||||
storables.setPunched();
|
||||
});
|
||||
|
||||
protocol.registerServerbound(ServerboundPackets26_3.CLIENT_TICK_END, wrapper -> {
|
||||
// Needs to be sent by the server every tick after starting now
|
||||
final ProtocolStorables26_3 storables = wrapper.user().storables(protocol);
|
||||
final int ticks = storables.endDestroyTick();
|
||||
if (ticks <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final PacketWrapper levelEvent = wrapper.create(ClientboundPackets26_3.LEVEL_EVENT);
|
||||
levelEvent.write(Types.INT, ticks % 4 == 0 ? DESTROY_PROGRESS_PARTICLES_AND_SOUND : DESTROY_PROGRESS_PARTICLES);
|
||||
levelEvent.write(Types.BLOCK_POSITION1_14, storables.destroyPosition());
|
||||
levelEvent.write(Types.INT, storables.destroyDirection());
|
||||
levelEvent.write(Types.BOOLEAN, false); // Global
|
||||
levelEvent.scheduleSend(Protocol26_2To26_3.class);
|
||||
});
|
||||
|
||||
protocol.registerServerbound(ServerboundPackets26_3.PLAYER_ACTION, wrapper -> {
|
||||
final int action = wrapper.read(Types.VAR_INT);
|
||||
final ProtocolStorables26_3 storables = wrapper.user().storables(protocol);
|
||||
if (action == CHANGE_DESTROY_DIRECTION_ACTION) {
|
||||
wrapper.read(Types.BLOCK_POSITION1_14); // Position
|
||||
storables.setDestroyDirection(wrapper.read(Types.UNSIGNED_BYTE));
|
||||
wrapper.cancel(); // 26.2 has no equivalent and never sends anything here
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper.write(Types.VAR_INT, action > CHANGE_DESTROY_DIRECTION_ACTION ? action - 1 : action);
|
||||
if (action == START_DESTROY_BLOCK_ACTION) {
|
||||
final BlockPosition position = wrapper.passthrough(Types.BLOCK_POSITION1_14);
|
||||
storables.startDestroying(position, wrapper.passthrough(Types.UNSIGNED_BYTE));
|
||||
} else if (action == ABORT_DESTROY_BLOCK_ACTION || action == STOP_DESTROY_BLOCK_ACTION) {
|
||||
storables.stopDestroying();
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets26_1.ANIMATE, wrapper -> {
|
||||
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 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.v26_2to26_3.storage;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.BlockPosition;
|
||||
import com.viaversion.viaversion.connection.ProtocolStorablesBase;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public final class ProtocolStorables26_3 extends ProtocolStorablesBase {
|
||||
|
||||
private BlockPosition destroyPosition;
|
||||
private short destroyDirection;
|
||||
private int destroyTicks;
|
||||
private boolean punched;
|
||||
|
||||
public @Nullable BlockPosition destroyPosition() {
|
||||
return destroyPosition;
|
||||
}
|
||||
|
||||
public int destroyDirection() {
|
||||
return destroyDirection;
|
||||
}
|
||||
|
||||
public void setDestroyDirection(final short destroyDirection) {
|
||||
this.destroyDirection = destroyDirection;
|
||||
}
|
||||
|
||||
public void startDestroying(final BlockPosition position, final short direction) {
|
||||
this.destroyPosition = position;
|
||||
this.destroyDirection = direction;
|
||||
this.destroyTicks = 0;
|
||||
this.punched = false;
|
||||
}
|
||||
|
||||
public void stopDestroying() {
|
||||
this.destroyPosition = null;
|
||||
}
|
||||
|
||||
public void setPunched() {
|
||||
this.punched = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the destroy tick that just ended, or -1 if the client did not continue destroying in it.
|
||||
*
|
||||
* @return destroy tick that just ended, or -1
|
||||
*/
|
||||
public int endDestroyTick() {
|
||||
if (destroyPosition == null) {
|
||||
return -1;
|
||||
}
|
||||
if (!punched) {
|
||||
destroyPosition = null;
|
||||
return -1;
|
||||
}
|
||||
|
||||
punched = false;
|
||||
return destroyTicks++;
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.rewriter.MappingDataListener;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.util.MathUtil;
|
||||
@@ -44,7 +45,7 @@ import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class BlockRewriter<C extends ClientboundPacketType> {
|
||||
public class BlockRewriter<C extends ClientboundPacketType> implements MappingDataListener {
|
||||
protected final Protocol<C, ?, ?, ?> protocol;
|
||||
private final Type<BlockPosition> positionType;
|
||||
private final Type<CompoundTag> compoundTagType;
|
||||
|
||||
@@ -423,11 +423,11 @@ public class StructuredItemRewriter<C extends ClientboundPacketType, S extends S
|
||||
if (customName != null) {
|
||||
container.set(StructuredDataKey.CUSTOM_NAME, customName);
|
||||
}
|
||||
}
|
||||
|
||||
final Tag itemName = removeBackupTag(customData, "item_name");
|
||||
if (itemName != null) {
|
||||
container.set(StructuredDataKey.ITEM_NAME, itemName);
|
||||
}
|
||||
final Tag itemName = removeBackupTag(customData, "item_name");
|
||||
if (itemName != null) {
|
||||
container.set(StructuredDataKey.ITEM_NAME, itemName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+40
-6
@@ -29,6 +29,11 @@ import com.viaversion.viaversion.rewriter.BlockRewriter;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class BlockRewriter1_21_5<C extends ClientboundPacketType> extends BlockRewriter<C> {
|
||||
private int signId = -1;
|
||||
private int hangingSignId = -1;
|
||||
private int shelfId = -1;
|
||||
private int campfireId = -1;
|
||||
private int vaultId = -1;
|
||||
|
||||
public BlockRewriter1_21_5(final Protocol<C, ?, ?, ?> protocol, final ChunkTypeSupplier chunkTypeSupplier, @Nullable final ChunkTypeSupplier mappedChunkTypeSupplier) {
|
||||
super(protocol, Types.BLOCK_POSITION1_14, Types.TRUSTED_COMPOUND_TAG, chunkTypeSupplier, mappedChunkTypeSupplier);
|
||||
@@ -41,17 +46,46 @@ public class BlockRewriter1_21_5<C extends ClientboundPacketType> extends BlockR
|
||||
@Override
|
||||
public void handleBlockEntity(final UserConnection connection, final BlockEntity blockEntity) {
|
||||
final CompoundTag tag = blockEntity.tag();
|
||||
if (tag == null) {
|
||||
if (tag == null || protocol.getComponentRewriter() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final FullMappings blockEntityMappings = protocol.getMappingData().getBlockEntityMappings();
|
||||
if (blockEntityMappings != null && protocol.getComponentRewriter() != null) {
|
||||
final int typeId = blockEntity.typeId();
|
||||
if (typeId == signId || typeId == hangingSignId) {
|
||||
// Update sign text components, relevant as of 1.21.5 given they are properly parsed and should not error on the client
|
||||
if (blockEntity.typeId() == blockEntityMappings.mappedId("sign") || blockEntity.typeId() == blockEntityMappings.mappedId("hanging_sign")) {
|
||||
updateSignMessages(connection, tag.getCompoundTag("front_text"));
|
||||
updateSignMessages(connection, tag.getCompoundTag("back_text"));
|
||||
updateSignMessages(connection, tag.getCompoundTag("front_text"));
|
||||
updateSignMessages(connection, tag.getCompoundTag("back_text"));
|
||||
} else if (typeId == shelfId || typeId == campfireId) {
|
||||
// Update items that are actually visible to the client
|
||||
final ListTag<CompoundTag> items = tag.getListTag("Items", CompoundTag.class);
|
||||
if (items != null) {
|
||||
for (final CompoundTag item : items) {
|
||||
updateItem(connection, item);
|
||||
}
|
||||
}
|
||||
} else if (typeId == vaultId) {
|
||||
final CompoundTag sharedData = tag.getCompoundTag("shared_data");
|
||||
if (sharedData != null) {
|
||||
updateItem(connection, sharedData.getCompoundTag("display_item"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMappingDataLoaded() {
|
||||
final FullMappings blockEntityMappings = protocol.getMappingData() != null ? protocol.getMappingData().getBlockEntityMappings() : null;
|
||||
if (blockEntityMappings != null) {
|
||||
signId = blockEntityMappings.mappedId("sign");
|
||||
hangingSignId = blockEntityMappings.mappedId("hanging_sign");
|
||||
shelfId = blockEntityMappings.mappedId("shelf");
|
||||
campfireId = blockEntityMappings.mappedId("campfire");
|
||||
vaultId = blockEntityMappings.mappedId("vault");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateItem(final UserConnection connection, @Nullable final CompoundTag item) {
|
||||
if (item != null && item.getStringTag("id") != null) {
|
||||
protocol.getComponentRewriter().handleShowItem(connection, item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
# Project properties - we put these here so they can be modified without causing a recompile of the build scripts
|
||||
projectVersion=5.12.1
|
||||
projectVersion=5.12.2-SNAPSHOT
|
||||
|
||||
# Smile emoji (note that modrinth may not have added the version on release yet)
|
||||
mcVersions=26.3, 26.2, 26.1.2, 26.1.1, 26.1, 1.21.11, 1.21.10, 1.21.9, 1.21.8, 1.21.7, 1.21.6, 1.21.5, 1.21.4, 1.21.3, 1.21.2, 1.21.1, 1.21, 1.20.6, 1.20.5, 1.20.4, 1.20.3, 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
|
||||
|
||||
Reference in new issue
Block a user