More absolutely cursed WIP

This commit is contained in:
Nassim Jahnke 2023-08-03 21:58:23 +10:00
parent 8c6d104faa
commit 62c0ef360f
15 changed files with 583 additions and 92 deletions

View File

@ -179,7 +179,7 @@ public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T> {
public static final Type<Item[]> FLAT_VAR_INT_ITEM_ARRAY_VAR_INT = new ArrayType<>(FLAT_VAR_INT_ITEM);
public static final Type<Item> ITEM1_20_2 = new Item1_20_2Type();
public static final Type<Item[]> ITEM1_20_2_ARRAY_VAR_INT = new ArrayType<>(ITEM1_20_2);
public static final Type<Item[]> ITEM1_20_2_VAR_INT_ARRAY = new ArrayType<>(ITEM1_20_2);
/* Actual Class */
private final Class<? super T> outputClass;

View File

@ -83,6 +83,9 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectSortedMap;
import org.checkerframework.checker.nullness.qual.Nullable;
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -103,8 +106,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.Nullable;
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
public class ProtocolManagerImpl implements ProtocolManager {
private static final Protocol BASE_PROTOCOL = new BaseProtocol();
@ -135,7 +136,7 @@ public class ProtocolManagerImpl implements ProtocolManager {
// Base Protocol
registerBaseProtocol(BASE_PROTOCOL, Range.lessThan(Integer.MIN_VALUE));
registerBaseProtocol(new BaseProtocol1_7(), Range.lessThan(ProtocolVersion.v1_16.getVersion()));
registerBaseProtocol(new BaseProtocol1_16(), Range.atLeast(ProtocolVersion.v1_16.getVersion()));
registerBaseProtocol(new BaseProtocol1_16(), Range.closed(ProtocolVersion.v1_16.getVersion(), ProtocolVersion.v1_20.getVersion()));
registerProtocol(new Protocol1_9To1_8(), ProtocolVersion.v1_9, ProtocolVersion.v1_8);
registerProtocol(new Protocol1_9_1To1_9(), Arrays.asList(ProtocolVersion.v1_9_1.getVersion(), ProtocolVersion.v1_9_2.getVersion()), ProtocolVersion.v1_9.getVersion());

View File

@ -19,15 +19,11 @@ package com.viaversion.viaversion.protocols.base;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import java.util.UUID;
public class BaseProtocol1_16 extends BaseProtocol1_7 {
@Override
protected boolean finishLoginAfterGameprofile() {
return false; // Start CONFIGURATION phase after the serverbound ack
}
@Override
protected UUID passthroughLoginUUID(final PacketWrapper wrapper) throws Exception {
return wrapper.passthrough(Type.UUID);

View File

@ -121,7 +121,7 @@ public class BaseProtocol1_7 extends AbstractProtocol {
// Login Success Packet
registerClientbound(ClientboundLoginPackets.GAME_PROFILE, wrapper -> {
ProtocolInfo info = wrapper.user().getProtocolInfo();
if (finishLoginAfterGameprofile()) {
if (info.getProtocolVersion() < ProtocolVersion.v1_20_2.getVersion()) {
info.setState(State.PLAY);
}
@ -166,8 +166,6 @@ public class BaseProtocol1_7 extends AbstractProtocol {
});
registerServerbound(ServerboundLoginPackets.LOGIN_ACKNOWLEDGED, wrapper -> wrapper.user().getProtocolInfo().setState(State.CONFIGURATION));
// TODO AAAAAAAAAAAAAAAAA
registerServerbound(ServerboundConfigurationPackets1_20_2.FINISH_CONFIGURATION, wrapper -> wrapper.user().getProtocolInfo().setState(State.PLAY));
}
@Override
@ -192,8 +190,4 @@ public class BaseProtocol1_7 extends AbstractProtocol {
}
return UUID.fromString(uuidString);
}
protected boolean finishLoginAfterGameprofile() {
return true;
}
}

View File

@ -23,9 +23,8 @@ import com.viaversion.viaversion.api.protocol.packet.State;
public enum ServerboundLoginPackets implements ServerboundPacketType {
HELLO, // 0x00
ENCRYPTION_KEY, // 0x01
CUSTOM_QUERY, // 0x02
CUSTOM_QUERY_ANSWER, // 0x03
LOGIN_ACKNOWLEDGED; // 0x04
CUSTOM_QUERY_ANSWER, // 0x02
LOGIN_ACKNOWLEDGED; // 0x03
@Override
public final int getId() {

View File

@ -48,7 +48,7 @@ public class RecipeRewriter1_19_3<C extends ClientboundPacketType> extends Recip
wrapper.passthrough(Type.STRING); // Group
wrapper.passthrough(Type.VAR_INT); // Crafting book category
handleIngredients(wrapper);
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
}
@Override
@ -59,7 +59,7 @@ public class RecipeRewriter1_19_3<C extends ClientboundPacketType> extends Recip
for (int i = 0; i < ingredients; i++) {
handleIngredient(wrapper);
}
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
}
@Override
@ -67,7 +67,7 @@ public class RecipeRewriter1_19_3<C extends ClientboundPacketType> extends Recip
wrapper.passthrough(Type.STRING); // Group
wrapper.passthrough(Type.VAR_INT); // Crafting book category
handleIngredient(wrapper);
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
wrapper.passthrough(Type.FLOAT); // EXP
wrapper.passthrough(Type.VAR_INT); // Cooking time
}

View File

@ -28,19 +28,24 @@ import com.viaversion.viaversion.api.rewriter.EntityRewriter;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.exception.CancelException;
import com.viaversion.viaversion.protocol.packet.PacketWrapperImpl;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import com.viaversion.viaversion.protocols.base.ServerboundLoginPackets;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ClientboundPackets1_19_4;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ServerboundPackets1_19_4;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter.BlockItemPacketRewriter1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter.EntityPacketRewriter1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ClientboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ClientboundPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ServerboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ServerboundPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter.BlockItemPacketRewriter1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter.EntityPacketRewriter1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage.FakeProtocolState;
import com.viaversion.viaversion.rewriter.SoundRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.UUID;
@ -57,8 +62,6 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
@Override
protected void registerPackets() {
// TODO Updated NBT type used in: block entity, chunk, tag query, entity metadata data, item type, mob effect
// TODO Handle Enabled features and tags before configuration phase end
// TODO Make sure Paper/Velocity handle a 0,0 uuid fine during login
@ -89,16 +92,31 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
});
// Deal with the new CONFIGURATION protocol state the client expects
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE.getId(), ClientboundLoginPackets.GAME_PROFILE.getId(), wrapper -> {
wrapper.user().get(FakeProtocolState.class).setGameProfileSent(true);
});
registerServerbound(State.LOGIN, ServerboundLoginPackets.LOGIN_ACKNOWLEDGED.getId(), -1, wrapper -> {
System.out.println("Login acknowleged!");
wrapper.user().getProtocolInfo().setState(State.PLAY);
wrapper.user().get(FakeProtocolState.class).setConfigurationState(true);
wrapper.cancel();
});
cancelServerbound(State.LOGIN, ServerboundLoginPackets.CUSTOM_QUERY_ANSWER.getId()); // TODO ?
// TODO Make sure this is called in other protocols as well/the base protocol
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.FINISH_CONFIGURATION.getId(), -1, wrapper -> {
wrapper.user().get(FakeProtocolState.class).setConfigurationState(false);
System.out.println("NOW PLAYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY");
wrapper.cancel();
});
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD.getId(), ServerboundPackets1_19_4.PLUGIN_MESSAGE.getId(), wrapper -> {
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD.getId(), -1, wrapper -> {
if (wrapper.user().getProtocolInfo().getState() == State.PLAY) {
wrapper.setPacketType(ServerboundPackets1_19_4.PLUGIN_MESSAGE);
} else {
wrapper.user().get(FakeProtocolState.class).addPacketToQueue(wrapper, false);
wrapper.cancel();
}
});
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.KEEP_ALIVE.getId(), ServerboundPackets1_19_4.KEEP_ALIVE.getId(), wrapper -> {
});
@ -120,47 +138,55 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
}
@Override
public void transform(Direction direction, State state, PacketWrapper packetWrapper) throws Exception {
final boolean configurationState = packetWrapper.user().get(FakeProtocolState.class).isConfigurationState();
if (direction == Direction.SERVERBOUND) {
// Redirect packets during the fake configuration phase
// This might mess up people using Via API/other protocols down the line, but such is life. We can't have different states for server and client
final State newState = configurationState ? State.CONFIGURATION : state;
super.transform(direction, newState, packetWrapper);
return;
public void transform(final Direction direction, final State state, final PacketWrapper packetWrapper) throws Exception {
final FakeProtocolState fakeProtocolState = packetWrapper.user().get(FakeProtocolState.class);
if (fakeProtocolState.hasGameProfileBeenSent() && !fakeProtocolState.isConfigurationState()) {
fakeProtocolState.addPacketToQueue(packetWrapper, direction == Direction.CLIENTBOUND);
System.out.println("added to queue " + packetWrapper.getId() + " " + direction + " " + state);
super.transform(direction, State.PLAY, packetWrapper);
throw CancelException.generate();
}
// Make sure we don't send the client any packets from another protocol state
if (configurationState) {
// TODO Queue these packets to send them later
Via.getPlatform().getLogger().warning("Cancelled packet " + packetWrapper.getId() + " sent during configuration state");
packetWrapper.cancel();
System.out.println("Transforming " + packetWrapper.getId() + " " + direction + " " + state);
System.out.println(fakeProtocolState.isConfigurationState());
if (!fakeProtocolState.isConfigurationState()) {
super.transform(direction, state, packetWrapper);
return;
}
// Map some of them to their configuration state counterparts
final int unmappedId = packetWrapper.getId();
if (state == State.PLAY && unmappedId != ClientboundPackets1_19_4.JOIN_GAME.getId()) {
if (unmappedId == ClientboundPackets1_19_4.PLUGIN_MESSAGE.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD);
} else if (unmappedId == ClientboundPackets1_19_4.DISCONNECT.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.DISCONNECT);
} else if (unmappedId == ClientboundPackets1_19_4.KEEP_ALIVE.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.KEEP_ALIVE);
} else if (unmappedId == ClientboundPackets1_19_4.PING.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.PING);
} else if (unmappedId == ClientboundPackets1_19_4.RESOURCE_PACK.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.RESOURCE_PACK);
} else if (unmappedId == ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.UPDATE_ENABLED_FEATURES);
} else if (unmappedId == ClientboundPackets1_19_4.TAGS.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.UPDATE_TAGS);
}
return;
}
if (direction == Direction.CLIENTBOUND
&& (packetWrapper.getPacketType() == null || packetWrapper.getPacketType().state() != State.CONFIGURATION)) {
// Map some of them to their configuration state counterparts
final int unmappedId = packetWrapper.getId();
if (state == State.PLAY && unmappedId != ClientboundPackets1_19_4.JOIN_GAME.getId()) {
if (unmappedId == ClientboundPackets1_19_4.PLUGIN_MESSAGE.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD);
} else if (unmappedId == ClientboundPackets1_19_4.DISCONNECT.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.DISCONNECT);
} else if (unmappedId == ClientboundPackets1_19_4.KEEP_ALIVE.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.KEEP_ALIVE);
} else if (unmappedId == ClientboundPackets1_19_4.PING.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.PING);
} else if (unmappedId == ClientboundPackets1_19_4.RESOURCE_PACK.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.RESOURCE_PACK);
} else if (unmappedId == ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.UPDATE_ENABLED_FEATURES);
} else if (unmappedId == ClientboundPackets1_19_4.TAGS.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.UPDATE_TAGS);
} else {
// TODO Queue these packets to send them later
Via.getPlatform().getLogger().warning("Cancelled packet " + packetWrapper.getId() + " sent during configuration state");
packetWrapper.cancel();
return;
}
super.transform(direction, state, packetWrapper);
super.transform(direction, State.CONFIGURATION, packetWrapper);
}
} else {
// Redirect packets during the fake configuration phase
// This might mess up people using Via API/other protocols down the line, but such is life. We can't have different states for server and client
super.transform(direction, State.CONFIGURATION, packetWrapper);
}
}
@Override

