Compare commits

...
35 Commits
Author SHA1 Message Date
NotAlexNoyle 4bbcf6511f Exclude CODEOWNERS from language statistics 2026-10-28 08:31:40 -04:00
NotAlexNoyle c33be26ef2 Add CODEOWNERS (one staff approval) 2026-10-28 08:31:40 -04:00
NotAlexNoyle b50d3bb759 Fix 1.8 combat packet handling 2026-08-09 14:35:28 -04:00
NotAlexNoyle 2dc6ac8c02 Update setting for TAB-OG 2026-07-12 16:54:33 -04:00
NotAlexNoyle c56b44d826 Fix raid messages for legacy clients 2026-06-17 13:02:42 -04:00
NotAlexNoyle bb282dce6b Merge branch 'ViaVersion:master' into master 2026-06-17 12:52:28 -04:00
Florian Reuth 59abf8bd18 Fix tag updating in 1.21.6->1.21.5 (#1277) 2026-06-15 11:17:05 +02:00
Term4 33d3b1db9c Round instead of truncating in toLegacyVelocity (#1272) 2026-06-12 17:28:11 +02:00
Nassim Jahnke 5255394ed6 Track mid-game spectator gamemode change in 26.1->1.21.11
Fixes #1267
2026-06-07 12:49:00 +02:00
Nassim Jahnke c5713f915d Move velocity explosion packet out of bounds in 1.21.2->1.21 2026-06-07 12:37:08 +02:00
NotAlexNoyle 00a0db26e3 TrueOG fork patches
Cumulative customizations on top of upstream ViaBackwards master:
- build.gradle.kts: enable Eclipse gradle plugin
- common/.../config.yml: TrueOG network production config,
  inventory title tweak for 1.8 clients

Squashes: Add eclipse library to build.gradle.kts (ee65f8a6),
Use live TrueOG Network config file (f6f2486c), Try to fix
inventory titles on 1.8 (50194b4d), Bee anger field iterations
(06ff7bc5, b3da4f1c), Fix packets (3cc57bfe).
2026-06-05 12:29:03 -04:00
Nassim Jahnke e651e1cef9 Update VV usage 2026-05-25 09:33:52 +02:00
Gubis Zsombor Dániel c3f6271a0d Fix NPE in BlockRewriter1_20_2 when block entity has null tag (#1262) 2026-05-19 10:21:03 +02:00
RK_01 1508cd2820 [ci skip] Remove redundant types (#1259) 2026-05-08 19:07:16 +02:00
Nassim Jahnke bc7f3607c6 Track gamemode in 1.20.5 protocol 2026-05-08 19:05:55 +02:00
Nassim Jahnke 95d53b7f01 5.9.1 Release 2026-05-04 20:31:09 +02:00
Nassim Jahnke c4ac1b0560 Add hashed item shortcut in 1.21.5->1.21.4 2026-05-03 16:00:40 +02:00
Nassim Jahnke 8ee6391ff9 Remove ChunkLightStorage reflection 2026-05-03 12:21:56 +02:00
Florian Reuth 7700afb479 Move configuration state tracking into shared registrations (#1249) 2026-05-02 09:49:45 +02:00
Nassim Jahnke 5361c019f2 Fix shouldered parrot tracking in 1.21.9->1.21.7
Fixes #1257
2026-04-27 15:50:53 +02:00
Nassim Jahnke 041f7f933b Fix toggled advance_time handling
Fixes #1256
2026-04-27 15:40:18 +02:00
Kichura 48ad4e4aa3 [ci skip] Update action files (#1253) 2026-04-26 16:19:27 +02:00
Nassim Jahnke 358288f8f7 [ci skip] Add agents.md file 2026-04-26 16:16:51 +02:00
Beanes e46cf56e52 Cancel non-player bed sleep data in 1.14->1.13 (#1252) 2026-04-22 20:03:45 +02:00
BT ab9d1d26f3 Use TagRewriter in 1.14->1.13.2 (#1251) 2026-04-21 10:58:10 +02:00
Nassim Jahnke 65b2c30c7e Remove copper golem data in 1.21.9->1.21.7 2026-04-21 10:51:56 +02:00
Nassim Jahnke 9af3076c54 5.9.0 Release 2026-04-19 15:39:12 +02:00
Nassim Jahnke 4c75ea98f1 Update mapping files
Includes https://github.com/ViaVersion/Mappings/commit/c933b2799c6ad68be4977330899d5d3f3ab140e8 and https://github.com/ViaVersion/Mappings/commit/feed902814fc7c450a93015e44db549c0f15c551
2026-04-18 13:36:48 +02:00
Niko 5194c27e4c Fix skull owner with multiple properties of the same key in 1.20.5->1.20.3 (#1248) 2026-04-17 22:34:54 +02:00
Nassim Jahnke c887ab740b Improve 1.12 keep_alive handling
Fixes handling of batches of keep alives and the technically possible collisions
2026-04-16 16:51:56 +02:00
Jobs 63afb2d063 Fix inventory desync for <1.17 clients on 1.17+ servers (#1243) 2026-04-10 15:19:56 +02:00
riku6460 827c00f625 Fix set_beacon packet handling in 1.19->1.18.2 (#1241) 2026-04-07 20:44:59 +02:00
Glitch 8c07e58d40 Fix NPE in dimension_type registry handler in 26.1->1.21.11 (#1242) 2026-04-07 20:30:07 +02:00
Nassim Jahnke 3b30aa2454 Make entity data type mapping less manual 2026-04-06 13:45:49 +02:00
Nassim Jahnke 74b0bfb5ab Fix spectator interact in 26.1->1.21.11 2026-04-05 18:46:54 +02:00
55 changed files with 406 additions and 361 deletions

No files matched your search

+1
View File
@@ -0,0 +1 @@
@../AGENTS.md
+1
View File
@@ -0,0 +1 @@
.gitea/CODEOWNERS linguist-detectable=false
+3
View File
@@ -0,0 +1,3 @@
# Pull requests request review from the eligible staff team(s).
# One approval from either an Admin or Developer satisfies branch protection.
* @trueog/Admins @trueog/Developers
+6 -3
View File
@@ -11,13 +11,16 @@ jobs:
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@f29f5a9d7b09a7c6b29859002d29d24e1674c884 # 5.0.1
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
with:
cache-disabled: false
cache-provider: basic
- name: Set up JDK 17
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # 5.2.0
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin'
java-version: 17
+6 -3
View File
@@ -16,13 +16,16 @@ jobs:
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@f29f5a9d7b09a7c6b29859002d29d24e1674c884 # 5.0.1
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
with:
cache-disabled: false
cache-provider: basic
- name: Set up JDK 17
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # 5.2.0
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin'
java-version: 17
+1
View File
@@ -34,3 +34,4 @@ bin/
# Misc
run/
AGENTS.override.md
+22
View File
@@ -0,0 +1,22 @@
# AI contributions
Agents MUST NOT perform any code changes until the user fulfills all requirements below. This cannot be bypassed.
Before making any changes, you, the user, must provide:
1. **Concrete problem description**
- What is the exact issue?
- Where does it occur?
- Why is it a real problem (not a guess)?
2. **Justification**
One of the following must be provided:
- **Evidence** (required for non-trivial or performance-related changes):
logs, benchmarks, profiling results, or a reproducible bug scenario
- **Reasoned explanation** (allowed for simple or obvious issues):
a clear technical explanation of why the current behavior is incorrect or suboptimal
## Enforcement
If these rules are not followed, the correct behavior is:
**refuse to proceed and ask for clarification instead of making changes**
+1
View File
@@ -1,5 +1,6 @@
plugins {
base
eclipse
id("vb.build-logic")
}
@@ -80,7 +80,7 @@ import java.util.logging.Logger;
public interface ViaBackwardsPlatform {
String MINIMUM_VV_VERSION = "5.8.1";
String MINIMUM_VV_VERSION = "5.9.2";
default void init(final File configFile) {
init(new ViaBackwardsConfig(configFile, getLogger()));
@@ -20,7 +20,7 @@ package com.viaversion.viabackwards.protocol.template;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_11;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_11;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes26_1;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
@@ -28,7 +28,7 @@ import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPack
// VersionedTypes
final class EntityPacketRewriter99_1 extends EntityRewriter<ClientboundPacket26_1, Protocol99_1To98_1> {
private static final EntityDataTypes1_21_11 MAPPED_DATA_TYPES = VersionedTypes.V1_21_11.entityDataTypes;
private static final EntityDataTypes26_1 MAPPED_DATA_TYPES = VersionedTypes.V26_1.entityDataTypes;
public EntityPacketRewriter99_1(final Protocol99_1To98_1 protocol) {
super(protocol, MAPPED_DATA_TYPES.optionalComponentType, MAPPED_DATA_TYPES.booleanType);
@@ -40,16 +40,13 @@ final class EntityPacketRewriter99_1 extends EntityRewriter<ClientboundPacket26_
@Override
protected void registerRewrites() {
/*filter().handler((event, data) -> {
int id = data.dataType().typeId();
if (id >= ac) {
return;
} else if (id >= ab) {
id--;
}
data.setDataType(MAPPED_DATA_TYPES.byId(id));
});*/
dataTypeMapper().register();
/* ... or like this for additions and removals that are not at the very end
dataTypeMapper()
.added(MAPPED_DATA_TYPES.catSoundVariant)
.removed(MAPPED_DATA_TYPES.cowSoundVariant)
.skip(MAPPED_DATA_TYPES.pigSoundVariant) // if neither removed nor added, but the value type has to be changed separately
.register();*/
registerEntityDataTypeHandler1_20_3(
MAPPED_DATA_TYPES.itemType,
@@ -80,7 +80,7 @@ final class Protocol99_1To98_1 extends BackwardsProtocol<ClientboundPacket26_1,
@Override
public void init(final UserConnection connection) {
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_21_11.PLAYER));
addItemHasher(connection, new ItemHasherBase(this, connection));
connection.addItemHasher(this.getClass(), new ItemHasherBase(this, connection));
}
@Override
@@ -21,7 +21,6 @@ package com.viaversion.viabackwards.protocol.v1_12_2to1_12_1;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.protocol.v1_12_2to1_12_1.storage.KeepAliveTracker;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_12to1_12_1.packet.ClientboundPackets1_12_1;
import com.viaversion.viaversion.protocols.v1_12to1_12_1.packet.ServerboundPackets1_12_1;
@@ -34,32 +33,20 @@ public class Protocol1_12_2To1_12_1 extends BackwardsProtocol<ClientboundPackets
@Override
protected void registerPackets() {
registerClientbound(ClientboundPackets1_12_1.KEEP_ALIVE, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
Long keepAlive = packetWrapper.read(Types.LONG);
packetWrapper.user().get(KeepAliveTracker.class).setKeepAlive(keepAlive);
packetWrapper.write(Types.VAR_INT, keepAlive.hashCode());
});
}
registerClientbound(ClientboundPackets1_12_1.KEEP_ALIVE, wrapper -> {
long keepAlive = wrapper.read(Types.LONG);
int id = wrapper.user().get(KeepAliveTracker.class).track(keepAlive);
wrapper.write(Types.VAR_INT, id);
});
registerServerbound(ServerboundPackets1_12_1.KEEP_ALIVE, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int keepAlive = packetWrapper.read(Types.VAR_INT);
long realKeepAlive = packetWrapper.user().get(KeepAliveTracker.class).getKeepAlive();
if (keepAlive != Long.hashCode(realKeepAlive)) {
packetWrapper.cancel(); // Wrong data, cancel packet
return;
}
packetWrapper.write(Types.LONG, realKeepAlive);
// Reset KeepAliveTracker (to prevent sending same valid value in a row causing a timeout)
packetWrapper.user().get(KeepAliveTracker.class).setKeepAlive(Integer.MAX_VALUE);
});
registerServerbound(ServerboundPackets1_12_1.KEEP_ALIVE, wrapper -> {
int keepAlive = wrapper.read(Types.VAR_INT);
Long realKeepAlive = wrapper.user().get(KeepAliveTracker.class).consume(keepAlive);
if (realKeepAlive == null) {
wrapper.cancel(); // stale/bad
return;
}
wrapper.write(Types.LONG, realKeepAlive);
});
}
@@ -19,20 +19,22 @@
package com.viaversion.viabackwards.protocol.v1_12_2to1_12_1.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import java.util.HashMap;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
public class KeepAliveTracker implements StorableObject {
private long keepAlive = Integer.MAX_VALUE;
public long getKeepAlive() {
return keepAlive;
private final Map<Integer, Long> pending = new HashMap<>();
private int nextId;
public int track(long original) {
int id = nextId++;
pending.put(id, original);
return id;
}
public void setKeepAlive(long keepAlive) {
this.keepAlive = keepAlive;
}
@Override
public String toString() {
return "KeepAliveTracker{" + "keepAlive=" + keepAlive + '}';
public @Nullable Long consume(int id) {
return pending.remove(id);
}
}
@@ -30,6 +30,7 @@ import com.viaversion.viabackwards.protocol.v1_14to1_13_2.storage.ChunkLightStor
import com.viaversion.viabackwards.protocol.v1_14to1_13_2.storage.DifficultyStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_14;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
@@ -39,6 +40,7 @@ import com.viaversion.viaversion.protocols.v1_13_2to1_14.packet.ClientboundPacke
import com.viaversion.viaversion.protocols.v1_13_2to1_14.packet.ServerboundPackets1_14;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.rewriter.text.ComponentRewriterBase;
public class Protocol1_14To1_13_2 extends BackwardsProtocol<ClientboundPackets1_14, ClientboundPackets1_13, ServerboundPackets1_14, ServerboundPackets1_13> {
@@ -49,6 +51,7 @@ public class Protocol1_14To1_13_2 extends BackwardsProtocol<ClientboundPackets1_
private final BlockRewriter<ClientboundPackets1_14> blockRewriter = BlockRewriter.legacy(this);
private final ParticleRewriter<ClientboundPackets1_14> particleRewriter = new ParticleRewriter<>(this);
private final JsonNBTComponentRewriter<ClientboundPackets1_14> translatableRewriter = new JsonNBTComponentRewriter<>(this, ComponentRewriterBase.ReadType.JSON);
private final TagRewriter<ClientboundPackets1_14> tagRewriter = new TagRewriter<>(this);
public Protocol1_14To1_13_2() {
super(ClientboundPackets1_14.class, ClientboundPackets1_13.class, ServerboundPackets1_14.class, ServerboundPackets1_13.class);
@@ -66,35 +69,9 @@ public class Protocol1_14To1_13_2 extends BackwardsProtocol<ClientboundPackets1_
cancelClientbound(ClientboundPackets1_14.SET_CHUNK_CACHE_RADIUS);
registerClientbound(ClientboundPackets1_14.UPDATE_TAGS, wrapper -> {
int blockTagsSize = wrapper.passthrough(Types.VAR_INT);
for (int i = 0; i < blockTagsSize; i++) {
wrapper.passthrough(Types.STRING);
int[] blockIds = wrapper.passthrough(Types.VAR_INT_ARRAY_PRIMITIVE);
for (int j = 0; j < blockIds.length; j++) {
int id = blockIds[j];
// Ignore new blocktags
int blockId = MAPPINGS.getNewBlockId(id);
blockIds[j] = blockId;
}
}
int itemTagsSize = wrapper.passthrough(Types.VAR_INT);
for (int i = 0; i < itemTagsSize; i++) {
wrapper.passthrough(Types.STRING);
int[] itemIds = wrapper.passthrough(Types.VAR_INT_ARRAY_PRIMITIVE);
for (int j = 0; j < itemIds.length; j++) {
int itemId = itemIds[j];
// Ignore new itemtags
int oldId = MAPPINGS.getItemMappings().getNewId(itemId);
itemIds[j] = oldId;
}
}
int fluidTagsSize = wrapper.passthrough(Types.VAR_INT); // fluid tags
for (int i = 0; i < fluidTagsSize; i++) {
wrapper.passthrough(Types.STRING);
wrapper.passthrough(Types.VAR_INT_ARRAY_PRIMITIVE);
}
tagRewriter.handle(wrapper, RegistryType.BLOCK);
tagRewriter.handle(wrapper, RegistryType.ITEM);
tagRewriter.handle(wrapper, RegistryType.FLUID);
// Eat entity tags
int entityTagsSize = wrapper.read(Types.VAR_INT);
@@ -194,4 +171,9 @@ public class Protocol1_14To1_13_2 extends BackwardsProtocol<ClientboundPackets1_
public JsonNBTComponentRewriter<ClientboundPackets1_14> getComponentRewriter() {
return translatableRewriter;
}
@Override
public TagRewriter<ClientboundPackets1_14> getTagRewriter() {
return tagRewriter;
}
}
@@ -450,15 +450,13 @@ public class EntityPacketRewriter1_14 extends LegacyEntityRewriter<ClientboundPa
if (index == 12) {
BlockPosition position = (BlockPosition) data.getValue();
if (position != null) {
// Use bed
PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_13.PLAYER_SLEEP, null, event.user());
wrapper.write(Types.VAR_INT, event.entityId());
wrapper.write(Types.BLOCK_POSITION1_8, position);
// Only players can sleep in 1.13
if (event.entityType() == EntityTypes1_14.PLAYER) {
PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_13.PLAYER_SLEEP, null, event.user());
wrapper.write(Types.VAR_INT, event.entityId());
wrapper.write(Types.BLOCK_POSITION1_8, position);
try {
wrapper.scheduleSend(Protocol1_14To1_13_2.class);
} catch (Exception ex) {
ex.printStackTrace();
}
}
@@ -18,26 +18,19 @@
package com.viaversion.viabackwards.protocol.v1_14to1_13_2.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import com.viaversion.viaversion.libs.fastutil.longs.Long2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class ChunkLightStorage implements StorableObject {
public static final byte[] FULL_LIGHT = new byte[2048];
public static final byte[] EMPTY_LIGHT = new byte[2048];
private static Constructor<?> fastUtilLongObjectHashMap;
private final Map<Long, ChunkLight> storedLight = createLongObjectMap();
private final Long2ObjectMap<ChunkLight> storedLight = new Long2ObjectOpenHashMap<>();
static {
Arrays.fill(FULL_LIGHT, (byte) 0xFF);
Arrays.fill(EMPTY_LIGHT, (byte) 0x0);
try {
fastUtilLongObjectHashMap = Class.forName("it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap").getConstructor();
} catch (ClassNotFoundException | NoSuchMethodException ignored) {
}
}
public void setStoredLight(byte[][] skyLight, byte[][] blockLight, int x, int z) {
@@ -60,17 +53,6 @@ public class ChunkLightStorage implements StorableObject {
return ((x & 0x3FFFFFFL) << 38) | (z & 0x3FFFFFFL);
}
private Map<Long, ChunkLight> createLongObjectMap() {
if (fastUtilLongObjectHashMap != null) {
try {
return (Map<Long, ChunkLight>) fastUtilLongObjectHashMap.newInstance();
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
e.printStackTrace();
}
}
return new HashMap<>();
}
public record ChunkLight(byte[][] skyLight, byte[][] blockLight) {
@Override
@@ -71,7 +71,7 @@ public final class Protocol1_17_1To1_17 extends BackwardsProtocol<ClientboundPac
// Length is encoded as a var int in 1.17.1
wrapper.write(Types.ITEM1_13_2_SHORT_ARRAY, wrapper.read(Types.ITEM1_13_2_ARRAY));
// Carried item - should work without adding it to the array above
// Carried item - forward as CONTAINER_SET_SLOT for <1.17 clients
Item carried = wrapper.read(Types.ITEM1_13_2);
PlayerLastCursorItem lastCursorItem = wrapper.user().get(PlayerLastCursorItem.class);
@@ -82,6 +82,16 @@ public final class Protocol1_17_1To1_17 extends BackwardsProtocol<ClientboundPac
// for a subsequent drag
lastCursorItem.setLastCursorItem(carried);
// In 1.17.1+, the carried/cursor item is part of CONTAINER_SET_CONTENT,
// but <1.17 clients don't have this field. Send it as a separate
// CONTAINER_SET_SLOT packet so the client's cursor state is properly synced.
// This fixes inventory desyncs when the server cancels InventoryClickEvents.
PacketWrapper cursorPacket = wrapper.create(ClientboundPackets1_17.CONTAINER_SET_SLOT);
cursorPacket.write(Types.BYTE, (byte) -1); // Window ID: -1 for cursor
cursorPacket.write(Types.SHORT, (short) -1); // Slot: -1 for cursor
cursorPacket.write(Types.ITEM1_13_2, carried);
cursorPacket.send(Protocol1_17_1To1_17.class);
}
});
@@ -26,6 +26,7 @@ import com.viaversion.viabackwards.api.rewriters.BackwardsItemRewriter;
import com.viaversion.viabackwards.api.rewriters.MapColorRewriter;
import com.viaversion.viabackwards.protocol.v1_17to1_16_4.Protocol1_17To1_16_4;
import com.viaversion.viabackwards.protocol.v1_17to1_16_4.data.MapColorMappings1_16_4;
import com.viaversion.viabackwards.protocol.v1_17_1to1_17.storage.InventoryStateIds;
import com.viaversion.viabackwards.protocol.v1_17to1_16_4.storage.PlayerLastCursorItem;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
@@ -83,8 +84,26 @@ public final class BlockItemPacketRewriter1_17 extends BackwardsItemRewriter<Cli
int mode = wrapper.passthrough(Types.VAR_INT); // Mode
Item clicked = handleItemToServer(wrapper.user(), wrapper.read(Types.ITEM1_13_2)); // Clicked item
// The 1.17 client would check the entire inventory for changes before -> after a click and send the changed slots here
wrapper.write(Types.VAR_INT, 0); // Empty array of slot+item
// The 1.17 client would check the entire inventory for changes before -> after a click
// and send the changed slots here. We include the clicked slot so the server
// detects any desync (e.g. cancelled InventoryClickEvent) and sends corrections.
if (slot >= 0 && clicked != null) {
wrapper.write(Types.VAR_INT, 1); // One modified slot
wrapper.write(Types.SHORT, slot); // The clicked slot
wrapper.write(Types.ITEM1_13_2, (Item) null); // Predicted: empty (item picked up)
} else {
wrapper.write(Types.VAR_INT, 0); // Empty array of slot+item
}
// Non-PICKUP modes (shift-click, swap, throw, drag, etc.) affect multiple slots
// that we can't easily predict. Force a state ID mismatch so the server
// sends a full inventory resync instead of individual slot corrections.
if (mode != 0) {
InventoryStateIds stateIds = wrapper.user().get(InventoryStateIds.class);
if (stateIds != null) {
stateIds.setStateId(wrapper.get(Types.BYTE, 0), -1);
}
}
PlayerLastCursorItem state = wrapper.user().get(PlayerLastCursorItem.class);
if (mode == 0 && button == 0 && clicked != null) {
@@ -70,8 +70,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public final class Protocol1_19_3To1_19_1 extends BackwardsProtocol<ClientboundPackets1_19_3, ClientboundPackets1_19_1, ServerboundPackets1_19_3, ServerboundPackets1_19_1> {
public static final BackwardsMappingData MAPPINGS = new BackwardsMappingData("1.19.3", "1.19", Protocol1_19_1To1_19_3.class);
public static final ByteArrayType.OptionalByteArrayType OPTIONAL_SIGNATURE_BYTES_TYPE = new ByteArrayType.OptionalByteArrayType(256);
public static final ByteArrayType SIGNATURE_BYTES_TYPE = new ByteArrayType(256);
private final EntityPacketRewriter1_19_3 entityRewriter = new EntityPacketRewriter1_19_3(this);
private final BlockItemPacketRewriter1_19_3 itemRewriter = new BlockItemPacketRewriter1_19_3(this);
private final ParticleRewriter<ClientboundPackets1_19_3> particleRewriter = new ParticleRewriter<>(this);
@@ -227,9 +225,9 @@ public final class Protocol1_19_3To1_19_1 extends BackwardsProtocol<ClientboundP
throw new RuntimeException(e);
}
wrapper.write(Protocol1_19_3To1_19_1.OPTIONAL_SIGNATURE_BYTES_TYPE, signature); // Signature
wrapper.write(Types.OPTIONAL_SIGNATURE_BYTES, signature); // Signature
} else {
wrapper.write(Protocol1_19_3To1_19_1.OPTIONAL_SIGNATURE_BYTES_TYPE, null); // Signature
wrapper.write(Types.OPTIONAL_SIGNATURE_BYTES, null); // Signature
}
//TODO is this fine (probably not)? same for chat_command
@@ -273,7 +271,7 @@ public final class Protocol1_19_3To1_19_1 extends BackwardsProtocol<ClientboundP
}
wrapper.write(Types.STRING, argument.key());
wrapper.write(Protocol1_19_3To1_19_1.SIGNATURE_BYTES_TYPE, signature);
wrapper.write(Types.SIGNATURE_BYTES, signature);
}
} else {
wrapper.write(Types.VAR_INT, 0); // No signatures
@@ -293,7 +291,7 @@ public final class Protocol1_19_3To1_19_1 extends BackwardsProtocol<ClientboundP
public void register() {
read(Types.UUID); // Sender
read(Types.VAR_INT); // Index
read(OPTIONAL_SIGNATURE_BYTES_TYPE); // Signature
read(Types.OPTIONAL_SIGNATURE_BYTES); // Signature
handler(wrapper -> {
final String plainContent = wrapper.read(Types.STRING);
wrapper.read(Types.LONG); // Timestamp
@@ -302,7 +300,7 @@ public final class Protocol1_19_3To1_19_1 extends BackwardsProtocol<ClientboundP
for (int i = 0; i < lastSeen; i++) {
final int index = wrapper.read(Types.VAR_INT);
if (index == 0) {
wrapper.read(SIGNATURE_BYTES_TYPE);
wrapper.read(Types.SIGNATURE_BYTES);
}
}
@@ -165,14 +165,10 @@ public final class EntityPacketRewriter1_19_4 extends EntityRewriter<Clientbound
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.HURT_ANIMATION, ClientboundPackets1_19_3.ANIMATE, new PacketHandlers() {
@Override
public void register() {
map(Types.VAR_INT); // Entity id
read(Types.FLOAT); // Yaw
create(Types.UNSIGNED_BYTE, (short) 1); // Hit
}
});
// The damage event above already maps to entity status 2, a superset of animate 1 on all
// 1.8-1.19.3 clients; forwarding both re-flashes the hurt when latency splits the pair.
// Cancelling restores pre-1.19.4 wire parity but drops plugin-sent standalone hurt animations.
protocol.cancelClientbound(ClientboundPackets1_19_4.HURT_ANIMATION);
protocol.registerClientbound(ClientboundPackets1_19_4.RESPAWN, new PacketHandlers() {
@Override
@@ -159,7 +159,7 @@ public final class BlockItemPacketRewriter1_19 extends BackwardsItemRewriter<Cli
protocol.registerServerbound(ServerboundPackets1_17.SET_BEACON, wrapper -> {
final int primaryEffect = wrapper.read(Types.VAR_INT);
if (primaryEffect != -1) {
if (primaryEffect > 0) {
wrapper.write(Types.BOOLEAN, true);
wrapper.write(Types.VAR_INT, primaryEffect);
} else {
@@ -167,7 +167,7 @@ public final class BlockItemPacketRewriter1_19 extends BackwardsItemRewriter<Cli
}
final int secondaryEffect = wrapper.read(Types.VAR_INT);
if (secondaryEffect != -1) {
if (secondaryEffect > 0) {
wrapper.write(Types.BOOLEAN, true);
wrapper.write(Types.VAR_INT, secondaryEffect);
} else {
@@ -195,11 +195,6 @@ public final class Protocol1_20_2To1_20 extends BackwardsProtocol<ClientboundPac
}
}
@Override
protected void registerConfigurationChangeHandlers() {
// Don't register them in the transitioning protocol
}
@Override
public void init(final UserConnection connection) {
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_19_4.PLAYER));
@@ -41,6 +41,9 @@ public final class BlockRewriter1_20_2 extends BlockRewriter<ClientboundPackets1
@Override
public void handleBlockEntity(final UserConnection connection, final BlockEntity blockEntity) {
final CompoundTag tag = blockEntity.tag();
if (tag == null) {
return;
}
final Tag primaryEffect = tag.remove("primary_effect");
if (primaryEffect instanceof StringTag) {
final String effectKey = Key.stripMinecraftNamespace(((StringTag) primaryEffect).getValue());
@@ -91,11 +91,11 @@ public final class Protocol1_20_5To1_20_3 extends BackwardsProtocol<ClientboundP
tagRewriter.handleGeneric(wrapper);
});
registerClientbound(ClientboundConfigurationPackets1_20_5.FINISH_CONFIGURATION, wrapper -> {
appendClientbound(ClientboundConfigurationPackets1_20_5.FINISH_CONFIGURATION, wrapper -> {
// In case the server for some reason does not send tags
sendRegistryData(wrapper.user());
});
registerClientbound(ClientboundPackets1_20_5.START_CONFIGURATION, wrapper -> wrapper.user().get(RegistryDataStorage.class).clear());
appendClientbound(ClientboundPackets1_20_5.START_CONFIGURATION, wrapper -> wrapper.user().get(RegistryDataStorage.class).clear());
registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO, wrapper -> {
wrapper.passthrough(Types.STRING); // Server ID
@@ -102,7 +102,10 @@ public final class BlockPacketRewriter1_20_5 extends BlockRewriter<ClientboundPa
final String value = propertyTag.getString("value", "");
final String signature = propertyTag.getString("signature");
final ListTag<CompoundTag> list = new ListTag<>(CompoundTag.class);
ListTag<CompoundTag> list = propertiesTag.getListTag(property, CompoundTag.class);
if (list == null) {
list = new ListTag<>(CompoundTag.class);
}
final CompoundTag updatedPropertyTag = new CompoundTag();
updatedPropertyTag.putString("Value", value);
if (signature != null) {
@@ -30,6 +30,7 @@ import com.viaversion.viabackwards.protocol.v1_20_5to1_20_3.storage.RegistryData
import com.viaversion.viabackwards.protocol.v1_20_5to1_20_3.storage.SecureChatStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.DimensionData;
import com.viaversion.viaversion.api.minecraft.GameMode;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
@@ -208,7 +209,10 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
});
map(Types.STRING); // World
map(Types.LONG); // Seed
map(Types.BYTE); // Gamemode
handler(wrapper -> {
final byte gamemode = wrapper.passthrough(Types.BYTE);
tracker(wrapper.user()).setInstaBuild(gamemode == GameMode.CREATIVE.id());
});
map(Types.BYTE); // Previous gamemode
map(Types.BOOLEAN); // Debug
map(Types.BOOLEAN); // Flat
@@ -234,6 +238,11 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
});
map(Types.STRING); // World
handler(worldDataTrackerHandlerByKey()); // Tracks world height and name for chunk data and entity (un)tracking
map(Types.LONG); // Seed
handler(wrapper -> {
final byte gamemode = wrapper.passthrough(Types.BYTE);
tracker(wrapper.user()).setInstaBuild(gamemode == GameMode.CREATIVE.id());
});
}
});
@@ -240,7 +240,7 @@ public final class Protocol1_21_11To1_21_9 extends BackwardsProtocol<Clientbound
@Override
public void init(final UserConnection connection) {
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_21_11.PLAYER));
addItemHasher(connection, new ItemHasherBase(this, connection));
connection.addItemHasher(this.getClass(), new ItemHasherBase(this, connection));
connection.put(new GameTimeStorage());
}
@@ -63,21 +63,13 @@ public final class EntityPacketRewriter1_21_11 extends EntityRewriter<Clientboun
protected void registerRewrites() {
final EntityDataTypes1_21_11 unmappedDataTypes = VersionedTypes.V1_21_11.entityDataTypes;
final EntityDataTypes1_21_9 entityDataTypes = VersionedTypes.V1_21_9.entityDataTypes;
filter().handler((event, data) -> {
if (data.dataType() == unmappedDataTypes.humanoidArmType) {
final int arm = data.value();
data.setTypeAndValue(entityDataTypes.byteType, (byte) arm);
return;
} else if (data.dataType() == unmappedDataTypes.zombieNautilusVariantType) {
event.cancel();
return;
}
int id = data.dataType().typeId();
if (id > unmappedDataTypes.zombieNautilusVariantType.typeId()) {
id--;
}
data.setDataType(entityDataTypes.byId(id));
dataTypeMapper()
.removed(unmappedDataTypes.zombieNautilusVariantType)
.skip(unmappedDataTypes.humanoidArmType)
.register();
filter().dataType(unmappedDataTypes.humanoidArmType).handler((event, data) -> {
final int arm = data.value();
data.setTypeAndValue(entityDataTypes.byteType, (byte) arm);
});
registerEntityDataTypeHandler1_20_3(
@@ -68,6 +68,8 @@ import com.viaversion.viaversion.rewriter.SoundRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.Limit;
import com.viaversion.viaversion.util.Unit;
import java.util.ArrayList;
import java.util.List;
import static com.viaversion.viaversion.protocols.v1_21to1_21_2.rewriter.BlockItemPacketRewriter1_21_2.downgradeItemData;
import static com.viaversion.viaversion.protocols.v1_21to1_21_2.rewriter.BlockItemPacketRewriter1_21_2.updateItemData;
@@ -575,15 +577,15 @@ public final class BlockItemPacketRewriter1_21_2 extends BackwardsStructuredItem
final String type = tag.getString("type");
if ("apply_effects".equals(type)) {
final ListTag<CompoundTag> effects = tag.getListTag("effects", CompoundTag.class);
final PotionEffect[] potionEffects = new PotionEffect[effects.size()];
final List<PotionEffect> potionEffects = new ArrayList<>();
for (int i = 0; i < effects.size(); i++) {
final CompoundTag effectTag = effects.get(i);
final int effect = effectTag.getInt("effect");
final PotionEffectData data = convertPotionEffectData(effectTag);
potionEffects[i] = new PotionEffect(effect, data);
potionEffects.add(new PotionEffect(effect, data));
}
final float probability = tag.getFloat("probability");
return new Consumable1_21_2.ConsumeEffect<>(id, Consumable1_21_2.ApplyStatusEffects.TYPE, new Consumable1_21_2.ApplyStatusEffects(potionEffects, probability));
return new Consumable1_21_2.ConsumeEffect<>(id, Consumable1_21_2.ApplyStatusEffects.TYPE, new Consumable1_21_2.ApplyStatusEffects(potionEffects.toArray(PotionEffect[]::new), probability));
} else if ("remove_effects".equals(type)) {
final HolderSet set = restoreHolderSet(tag, "remove_effects");
return new Consumable1_21_2.ConsumeEffect<>(id, Types.HOLDER_SET, set);
@@ -671,11 +673,14 @@ public final class BlockItemPacketRewriter1_21_2 extends BackwardsStructuredItem
final ListTag<CompoundTag> deathProtection = backupTag.getListTag("death_protection", CompoundTag.class);
if (deathProtection != null) {
final Consumable1_21_2.ConsumeEffect<?>[] effects = new Consumable1_21_2.ConsumeEffect[deathProtection.size()];
final List<Consumable1_21_2.ConsumeEffect<?>> effects = new ArrayList<>();
for (int i = 0; i < deathProtection.size(); i++) {
effects[i] = convertConsumableEffect(deathProtection.get(i));
final Consumable1_21_2.ConsumeEffect<?> effect = convertConsumableEffect(deathProtection.get(i));
if (effect != null) {
effects.add(effect);
}
}
data.set(StructuredDataKey.DEATH_PROTECTION, new DeathProtection(effects));
data.set(StructuredDataKey.DEATH_PROTECTION, new DeathProtection(effects.toArray(Consumable1_21_2.ConsumeEffect[]::new)));
}
removeCustomTag(data, customData);
@@ -528,7 +528,7 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
final PacketWrapper explosionPacket = wrapper.create(ClientboundPackets1_21.EXPLODE);
explosionPacket.write(Types.DOUBLE, 0.0); // Center X
explosionPacket.write(Types.DOUBLE, 0.0); // Center Y
explosionPacket.write(Types.DOUBLE, 20_000.0); // Center Y
explosionPacket.write(Types.DOUBLE, 0.0); // Center Z
explosionPacket.write(Types.FLOAT, 0F); // Power
explosionPacket.write(Types.VAR_INT, 0); // Blocks affected
@@ -538,7 +538,7 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
explosionPacket.write(Types.VAR_INT, 0); // Block interaction
explosionPacket.write(VersionedTypes.V1_21.particle(), new Particle(0)); // Small explosion
explosionPacket.write(VersionedTypes.V1_21.particle(), new Particle(0)); // Large explosion
explosionPacket.write(Types.SOUND_EVENT, Holder.of(new SoundEvent("", null))); // Explosion sound
explosionPacket.write(Types.SOUND_EVENT, Holder.of(new SoundEvent("intentionally_empty", null))); // Explosion sound
explosionPacket.send(Protocol1_21_2To1_21.class);
} else if (!relativeDeltaX && !relativeDeltaY && !relativeDeltaZ) {
@@ -626,7 +626,7 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
@Override
protected void registerRewrites() {
filter().mapDataType(VersionedTypes.V1_21.entityDataTypes::byId);
dataTypeMapper().register();
registerEntityDataTypeHandler1_20_3(
VersionedTypes.V1_21.entityDataTypes.itemType,
VersionedTypes.V1_21.entityDataTypes.blockStateType,
@@ -77,7 +77,7 @@ public final class EntityPacketRewriter1_21_4 extends EntityRewriter<Clientbound
@Override
protected void registerRewrites() {
filter().mapDataType(VersionedTypes.V1_21_2.entityDataTypes::byId);
dataTypeMapper().register();
registerEntityDataTypeHandler1_20_3(
VersionedTypes.V1_21_2.entityDataTypes.itemType,
VersionedTypes.V1_21_2.entityDataTypes.blockStateType,
@@ -178,7 +178,7 @@ public final class Protocol1_21_5To1_21_4 extends BackwardsProtocol<ClientboundP
@Override
public void init(final UserConnection user) {
addEntityTracker(user, new EntityTrackerBase(user, EntityTypes1_21_4.PLAYER));
user.put(new HashedItemConverterStorage(this));
user.put(new HashedItemConverterStorage(this, user));
}
@Override
@@ -44,6 +44,7 @@ import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_5;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.item.HashedItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.item.data.ArmorTrimMaterial;
import com.viaversion.viaversion.api.minecraft.item.data.BlocksAttacks;
@@ -65,6 +66,7 @@ import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_21_5;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.data.item.ItemHasherBase;
import com.viaversion.viaversion.data.item.OriginalHashedItem;
import com.viaversion.viaversion.libs.fastutil.ints.IntArrayList;
import com.viaversion.viaversion.libs.fastutil.ints.IntLinkedOpenHashSet;
import com.viaversion.viaversion.libs.fastutil.ints.IntList;
@@ -80,6 +82,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
import static com.viaversion.viaversion.protocols.v1_21_4to1_21_5.rewriter.BlockItemPacketRewriter1_21_5.downgradeItemData;
import static com.viaversion.viaversion.protocols.v1_21_4to1_21_5.rewriter.BlockItemPacketRewriter1_21_5.updateItemData;
@@ -151,12 +154,9 @@ public final class BlockItemPacketRewriter1_21_5 extends BackwardsStructuredItem
final int affectedItems = Limit.max(wrapper.passthrough(Types.VAR_INT), 128);
for (int i = 0; i < affectedItems; i++) {
wrapper.passthrough(Types.SHORT); // Slot
final Item item = handleItemToServer(wrapper.user(), wrapper.read(mappedItemType()));
wrapper.write(Types.HASHED_ITEM, ItemHasherBase.toHashedItem(hashedItemConverter.hasher(), item));
itemToHashedItem(wrapper, hashedItemConverter);
}
final Item carriedItem = handleItemToServer(wrapper.user(), wrapper.read(mappedItemType()));
wrapper.write(Types.HASHED_ITEM, ItemHasherBase.toHashedItem(hashedItemConverter.hasher(), carriedItem));
itemToHashedItem(wrapper, hashedItemConverter);
});
protocol.replaceClientbound(ClientboundPackets1_21_5.SET_EQUIPMENT, wrapper -> {
@@ -248,7 +248,27 @@ public final class BlockItemPacketRewriter1_21_5 extends BackwardsStructuredItem
wrapper.read(Types.BOOLEAN); // Show advancements
});
}
private void itemToHashedItem(final PacketWrapper wrapper, final HashedItemConverterStorage hashedItemConverter) {
final Item item = wrapper.read(mappedItemType());
final HashedItem originalHash = originalHashedItemFromBackup(item);
if (originalHash != null) {
// Will be restored in a later protocol
wrapper.write(Types.HASHED_ITEM, originalHash);
} else {
final Item serverItem = handleItemToServer(wrapper.user(), item);
wrapper.write(Types.HASHED_ITEM, ItemHasherBase.toHashedItem(hashedItemConverter.hasher(), serverItem));
}
}
private @Nullable OriginalHashedItem originalHashedItemFromBackup(final Item item) {
final CompoundTag customData = item.dataContainer().get(StructuredDataKey.CUSTOM_DATA);
final CompoundTag originalHashes;
if (customData == null || (originalHashes = customData.getCompoundTag("VV|original_hashes")) == null) {
return null;
}
return backedUpOriginalHashes(originalHashes, item);
}
private void convertClientAsset(final PacketWrapper wrapper) {
@@ -136,62 +136,17 @@ public final class EntityPacketRewriter1_21_5 extends EntityRewriter<Clientbound
protected void registerRewrites() {
final EntityDataTypes1_21_5 entityDataTypes = VersionedTypes.V1_21_5.entityDataTypes;
final EntityDataTypes1_21_2 mappedEntityDataTypes = VersionedTypes.V1_21_4.entityDataTypes;
filter().handler((event, data) -> {
final int id = data.dataType().typeId();
if (id == entityDataTypes.wolfVariantType.typeId()) {
final int type = data.value();
final Holder<WolfVariant> variant = Holder.of(type);
data.setTypeAndValue(mappedEntityDataTypes.wolfVariantType, variant);
return;
} else if (id == entityDataTypes.frogVariantType.typeId()) {
final int value = data.value();
final String variantKey = protocol.getRegistryDataRewriter().getMappings("frog_variant").idToKey(value);
final int newValue = (variantKey == null) ? 0 : switch (variantKey) {
case "cold" -> 2;
case "temperate" -> 0;
case "warm" -> 1;
default -> 0;
};
data.setTypeAndValue(mappedEntityDataTypes.frogVariantType, newValue);
return;
} else if (id == entityDataTypes.catVariantType.typeId()) {
final int value = data.value();
final String variantKey = protocol.getRegistryDataRewriter().getMappings("cat_variant").idToKey(value);
final int newValue = (variantKey == null) ? 1 : switch (variantKey) {
case "all_black" -> 10;
case "black" -> 1;
case "british_shorthair" -> 4;
case "calico" -> 5;
case "jellie" -> 9;
case "persian" -> 6;
case "ragdoll" -> 7;
case "red" -> 2;
case "siamese" -> 3;
case "tabby" -> 0;
case "white" -> 8;
default -> 1;
};
data.setTypeAndValue(mappedEntityDataTypes.catVariantType, newValue);
return;
}
int mappedId = id;
if (id == entityDataTypes.cowVariantType.typeId()
|| id == entityDataTypes.pigVariantType.typeId()
|| id == entityDataTypes.chickenVariantType.typeId()
|| id == entityDataTypes.wolfSoundVariantType.typeId()) {
event.cancel();
return;
} else if (id > entityDataTypes.chickenVariantType.typeId()) {
mappedId -= 4;
} else if (id > entityDataTypes.pigVariantType.typeId()) {
mappedId -= 3;
} else if (id > entityDataTypes.wolfSoundVariantType.typeId()) {
mappedId -= 2;
} else if (id > entityDataTypes.cowVariantType.typeId()) {
mappedId -= 1;
}
data.setDataType(mappedEntityDataTypes.byId(mappedId));
dataTypeMapper()
.removed(entityDataTypes.cowVariantType)
.removed(entityDataTypes.wolfSoundVariantType)
.removed(entityDataTypes.pigVariantType)
.removed(entityDataTypes.chickenVariantType)
.skip(entityDataTypes.wolfVariantType)
.register();
filter().dataType(entityDataTypes.wolfVariantType).handler((event, data) -> {
final int type = data.value();
final Holder<WolfVariant> variant = Holder.of(type);
data.setTypeAndValue(mappedEntityDataTypes.wolfVariantType, variant);
});
registerEntityDataTypeHandler1_20_3(
@@ -204,6 +159,37 @@ public final class EntityPacketRewriter1_21_5 extends EntityRewriter<Clientbound
mappedEntityDataTypes.optionalComponentType
);
filter().dataType(mappedEntityDataTypes.frogVariantType).handler((event, data) -> {
final int value = data.value();
final String variantKey = tracker(event.user()).registryKeys("frog_variant").idToKey(value);
final int newValue = (variantKey == null) ? 0 : switch (variantKey) {
case "cold" -> 2;
case "temperate" -> 0;
case "warm" -> 1;
default -> 0;
};
data.setValue(newValue);
});
filter().dataType(mappedEntityDataTypes.catVariantType).handler((event, data) -> {
final int value = data.value();
final String variantKey = tracker(event.user()).registryKeys("cat_variant").idToKey(value);
final int newValue = (variantKey == null) ? 1 : switch (variantKey) {
case "all_black" -> 10;
case "black" -> 1;
case "british_shorthair" -> 4;
case "calico" -> 5;
case "jellie" -> 9;
case "persian" -> 6;
case "ragdoll" -> 7;
case "red" -> 2;
case "siamese" -> 3;
case "tabby" -> 0;
case "white" -> 8;
default -> 1;
};
data.setValue(newValue);
});
filter().type(EntityTypes1_21_5.ABSTRACT_MINECART).addIndex(13); // Custom display
filter().type(EntityTypes1_21_5.ABSTRACT_MINECART).index(11).handler((event, data) -> {
final int state = (int) data.getValue();
@@ -240,7 +226,7 @@ public final class EntityPacketRewriter1_21_5 extends EntityRewriter<Clientbound
filter().type(EntityTypes1_21_5.CHICKEN).cancel(17); // Chicken variant
filter().type(EntityTypes1_21_5.COW).cancel(17); // Cow variant
filter().type(EntityTypes1_21_5.PIG).cancel(19); // Pig variant
filter().type(EntityTypes1_21_5.PIG).cancel(18); // Pig variant
filter().type(EntityTypes1_21_5.WOLF).cancel(23); // Sound variant
filter().type(EntityTypes1_21_5.EXPERIENCE_ORB).cancel(8); // Value
@@ -18,6 +18,7 @@
package com.viaversion.viabackwards.protocol.v1_21_5to1_21_4.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.codec.CodecContext;
import com.viaversion.viaversion.api.minecraft.codec.CodecContext.RegistryAccess;
import com.viaversion.viaversion.api.minecraft.codec.hash.Hasher;
@@ -30,8 +31,8 @@ public class HashedItemConverterStorage implements StorableObject {
private final Hasher hasher;
public HashedItemConverterStorage(final Protocol<?, ?, ?, ?> protocol) {
final RegistryAccess registryAccess = RegistryAccess.of(protocol);
public HashedItemConverterStorage(final Protocol<?, ?, ?, ?> protocol, final UserConnection connection) {
final RegistryAccess registryAccess = RegistryAccess.of(protocol, connection);
final CodecContext context = new CodecRegistryContext(protocol, registryAccess, false);
this.hasher = new HashOps(context, HashFunction.CRC32C);
}
@@ -93,6 +93,9 @@ public final class Protocol1_21_6To1_21_5 extends BackwardsProtocol<ClientboundP
protected void registerPackets() {
super.registerPackets();
replaceClientbound(ClientboundPackets1_21_6.UPDATE_TAGS, this::updateTags);
replaceClientbound(ClientboundConfigurationPackets1_21_6.UPDATE_TAGS, this::updateTags);
appendClientbound(ClientboundPackets1_21_6.SOUND, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Source
fixSoundSource(wrapper);
@@ -238,34 +241,24 @@ public final class Protocol1_21_6To1_21_5 extends BackwardsProtocol<ClientboundP
}
private void updateTags(final PacketWrapper wrapper) {
tagRewriter.handleGeneric(wrapper);
wrapper.resetReader();
// Store dialog tags; then call the normal rewriter which will remove them before sending to the client
final RegistryAndTags registryAndTags = wrapper.user().get(RegistryAndTags.class);
final int length = wrapper.passthrough(Types.VAR_INT);
for (int i = 0; i < length; i++) {
final String registryKey = wrapper.read(Types.STRING);
final String registryKey = wrapper.passthrough(Types.STRING);
final boolean dialog = "dialog".equals(Key.stripMinecraftNamespace(registryKey));
if (dialog) {
final int tagsSize = wrapper.read(Types.VAR_INT);
for (int j = 0; j < tagsSize; j++) {
final String key = wrapper.read(Types.STRING);
final int[] ids = wrapper.read(Types.VAR_INT_ARRAY_PRIMITIVE);
final int tagsSize = wrapper.passthrough(Types.VAR_INT);
for (int j = 0; j < tagsSize; j++) {
final String key = wrapper.passthrough(Types.STRING);
final int[] ids = wrapper.passthrough(Types.VAR_INT_ARRAY_PRIMITIVE);
if (dialog) {
registryAndTags.storeTags(key, ids);
}
} else {
wrapper.write(Types.STRING, registryKey); // Write back
final int tagsSize = wrapper.passthrough(Types.VAR_INT);
for (int j = 0; j < tagsSize; j++) {
wrapper.passthrough(Types.STRING);
wrapper.passthrough(Types.VAR_INT_ARRAY_PRIMITIVE);
}
}
}
if (registryAndTags.tagsSent()) {
wrapper.set(Types.VAR_INT, 0, length - 1); // Dialog tags have been read, remove from size
}
wrapper.resetReader();
tagRewriter.handleGeneric(wrapper);
}
private void clearDialog(final PacketWrapper wrapper) {
@@ -307,7 +300,7 @@ public final class Protocol1_21_6To1_21_5 extends BackwardsProtocol<ClientboundP
@Override
public void init(final UserConnection user) {
addEntityTracker(user, new EntityTrackerBase(user, EntityTypes1_21_6.PLAYER));
addItemHasher(user, new ItemHasherBase(this, user));
user.addItemHasher(this.getClass(), new ItemHasherBase(this, user));
user.put(new RegistryAndTags());
user.put(new ClickEvents());
}
@@ -84,7 +84,7 @@ public final class EntityPacketRewriter1_21_6 extends EntityRewriter<Clientbound
@Override
protected void registerRewrites() {
final EntityDataTypes1_21_5 entityDataTypes = VersionedTypes.V1_21_5.entityDataTypes;
filter().mapDataType(entityDataTypes::byId);
dataTypeMapper().register();
registerEntityDataTypeHandler1_20_3(
entityDataTypes.itemType,
entityDataTypes.blockStateType,
@@ -44,10 +44,6 @@ public final class RegistryAndTags implements StorableObject {
return dialogs.get(Key.stripMinecraftNamespace(key));
}
public boolean tagsSent() {
return dialogTags != null && !dialogTags.isEmpty();
}
public void storeTags(final String key, final int[] ids) {
if (dialogTags == null) {
dialogTags = new Object2ObjectArrayMap<>();
@@ -55,12 +51,8 @@ public final class RegistryAndTags implements StorableObject {
dialogTags.put(Key.stripMinecraftNamespace(key), ids);
}
public int[] fromKey(final String key) {
return dialogTags.get(Key.stripMinecraftNamespace(key));
}
public CompoundTag[] fromRegistryKey(final String key) {
final int[] ids = fromKey(key);
final int[] ids = dialogTags.get(Key.stripMinecraftNamespace(key));
if (ids == null) {
return null;
}
@@ -68,7 +68,7 @@ public final class Protocol1_21_7To1_21_6 extends BackwardsProtocol<ClientboundP
@Override
public void init(final UserConnection connection) {
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_21_6.PLAYER));
addItemHasher(connection, new ItemHasherBase(this, connection));
connection.addItemHasher(this.getClass(), new ItemHasherBase(this, connection));
}
@Override
@@ -193,7 +193,7 @@ public final class Protocol1_21_9To1_21_7 extends BackwardsProtocol<ClientboundP
@Override
public void init(final UserConnection connection) {
addEntityTracker(connection, new EntityTracker1_21_9(connection, EntityTypes1_21_9.PLAYER));
addItemHasher(connection, new ItemHasherBase(this, connection));
connection.addItemHasher(this.getClass(), new ItemHasherBase(this, connection));
connection.put(new PlayerRotationStorage());
connection.put(new DimensionScaleStorage());
connection.put(new BundleStateTracker());
@@ -338,27 +338,12 @@ public final class EntityPacketRewriter1_21_9 extends EntityRewriter<Clientbound
@Override
protected void registerRewrites() {
final EntityDataTypes1_21_5 entityDataTypes = protocol.mappedTypes().entityDataTypes();
filter().handler((event, data) -> {
int id = data.dataType().typeId();
if (id == VersionedTypes.V1_21_9.entityDataTypes.copperGolemState.typeId()
|| id == VersionedTypes.V1_21_9.entityDataTypes.weatheringCopperState.typeId()) {
event.cancel();
return;
}
if (id == VersionedTypes.V1_21_9.entityDataTypes.mannequinProfileType.typeId()) {
if (event.entityType() == null) {
event.cancel();
}
return; // Handled separately
}
if (id > VersionedTypes.V1_21_9.entityDataTypes.armadilloState.typeId()) {
id -= 2;
}
if (id >= entityDataTypes.compoundTagType.typeId()) {
id++;
}
data.setDataType(entityDataTypes.byId(id));
});
dataTypeMapper()
.added(entityDataTypes.compoundTagType)
.removed(VersionedTypes.V1_21_9.entityDataTypes.copperGolemState)
.removed(VersionedTypes.V1_21_9.entityDataTypes.weatheringCopperState)
.removed(VersionedTypes.V1_21_9.entityDataTypes.mannequinProfileType)
.register();
registerEntityDataTypeHandler1_20_3(
entityDataTypes.itemType,
@@ -370,11 +355,14 @@ public final class EntityPacketRewriter1_21_9 extends EntityRewriter<Clientbound
entityDataTypes.optionalComponentType
);
filter().type(EntityTypes1_21_9.COPPER_GOLEM).cancel(16); // Weather state
filter().type(EntityTypes1_21_9.COPPER_GOLEM).cancel(17); // Golem state
final EntityDataHandler shoulderDataHandler = (event, data) -> {
final CompoundTag entityTag = new CompoundTag();
final Integer value = data.value();
if (value != null) {
entityTag.putInt("id", EntityTypes1_21_6.PARROT.getId());
entityTag.putString("id", "parrot");
entityTag.putInt("Variant", value);
}
data.setTypeAndValue(protocol.mappedTypes().entityDataTypes.compoundTagType, entityTag);
@@ -29,7 +29,6 @@ import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.WolfVariant;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_20_5;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
@@ -147,26 +146,27 @@ public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPa
@Override
protected void registerRewrites() {
final EntityDataTypes1_20_5 mappedEntityDataTypes = VersionedTypes.V1_20_5.entityDataTypes;
filter().handler((event, data) -> {
final EntityDataType type = data.dataType();
if (type == VersionedTypes.V1_21.entityDataTypes.wolfVariantType) {
final Holder<WolfVariant> variant = data.value();
if (variant.hasId()) {
data.setTypeAndValue(mappedEntityDataTypes.wolfVariantType, variant.id());
} else {
event.cancel();
}
} else if (type == VersionedTypes.V1_21.entityDataTypes.paintingVariantType) {
final Holder<PaintingVariant> variant = data.value();
if (variant.hasId()) {
final EnchantmentsPaintingsStorage storage = event.user().get(EnchantmentsPaintingsStorage.class);
final int mappedId = storage.mappedPainting(variant.id());
data.setTypeAndValue(mappedEntityDataTypes.paintingVariantType, mappedId);
} else {
event.cancel();
}
dataTypeMapper()
.skip(VersionedTypes.V1_21.entityDataTypes.wolfVariantType)
.skip(VersionedTypes.V1_21.entityDataTypes.paintingVariantType)
.register();
filter().dataType(VersionedTypes.V1_21.entityDataTypes.wolfVariantType).handler((event, data) -> {
final Holder<WolfVariant> variant = data.value();
if (variant.hasId()) {
data.setTypeAndValue(mappedEntityDataTypes.wolfVariantType, variant.id());
} else {
data.setDataType(mappedEntityDataTypes.byId(type.typeId()));
event.cancel();
}
});
filter().dataType(VersionedTypes.V1_21.entityDataTypes.paintingVariantType).handler((event, data) -> {
final Holder<PaintingVariant> variant = data.value();
if (variant.hasId()) {
final EnchantmentsPaintingsStorage storage = event.user().get(EnchantmentsPaintingsStorage.class);
final int mappedId = storage.mappedPainting(variant.id());
data.setTypeAndValue(mappedEntityDataTypes.paintingVariantType, mappedId);
} else {
event.cancel();
}
});
registerEntityDataTypeHandler1_20_3(
@@ -27,6 +27,7 @@ import com.viaversion.viabackwards.protocol.v26_1to1_21_11.rewriter.BlockItemPac
import com.viaversion.viabackwards.protocol.v26_1to1_21_11.rewriter.ComponentRewriter26_1;
import com.viaversion.viabackwards.protocol.v26_1to1_21_11.rewriter.EntityPacketRewriter26_1;
import com.viaversion.viabackwards.protocol.v26_1to1_21_11.storage.DayTimeStorage;
import com.viaversion.viabackwards.protocol.v26_1to1_21_11.storage.GameModeStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_11;
@@ -88,9 +89,11 @@ public final class Protocol26_1To1_21_11 extends BackwardsProtocol<ClientboundPa
// Remove new environment attributes
registryDataRewriter.addHandler("dimension_type", (key, tag) -> {
final CompoundTag attributes = tag.getCompoundTag("attributes");
removeNamespaced(attributes, "visual/block_light_tint");
removeNamespaced(attributes, "visual/night_vision_color");
removeNamespaced(attributes, "visual/ambient_light_color");
if (attributes != null) {
removeNamespaced(attributes, "visual/block_light_tint");
removeNamespaced(attributes, "visual/night_vision_color");
removeNamespaced(attributes, "visual/ambient_light_color");
}
});
// Move around entity variant names and sounds
@@ -127,7 +130,7 @@ public final class Protocol26_1To1_21_11 extends BackwardsProtocol<ClientboundPa
final long totalTicks = wrapper.read(Types.VAR_LONG);
wrapper.read(Types.FLOAT); // Partial tick
final float tickRate = wrapper.read(Types.FLOAT);
if (Key.equals(registryDataRewriter.getMappings("world_clock").idToKey(clockType), "overworld")) {
if (Key.equals(entityRewriter.tracker(wrapper.user()).registryKeys("world_clock").idToKey(clockType), "overworld")) {
dayTime = totalTicks;
advanceTime = tickRate != 0;
}
@@ -166,8 +169,9 @@ public final class Protocol26_1To1_21_11 extends BackwardsProtocol<ClientboundPa
@Override
public void init(final UserConnection connection) {
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_21_11.PLAYER));
addItemHasher(connection, new ItemHasherBase(this, connection));
connection.addItemHasher(this.getClass(), new ItemHasherBase(this, connection));
connection.put(new DayTimeStorage());
connection.put(new GameModeStorage());
}
@Override
@@ -45,7 +45,7 @@ public final class BlockItemPacketRewriter26_1 extends BackwardsStructuredItemRe
@Override
protected void handleItemDataComponentsToServer(final UserConnection connection, final Item item, final StructuredDataContainer container) {
super.handleItemDataComponentsToServer(connection, item, container);
upgradeData(protocol, protocol.types().structuredDataKeys(), container);
upgradeData(protocol, connection, protocol.types().structuredDataKeys(), container);
}
@Override
@@ -19,6 +19,8 @@ package com.viaversion.viabackwards.protocol.v26_1to1_21_11.rewriter;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v26_1to1_21_11.Protocol26_1To1_21_11;
import com.viaversion.viabackwards.protocol.v26_1to1_21_11.storage.GameModeStorage;
import com.viaversion.viaversion.api.minecraft.GameMode;
import com.viaversion.viaversion.api.minecraft.Vector3d;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_11;
@@ -27,6 +29,7 @@ import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes2
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
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.ServerboundPackets26_1;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPackets1_21_6;
@@ -42,13 +45,31 @@ public final class EntityPacketRewriter26_1 extends EntityRewriter<ClientboundPa
@Override
public void registerPackets() {
protocol.appendClientbound(ClientboundPackets26_1.RESPAWN, wrapper -> {
final byte gamemode = wrapper.get(Types.BYTE, 0);
wrapper.user().get(GameModeStorage.class).setGameMode(gamemode);
});
protocol.appendClientbound(ClientboundPackets26_1.LOGIN, wrapper -> {
final byte gamemode = wrapper.get(Types.BYTE, 0);
wrapper.user().get(GameModeStorage.class).setGameMode(gamemode);
});
protocol.appendClientbound(ClientboundPackets26_1.GAME_EVENT, wrapper -> {
wrapper.resetReader();
final short event = wrapper.passthrough(Types.UNSIGNED_BYTE);
if (event == 3) {
final int value = (int) Math.floor(wrapper.passthrough(Types.FLOAT) + 0.5F);
wrapper.user().get(GameModeStorage.class).setGameMode(value);
}
});
protocol.registerServerbound(ServerboundPackets1_21_6.INTERACT, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
final int action = wrapper.read(Types.VAR_INT);
switch (action) {
case INTERACT_ACTION -> wrapper.cancel(); // Drop "normal" interacts, as interact_at is always sent by Vanilla clients, and always sent first, with this following after
case ATTACK_ACTION -> {
wrapper.setPacketType(ServerboundPackets26_1.ATTACK);
final boolean spectator = wrapper.user().get(GameModeStorage.class).gameMode() == GameMode.SPECTATOR.id();
wrapper.setPacketType(spectator ? ServerboundPackets26_1.SPECTATE_ENTITY : ServerboundPackets26_1.ATTACK);
wrapper.read(Types.BOOLEAN); // Using secondary action
}
case INTERACT_AT_ACTION -> {
@@ -68,26 +89,12 @@ public final class EntityPacketRewriter26_1 extends EntityRewriter<ClientboundPa
protected void registerRewrites() {
final EntityDataTypes26_1 entityDataTypes = VersionedTypes.V26_1.entityDataTypes;
final EntityDataTypes1_21_11 mappedEntityDataTypes = VersionedTypes.V1_21_11.entityDataTypes;
filter().handler((event, data) -> {
final int id = data.dataType().typeId();
int mappedId = id;
if (id == entityDataTypes.catSoundVariant.typeId()
|| id == entityDataTypes.cowSoundVariant.typeId()
|| id == entityDataTypes.pigSoundVariant.typeId()
|| id == entityDataTypes.chickenSoundVariant.typeId()) {
event.cancel();
return;
} else if (id > entityDataTypes.chickenSoundVariant.typeId()) {
mappedId -= 4;
} else if (id > entityDataTypes.pigSoundVariant.typeId()) {
mappedId -= 3;
} else if (id > entityDataTypes.cowSoundVariant.typeId()) {
mappedId -= 2;
} else if (id > entityDataTypes.catSoundVariant.typeId()) {
mappedId -= 1;
}
data.setDataType(mappedEntityDataTypes.byId(mappedId));
});
dataTypeMapper()
.removed(entityDataTypes.catSoundVariant)
.removed(entityDataTypes.cowSoundVariant)
.removed(entityDataTypes.pigSoundVariant)
.removed(entityDataTypes.chickenSoundVariant)
.register();
registerEntityDataTypeHandler1_20_3(
mappedEntityDataTypes.itemType,
mappedEntityDataTypes.blockStateType,
@@ -34,7 +34,9 @@ public final class DayTimeStorage implements StorableObject {
}
public long setGameTimeAndUpdateDayTime(final long gameTime) {
this.dayTime += gameTime - this.gameTime;
if (advanceTime) {
this.dayTime += gameTime - this.gameTime;
}
this.gameTime = gameTime;
return dayTime;
}
@@ -0,0 +1,33 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* 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.viabackwards.protocol.v26_1to1_21_11.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
public final class GameModeStorage implements StorableObject {
private int gameMode = -1;
public int gameMode() {
return gameMode;
}
public void setGameMode(final int gameMode) {
this.gameMode = gameMode;
}
}
@@ -20,7 +20,11 @@ package com.viaversion.viabackwards.utils;
public class VelocityUtil {
public static short toLegacyVelocity(double value) {
return (short) Math.max(Short.MIN_VALUE, Math.min(Short.MAX_VALUE, (long) (value * 8000)));
// Round instead of truncating toward zero. The 1.21.9+ LP-vector encoding is lossy: 0.4 b/t
// decodes as 0.39998779, and (long)(value * 8000) floors that to 3199 instead of 3200. Rounding
// restores the intended legacy short and matches a native 1.8 server, which sends 0.4 directly
// as (int)(0.4 * 8000) = 3200.
return (short) Math.max(Short.MIN_VALUE, Math.min(Short.MAX_VALUE, Math.round(value * 8000)));
}
}
@@ -8,10 +8,10 @@ always-show-original-mob-name: true
add-custom-enchants-into-lore: true
#
# Adds the color of a scoreboard team after its prefix for 1.12 clients on 1.13+ servers.
add-teamcolor-to-prefix: true
add-teamcolor-to-prefix: false
#
# Converts the 1.13 face look-at packet for 1.12- players. Requires a bit of extra caching.
fix-1_13-face-player: false
fix-1_13-face-player: true
#
# Fixes 1.13 clients and lower not seeing color or formatting in inventory titles by converting them to legacy text.
# If you have issues with translatable text being displayed wrongly, disable this.
@@ -19,10 +19,10 @@ fix-formatted-inventory-titles: true
#
# Sends inventory acknowledgement packets to act as a replacement for ping packets for sub 1.17 clients.
# This only takes effect for ids in the short range. Useful for anticheat compatibility.
handle-pings-as-inv-acknowledgements: false
handle-pings-as-inv-acknowledgements: true
#
# Adds bedrock blocks at y=0 for sub 1.17 clients. This may allow for weird interactions due to sending fake blocks.
bedrock-at-y-0: false
bedrock-at-y-0: true
#
# Shows sculk shriekers as crying obsidian for 1.18.2 clients on 1.19+ servers. This fixes collision and block breaking issues.
# If disabled, the client will see them as end portal frames.
@@ -30,7 +30,7 @@ sculk-shriekers-to-crying-obsidian: true
#
# Shows scaffolding as water for 1.13.2 clients on 1.14+ servers. This fixes collision issues.
# If disabled, the client will see them as hay blocks.
scaffolding-to-water: false
scaffolding-to-water: true
#
# Maps the darkness effect to blindness for 1.18.2 clients on 1.19+ servers.
map-darkness-effect: true
@@ -43,31 +43,31 @@ map-custom-model-data: true
map-display-entities: true
#
# Suppresses warnings of missing emulations for certain features that are not supported (e.g. world height in 1.17+).
suppress-emulation-warnings: false
suppress-emulation-warnings: true
#
# If enabled, dialogs will be shown via chest inventories for 1.21.5 clients on 1.21.6+ servers.
dialogs-via-chests: true
#
# Dialog styling. You can also use translation keys here.
dialog-style:
page-navigation-title: "&9&lPage navigation"
page-navigation-next: "&9Left click: &6Go to next page"
page-navigation-previous: "&9Right click: &6Go to previous page"
toggle-value: "&9Left click: &6Toggle value"
increase-value: "&9Left click: &6Increase value by %s"
decrease-value: "&9Right click: &6Decrease value by %s"
value-range: "&7(Value between &a%s &7and &a%s&7)"
current-value: "&7Current value: &a%s"
edit-value: "&9Left click: &6Edit text"
next-option: "&9Left click: &6Go to next option"
previous-option: "&9Right click: &6Go to previous option"
set-text: "&9Left click/close: &6Set text"
close: "&9Left click: &6Close"
page-navigation-title: '&9&lPage navigation'
page-navigation-next: '&9Left click: &6Go to next page'
page-navigation-previous: '&9Right click: &6Go to previous page'
toggle-value: '&9Left click: &6Toggle value'
increase-value: '&9Left click: &6Increase value by %s'
decrease-value: '&9Right click: &6Decrease value by %s'
value-range: '&7(Value between &a%s &7and &a%s&7)'
current-value: '&7Current value: &a%s'
edit-value: '&9Left click: &6Edit text'
next-option: '&9Left click: &6Go to next option'
previous-option: '&9Right click: &6Go to previous option'
set-text: '&9Left click/close: &6Set text'
close: '&9Left click: &6Close'
#
# If enabled, the code of conduct will be shown as a dialog for 1.21.7 clients on 1.21.9+ servers.
# Note that this is not supported for clients below 1.21.6 right now due to missing support for
# dialogs during the configuration phase.
code-of-conduct-as-dialog: true
code-of-conduct-as-dialog: false
#
# Passes the original vanilla 1.21.4+ item name into custom_model_data strings.
# This allows client resource packs to restore the appearance of newer items entirely missing from this older version.
@@ -3015,7 +3015,9 @@
"command.context.parse_error": "%s at position %s: %s",
"commands.list.nameAndId": "%s (%s)",
"argument.angle.incomplete": "Incomplete (expected 1 angle)",
"commands.summon.failed.uuid": "Unable to summon entity due to duplicate UUIDs"
"commands.summon.failed.uuid": "Unable to summon entity due to duplicate UUIDs",
"event.minecraft.raid.victory.full": "Raid - Victory",
"event.minecraft.raid.defeat.full": "Raid - Defeat"
},
"1.16": {
"gui.recipebook.search_hint": "Search...",
+3 -3
View File
@@ -1,8 +1,8 @@
projectVersion=5.9.0-SNAPSHOT
projectVersion=5.9.2-SNAPSHOT
# Smile emoji (note that modrinth may not have added the version on release yet)
mcVersions=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
mcVersionRange=1.10-26.1
mcVersions=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
mcVersionRange=1.10-26.1.2
velocityVersion=3.4-3.5
org.gradle.configureondemand=true
+2 -2
View File
@@ -3,14 +3,14 @@ metadata.format.version = "1.1"
[versions]
# ViaVersion
viaver = "5.9.0-SNAPSHOT"
viaver = "5.9.2-SNAPSHOT"
# Common provided
netty = "4.0.20.Final"
guava = "17.0"
log4j = "2.8.1"
checkerQual = "3.53.1"
checkerQual = "3.54.0"
# Platforms
paper = "1.16.5-R0.1-SNAPSHOT"
@@ -47,7 +47,7 @@
},
{
"id": "viaversion",
"version": "[5.8.1-SNAPSHOT,)"
"version": "[5.9.2-SNAPSHOT,)"
}
]
},