View File

@ -17,17 +17,28 @@
*/
package com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter;
import com.viaversion.viaversion.api.data.ParticleMappings;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.ChunkPosition;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_18to1_17_1.types.Chunk1_18Type;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ClientboundPackets1_19_4;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.rewriter.RecipeRewriter1_19_4;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.Protocol1_20_2To1_20;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ServerboundPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.types.Chunk1_20_2Type;
import com.viaversion.viaversion.protocols.protocol1_20to1_19_4.Protocol1_20To1_19_4;
import com.viaversion.viaversion.rewriter.ItemRewriter;
import com.viaversion.viaversion.util.MathUtil;
public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<ClientboundPackets1_19_4, ServerboundPackets1_20_2, Protocol1_20_2To1_20> {
public BlockItemPacketRewriter1_20_2(final Protocol1_20_2To1_20 protocol) {
super(protocol);
super(protocol, Type.ITEM1_20_2, Type.ITEM1_20_2_VAR_INT_ARRAY);
}
@Override
@ -37,5 +48,250 @@ public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<Clientboun
final int z = wrapper.read(Type.INT);
wrapper.write(Type.CHUNK_POSITION, new ChunkPosition(x, z));
});
protocol.registerClientbound(ClientboundPackets1_19_4.NBT_QUERY, wrapper -> {
wrapper.passthrough(Type.VAR_INT); // Transaction id
wrapper.write(Type.NAMELESS_NBT, wrapper.read(Type.NBT));
});
protocol.registerClientbound(ClientboundPackets1_19_4.BLOCK_ENTITY_DATA, wrapper -> {
wrapper.passthrough(Type.POSITION1_14); // Position
wrapper.passthrough(Type.VAR_INT); // Type
wrapper.write(Type.NAMELESS_NBT, wrapper.read(Type.NBT));
});
protocol.registerClientbound(ClientboundPackets1_19_4.CHUNK_DATA, wrapper -> {
final EntityTracker tracker = protocol.getEntityRewriter().tracker(wrapper.user());
final Type<Chunk> chunkType = new Chunk1_18Type(tracker.currentWorldSectionHeight(),
MathUtil.ceilLog2(Protocol1_20To1_19_4.MAPPINGS.getBlockStateMappings().mappedSize()),
MathUtil.ceilLog2(tracker.biomesSent()));
final Chunk chunk = wrapper.read(chunkType);
final Type<Chunk> newChunkType = new Chunk1_20_2Type(tracker.currentWorldSectionHeight(),
MathUtil.ceilLog2(Protocol1_20To1_19_4.MAPPINGS.getBlockStateMappings().mappedSize()),
MathUtil.ceilLog2(tracker.biomesSent()));
wrapper.write(newChunkType, chunk);
});
// Weeeeeeeeeeeeeeeeeeeeeeeeeeeeee
protocol.registerClientbound(ClientboundPackets1_19_4.WINDOW_ITEMS, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE); // Window id
map(Type.VAR_INT); // State id
handler(wrapper -> {
wrapper.write(Type.ITEM1_20_2_VAR_INT_ARRAY, wrapper.read(Type.FLAT_ITEM_ARRAY_VAR_INT)); // Items
wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM)); // Carried item
});
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.SET_SLOT, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE); // Window id
map(Type.VAR_INT); // State id
map(Type.SHORT); // Slot id
map(Type.FLAT_VAR_INT_ITEM, Type.ITEM1_20_2); // Item
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.ADVANCEMENTS, wrapper -> {
wrapper.passthrough(Type.BOOLEAN); // Reset/clear
int size = wrapper.passthrough(Type.VAR_INT); // Mapping size
for (int i = 0; i < size; i++) {
wrapper.passthrough(Type.STRING); // Identifier
// Parent
if (wrapper.passthrough(Type.BOOLEAN))
wrapper.passthrough(Type.STRING);
// Display data
if (wrapper.passthrough(Type.BOOLEAN)) {
wrapper.passthrough(Type.COMPONENT); // Title
wrapper.passthrough(Type.COMPONENT); // Description
wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM)); // Icon
wrapper.passthrough(Type.VAR_INT); // Frame type
int flags = wrapper.passthrough(Type.INT); // Flags
if ((flags & 1) != 0) {
wrapper.passthrough(Type.STRING); // Background texture
}
wrapper.passthrough(Type.FLOAT); // X
wrapper.passthrough(Type.FLOAT); // Y
}
wrapper.passthrough(Type.STRING_ARRAY); // Criteria
int arrayLength = wrapper.passthrough(Type.VAR_INT);
for (int array = 0; array < arrayLength; array++) {
wrapper.passthrough(Type.STRING_ARRAY); // String array
}
wrapper.passthrough(Type.BOOLEAN); // Send telemetry
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.ENTITY_EQUIPMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // 0 - Entity ID
handler(wrapper -> {
byte slot;
do {
slot = wrapper.passthrough(Type.BYTE);
wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM));
} while ((slot & 0xFFFFFF80) != 0);
});
}
});
protocol.registerServerbound(ServerboundPackets1_20_2.CLICK_WINDOW, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE); // Window Id
map(Type.VAR_INT); // State id
map(Type.SHORT); // Slot
map(Type.BYTE); // Button
map(Type.VAR_INT); // Mode
handler(wrapper -> {
// Affected items
int length = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < length; i++) {
wrapper.passthrough(Type.SHORT); // Slot
wrapper.write(Type.FLAT_VAR_INT_ITEM, wrapper.read(Type.ITEM1_20_2));
}
// Carried item
wrapper.write(Type.FLAT_VAR_INT_ITEM, wrapper.read(Type.ITEM1_20_2));
});
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.TRADE_LIST, wrapper -> {
wrapper.passthrough(Type.VAR_INT); // Container id
int size = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < size; i++) {
wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM)); // Input
wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM)); // Output
wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM)); // Second Item
wrapper.passthrough(Type.BOOLEAN); // Trade disabled
wrapper.passthrough(Type.INT); // Number of tools uses
wrapper.passthrough(Type.INT); // Maximum number of trade uses
wrapper.passthrough(Type.INT); // XP
wrapper.passthrough(Type.INT); // Special price
wrapper.passthrough(Type.FLOAT); // Price multiplier
wrapper.passthrough(Type.INT); // Demand
}
});
protocol.registerServerbound(ServerboundPackets1_20_2.CREATIVE_INVENTORY_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.SHORT); // 0 - Slot
map(Type.ITEM1_20_2, Type.FLAT_VAR_INT_ITEM); // 1 - Clicked Item
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.SPAWN_PARTICLE, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // 0 - Particle ID
map(Type.BOOLEAN); // 1 - Long Distance
map(Type.DOUBLE); // 2 - X
map(Type.DOUBLE); // 3 - Y
map(Type.DOUBLE); // 4 - Z
map(Type.FLOAT); // 5 - Offset X
map(Type.FLOAT); // 6 - Offset Y
map(Type.FLOAT); // 7 - Offset Z
map(Type.FLOAT); // 8 - Particle Data
map(Type.INT); // 9 - Particle Count
handler(wrapper -> {
int id = wrapper.get(Type.VAR_INT, 0);
ParticleMappings mappings = Protocol1_20To1_19_4.MAPPINGS.getParticleMappings();
if (mappings.isItemParticle(id)) {
wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM));
}
});
}
});
new RecipeRewriter1_19_4<ClientboundPackets1_19_4>(protocol) {
@Override
public void handleCraftingShapeless(final PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.STRING); // Group
wrapper.passthrough(Type.VAR_INT); // Crafting book category
handleIngredients(wrapper);
final Item result = wrapper.read(itemType());
rewrite(result);
wrapper.write(Type.ITEM1_20_2, result);
}
@Override
public void handleSmelting(final PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.STRING); // Group
wrapper.passthrough(Type.VAR_INT); // Crafting book category
handleIngredient(wrapper);
final Item result = wrapper.read(itemType());
rewrite(result);
wrapper.write(Type.ITEM1_20_2, result);
wrapper.passthrough(Type.FLOAT); // EXP
wrapper.passthrough(Type.VAR_INT); // Cooking time
}
@Override
public void handleCraftingShaped(final PacketWrapper wrapper) throws Exception {
final int ingredients = wrapper.passthrough(Type.VAR_INT) * wrapper.passthrough(Type.VAR_INT);
wrapper.passthrough(Type.STRING); // Group
wrapper.passthrough(Type.VAR_INT); // Crafting book category
for (int i = 0; i < ingredients; i++) {
handleIngredient(wrapper);
}
final Item result = wrapper.read(itemType());
rewrite(result);
wrapper.write(Type.ITEM1_20_2, result);
wrapper.passthrough(Type.BOOLEAN); // Show notification
}
@Override
public void handleStonecutting(final PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.STRING); // Group
handleIngredient(wrapper);
final Item result = wrapper.read(itemType());
rewrite(result);
wrapper.write(Type.ITEM1_20_2, result);
}
@Override
public void handleSmithing(final PacketWrapper wrapper) throws Exception {
handleIngredient(wrapper); // Base
handleIngredient(wrapper); // Addition
final Item result = wrapper.read(itemType());
rewrite(result);
wrapper.write(Type.ITEM1_20_2, result);
}
@Override
public void handleSmithingTransform(final PacketWrapper wrapper) throws Exception {
handleIngredient(wrapper); // Template
handleIngredient(wrapper); // Base
handleIngredient(wrapper); // Additions
final Item result = wrapper.read(itemType());
rewrite(result);
wrapper.write(Type.ITEM1_20_2, result);
}
@Override
protected void handleIngredient(final PacketWrapper wrapper) throws Exception {
final Item[] items = wrapper.read(itemArrayType());
wrapper.write(Type.ITEM1_20_2_VAR_INT_ARRAY, items);
for (final Item item : items) {
rewrite(item);
}
}
}.register(ClientboundPackets1_19_4.DECLARE_RECIPES);
}
}

View File

@ -18,11 +18,10 @@
package com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_19_4Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_20;
@ -32,8 +31,6 @@ import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.Protocol1_20_2To
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ClientboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import java.util.List;
public final class EntityPacketRewriter1_20_2 extends EntityRewriter<ClientboundPackets1_19_4, Protocol1_20_2To1_20> {
public EntityPacketRewriter1_20_2(final Protocol1_20_2To1_20 protocol) {
@ -95,6 +92,11 @@ public final class EntityPacketRewriter1_20_2 extends EntityRewriter<Clientbound
enableFeaturesPacket.write(Type.STRING, "minecraft:vanilla");
enableFeaturesPacket.scheduleSend(Protocol1_20_2To1_20.class);
final PacketWrapper finishConfigurationPacket = wrapper.create(ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION);
finishConfigurationPacket.send(Protocol1_20_2To1_20.class);
System.out.println("PLEASEEEEEEEE");
// Manually send it at the end and hope nothing breaks
wrapper.send(Protocol1_20_2To1_20.class);
wrapper.cancel();
@ -126,6 +128,17 @@ public final class EntityPacketRewriter1_20_2 extends EntityRewriter<Clientbound
handler(worldDataTrackerHandlerByKey()); // Tracks world height and name for chunk data and entity (un)tracking
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.ENTITY_EFFECT, wrapper -> {
wrapper.passthrough(Type.VAR_INT); // Entity id
wrapper.passthrough(Type.VAR_INT); // Effect id
wrapper.passthrough(Type.BYTE); // Amplifier
wrapper.passthrough(Type.VAR_INT); // Duration
wrapper.passthrough(Type.BYTE); // Flags
if (wrapper.passthrough(Type.BOOLEAN)) {
wrapper.write(Type.NAMELESS_NBT, wrapper.read(Type.NBT)); // Factor data
}
});
}
@Override

View File

@ -0,0 +1,41 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.rewriter.RecipeRewriter1_19_4;
public class RecipeRewriter1_20_2<C extends ClientboundPacketType> extends RecipeRewriter1_19_4<C> {
public RecipeRewriter1_20_2(final Protocol<C, ?, ?, ?> protocol) {
super(protocol);
}
@Override
protected Type<Item> itemType() {
return Type.ITEM1_20_2;
}
@Override
protected Type<Item[]> itemArrayType() {
return Type.ITEM1_20_2_VAR_INT_ARRAY;
}
}

View File

@ -18,10 +18,18 @@
package com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.protocol.packet.PacketWrapperImpl;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
public class FakeProtocolState implements StorableObject {
private final List<QueuedPacket> packetQueue = new ArrayList<>();
private boolean configurationState;
private boolean gameProfileSent;
public boolean isConfigurationState() {
return configurationState;
@ -31,8 +39,42 @@ public class FakeProtocolState implements StorableObject {
this.configurationState = configurationState;
}
public void addPacketToQueue(final PacketWrapper wrapper, final boolean clientbound) {
packetQueue.add(new QueuedPacket(((PacketWrapperImpl) wrapper).getInputBuffer().copy(), clientbound)); // TODO
}
public List<QueuedPacket> packetQueue() {
return packetQueue;
}
public boolean hasGameProfileBeenSent() {
return gameProfileSent;
}
public void setGameProfileSent(final boolean gameProfileSent) {
this.gameProfileSent = gameProfileSent;
}
@Override
public boolean clearOnServerSwitch() {
return false;
}
public static final class QueuedPacket {
private final ByteBuf buf;
private final boolean clientbound;
private QueuedPacket(final ByteBuf buf, final boolean clientbound) {
this.buf = buf;
this.clientbound = clientbound;
}
public ByteBuf buf() {
return buf;
}
public boolean clientbound() {
return clientbound;
}
}
}

View File

@ -0,0 +1,102 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.protocols.protocol1_20_2to1_20.types;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk1_18;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.minecraft.BaseChunkType;
import com.viaversion.viaversion.api.type.types.version.ChunkSectionType1_18;
import com.viaversion.viaversion.api.type.types.version.Types1_18;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
public final class Chunk1_20_2Type extends Type<Chunk> {
private final ChunkSectionType1_18 sectionType;
private final int ySectionCount;
public Chunk1_20_2Type(final int ySectionCount, final int globalPaletteBlockBits, final int globalPaletteBiomeBits) {
super(Chunk.class);
Preconditions.checkArgument(ySectionCount > 0);
this.sectionType = new ChunkSectionType1_18(globalPaletteBlockBits, globalPaletteBiomeBits);
this.ySectionCount = ySectionCount;
}
@Override
public Chunk read(final ByteBuf buffer) throws Exception {
final int chunkX = buffer.readInt();
final int chunkZ = buffer.readInt();
final CompoundTag heightMap = Type.NAMELESS_NBT.read(buffer);
// Read sections
final ByteBuf sectionsBuf = buffer.readBytes(Type.VAR_INT.readPrimitive(buffer));
final ChunkSection[] sections = new ChunkSection[ySectionCount];
try {
for (int i = 0; i < ySectionCount; i++) {
sections[i] = sectionType.read(sectionsBuf);
}
} finally {
sectionsBuf.release();
}
final int blockEntitiesLength = Type.VAR_INT.readPrimitive(buffer);
final List<BlockEntity> blockEntities = new ArrayList<>(blockEntitiesLength);
for (int i = 0; i < blockEntitiesLength; i++) {
blockEntities.add(Types1_18.BLOCK_ENTITY.read(buffer));
}
return new Chunk1_18(chunkX, chunkZ, sections, heightMap, blockEntities);
}
@Override
public void write(final ByteBuf buffer, final Chunk chunk) throws Exception {
buffer.writeInt(chunk.getX());
buffer.writeInt(chunk.getZ());
Type.NAMELESS_NBT.write(buffer, chunk.getHeightMap());
final ByteBuf sectionBuffer = buffer.alloc().buffer();
try {
for (final ChunkSection section : chunk.getSections()) {
sectionType.write(sectionBuffer, section);
}
sectionBuffer.readerIndex(0);
Type.VAR_INT.writePrimitive(buffer, sectionBuffer.readableBytes());
buffer.writeBytes(sectionBuffer);
} finally {
sectionBuffer.release(); // release buffer
}
Type.VAR_INT.writePrimitive(buffer, chunk.blockEntities().size());
for (final BlockEntity blockEntity : chunk.blockEntities()) {
Types1_18.BLOCK_ENTITY.write(buffer, blockEntity);
}
}
@Override
public Class<? extends Type> getBaseClass() {
return BaseChunkType.class;
}
}

View File

@ -42,10 +42,16 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public class BlockRewriter<C extends ClientboundPacketType> {
private final Protocol<C, ?, ?, ?> protocol;
private final Type<Position> positionType;
private final Type<CompoundTag> nbtType;
public BlockRewriter(Protocol<C, ?, ?, ?> protocol, Type<Position> positionType) {
this(protocol, positionType, Type.NBT);
}
public BlockRewriter(Protocol<C, ?, ?, ?> protocol, Type<Position> positionType, Type<CompoundTag> nbtType) {
this.protocol = protocol;
this.positionType = positionType;
this.nbtType = nbtType;
}
public void registerBlockAction(C packetType) {
@ -203,7 +209,7 @@ public class BlockRewriter<C extends ClientboundPacketType> {
public void registerBlockEntityData(C packetType, @Nullable Consumer<BlockEntity> blockEntityHandler) {
protocol.registerClientbound(packetType, wrapper -> {
final Position position = wrapper.passthrough(Type.POSITION1_14);
final Position position = wrapper.passthrough(positionType);
final int blockEntityId = wrapper.read(Type.VAR_INT);
final Mappings mappings = protocol.getMappingData().getBlockEntityMappings();
@ -214,7 +220,7 @@ public class BlockRewriter<C extends ClientboundPacketType> {
}
final CompoundTag tag;
if (blockEntityHandler != null && (tag = wrapper.passthrough(Type.NBT)) != null) {
if (blockEntityHandler != null && (tag = wrapper.passthrough(nbtType)) != null) {
final BlockEntity blockEntity = new BlockEntityImpl(BlockEntity.pack(position.x(), position.z()), (short) position.y(), blockEntityId, tag);
blockEntityHandler.accept(blockEntity);
}

View File

@ -31,9 +31,17 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public abstract class ItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType,
T extends Protocol<C, ?, ?, S>> extends RewriterBase<T> implements com.viaversion.viaversion.api.rewriter.ItemRewriter<T> {
private final Type<Item> itemType;
private final Type<Item[]> itemArrayType;
protected ItemRewriter(T protocol) {
this(protocol, Type.FLAT_VAR_INT_ITEM, Type.FLAT_VAR_INT_ITEM_ARRAY);
}
public ItemRewriter(T protocol, Type<Item> itemType, Type<Item[]> itemArrayType) {
super(protocol);
this.itemType = itemType;
this.itemArrayType = itemArrayType;
}
// These two methods always return the same item instance *for now*
@ -74,12 +82,12 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
map(Type.UNSIGNED_BYTE); // Window id
map(Type.VAR_INT); // State id
handler(wrapper -> {
Item[] items = wrapper.passthrough(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT);
Item[] items = wrapper.passthrough(itemArrayType);
for (Item item : items) {
handleItemToClient(item);
}
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Carried item
handleItemToClient(wrapper.passthrough(itemType)); // Carried item
});
}
});
@ -123,8 +131,8 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
map(Type.UNSIGNED_BYTE); // Window id
map(Type.VAR_INT); // State id
map(Type.SHORT); // Slot id
map(Type.FLAT_VAR_INT_ITEM); // Item
handler(itemToClientHandler(Type.FLAT_VAR_INT_ITEM));
map(itemType); // Item
handler(itemToClientHandler(itemType));
}
});
}
@ -155,7 +163,7 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
do {
slot = wrapper.passthrough(Type.BYTE);
// & 0x7F into an extra variable if slot is needed
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM));
handleItemToClient(wrapper.passthrough(itemType));
} while ((slot & 0xFFFFFF80) != 0);
});
}
@ -168,7 +176,6 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
public void register() {
map(Type.SHORT); // 0 - Slot
map(type); // 1 - Clicked Item
handler(itemToServerHandler(type));
}
});
@ -205,11 +212,11 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
int length = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < length; i++) {
wrapper.passthrough(Type.SHORT); // Slot
handleItemToServer(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM));
handleItemToServer(wrapper.passthrough(itemType));
}
// Carried item
handleItemToServer(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM));
handleItemToServer(wrapper.passthrough(itemType));
});
}
});
@ -228,11 +235,11 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
wrapper.passthrough(Type.VAR_INT);
int size = wrapper.passthrough(Type.UNSIGNED_BYTE);
for (int i = 0; i < size; i++) {
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Input
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Output
handleItemToClient(wrapper.passthrough(itemType)); // Input
handleItemToClient(wrapper.passthrough(itemType)); // Output
if (wrapper.passthrough(Type.BOOLEAN)) { // Has second item
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Second Item
handleItemToClient(wrapper.passthrough(itemType)); // Second Item
}
wrapper.passthrough(Type.BOOLEAN); // Trade disabled
@ -253,9 +260,9 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
wrapper.passthrough(Type.VAR_INT); // Container id
int size = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < size; i++) {
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Input
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Output
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Second Item
handleItemToClient(wrapper.passthrough(itemType)); // Input
handleItemToClient(wrapper.passthrough(itemType)); // Output
handleItemToClient(wrapper.passthrough(itemType)); // Second Item
wrapper.passthrough(Type.BOOLEAN); // Trade disabled
wrapper.passthrough(Type.INT); // Number of tools uses
@ -304,7 +311,7 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
});
}
public void registerAdvancements1_20(C packetType, Type<Item> type) {
public void registerAdvancements1_20(C packetType) {
protocol.registerClientbound(packetType, wrapper -> {
wrapper.passthrough(Type.BOOLEAN); // Reset/clear
int size = wrapper.passthrough(Type.VAR_INT); // Mapping size
@ -319,7 +326,7 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
if (wrapper.passthrough(Type.BOOLEAN)) {
wrapper.passthrough(Type.COMPONENT); // Title
wrapper.passthrough(Type.COMPONENT); // Description
handleItemToClient(wrapper.passthrough(type)); // Icon
handleItemToClient(wrapper.passthrough(itemType)); // Icon
wrapper.passthrough(Type.VAR_INT); // Frame type
int flags = wrapper.passthrough(Type.INT); // Flags
if ((flags & 1) != 0) {
@ -396,7 +403,7 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
map(Type.FLOAT); // 7 - Offset Z
map(Type.FLOAT); // 8 - Particle Data
map(Type.INT); // 9 - Particle Count
handler(getSpawnParticleHandler(Type.VAR_INT, Type.FLAT_VAR_INT_ITEM));
handler(getSpawnParticleHandler(Type.VAR_INT, itemType));
}
});
}

View File

@ -82,19 +82,19 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
for (int i = 0; i < ingredientsNo; i++) {
handleIngredient(wrapper);
}
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
}
public void handleCraftingShapeless(PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.STRING); // Group
handleIngredients(wrapper);
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
}
public void handleSmelting(PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.STRING); // Group
handleIngredient(wrapper);
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
wrapper.passthrough(Type.FLOAT); // EXP
wrapper.passthrough(Type.VAR_INT); // Cooking time
}
@ -102,13 +102,13 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
public void handleStonecutting(PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.STRING); // Group
handleIngredient(wrapper);
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
}
public void handleSmithing(PacketWrapper wrapper) throws Exception {
handleIngredient(wrapper); // Base
handleIngredient(wrapper); // Addition
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
}
public void handleSimpleRecipe(final PacketWrapper wrapper) throws Exception {
@ -119,7 +119,7 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
handleIngredient(wrapper); // Template
handleIngredient(wrapper); // Base
handleIngredient(wrapper); // Additions
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
}
public void handleSmithingTrim(final PacketWrapper wrapper) throws Exception {
@ -135,7 +135,7 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
}
protected void handleIngredient(final PacketWrapper wrapper) throws Exception {
final Item[] items = wrapper.passthrough(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT);
final Item[] items = wrapper.passthrough(itemArrayType());
for (final Item item : items) {
rewrite(item);
}
@ -153,4 +153,12 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
void accept(PacketWrapper wrapper) throws Exception;
}
protected Type<Item> itemType() {
return Type.FLAT_VAR_INT_ITEM;
}
protected Type<Item[]> itemArrayType() {
return Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT;
}
}