Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8acae2d5f | ||
|
|
fdb7f47749 | ||
|
|
cabb95a3a4 | ||
|
|
0b93af88a3 | ||
|
|
11cb113619 | ||
|
|
429e4f0bff | ||
|
|
3b0d1d961a | ||
|
|
b4720c723a | ||
|
|
215cbc6310 | ||
|
|
f07ba9b527 | ||
|
|
5a20030ff3 | ||
|
|
1b350c0c53 | ||
|
|
87db6fc75a | ||
|
|
840770a350 | ||
|
|
3997ea70f7 | ||
|
|
854696abff | ||
|
|
d92b9fdeaa | ||
|
|
270d28f259 | ||
|
|
ed1852ba40 | ||
|
|
f91e6a83f9 | ||
|
|
8a0e187621 | ||
|
|
0e8b5e8e98 | ||
|
|
e30dd63b3c |
No files matched your search
@@ -83,7 +83,7 @@ Resources
|
||||
--------
|
||||
|
||||
- **[Via Mappings Generator](https://github.com/ViaVersion/Mappings)**
|
||||
- **[Mojang mappings](https://minecraft.fandom.com/wiki/Obfuscation_map)** (Thank you, Mojang, very cool)
|
||||
- **[Mojang mappings](https://minecraft.wiki/w/Obfuscation_map)** (Thank you, Mojang, very cool)
|
||||
- **[wiki.vg](https://wiki.vg)** (Used for historic information regarding packet structure, we also contribute back)
|
||||
- **[Burger](https://github.com/Pokechu22/Burger)** (See [PAaaS](https://github.com/Matsv/Paaas))
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
package com.viaversion.viaversion.api.connection;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.ProtocolPipeline;
|
||||
import com.viaversion.viaversion.api.protocol.packet.Direction;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import java.util.UUID;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
@@ -33,10 +34,63 @@ public interface ProtocolInfo {
|
||||
* Returns the protocol state the user is currently in.
|
||||
*
|
||||
* @return protocol state
|
||||
* @deprecated server and client can be in different states, use {@link #getClientState()} or {@link #getServerState()}
|
||||
*/
|
||||
State getState();
|
||||
@Deprecated/*(forRemoval = true)*/
|
||||
default State getState() {
|
||||
return this.getServerState();
|
||||
}
|
||||
|
||||
void setState(State state);
|
||||
/**
|
||||
* Returns the protocol state the client is currently in.
|
||||
*
|
||||
* @return the client protocol state
|
||||
*/
|
||||
State getClientState();
|
||||
|
||||
/**
|
||||
* Returns the protocol state the server is currently in.
|
||||
*
|
||||
* @return the server protocol state
|
||||
*/
|
||||
State getServerState();
|
||||
|
||||
/**
|
||||
* Returns the protocol state for the given direction.
|
||||
*
|
||||
* @param direction protocol direction
|
||||
* @return state for the given direction
|
||||
*/
|
||||
default State getState(final Direction direction) {
|
||||
// Return the state the packet is coming from
|
||||
return direction == Direction.CLIENTBOUND ? this.getServerState() : this.getClientState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets both client and server state.
|
||||
*
|
||||
* @param state the new protocol state
|
||||
* @see #setClientState(State)
|
||||
* @see #setServerState(State)
|
||||
*/
|
||||
default void setState(final State state) {
|
||||
this.setClientState(state);
|
||||
this.setServerState(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the client protocol state.
|
||||
*
|
||||
* @param clientState the new client protocol state
|
||||
*/
|
||||
void setClientState(State clientState);
|
||||
|
||||
/**
|
||||
* Sets the server protocol state.
|
||||
*
|
||||
* @param serverState the new server protocol state
|
||||
*/
|
||||
void setServerState(State serverState);
|
||||
|
||||
/**
|
||||
* Returns the user's protocol version, or -1 if not set.
|
||||
|
||||
@@ -96,19 +96,7 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
initialized = true;
|
||||
|
||||
registerPackets();
|
||||
|
||||
// Register handlers for protocol state switching
|
||||
// TODO Only register one of those handlers, possibly somehow in the base protocol
|
||||
final SU configurationAcknowledgedPacket = configurationAcknowledgedPacket();
|
||||
if (configurationAcknowledgedPacket != null) {
|
||||
registerServerbound(configurationAcknowledgedPacket, wrapper -> wrapper.user().getProtocolInfo().setState(State.CONFIGURATION));
|
||||
}
|
||||
|
||||
final ServerboundPacketType finishConfigurationPacket = finishConfigurationPacket();
|
||||
if (finishConfigurationPacket != null) {
|
||||
final int id = finishConfigurationPacket.getId();
|
||||
registerServerbound(State.CONFIGURATION, id, id, wrapper -> wrapper.user().getProtocolInfo().setState(State.PLAY));
|
||||
}
|
||||
registerConfigurationChangeHandlers();
|
||||
|
||||
// Register the rest of the ids with no handlers if necessary
|
||||
if (unmappedClientboundPacketType != null && mappedClientboundPacketType != null
|
||||
@@ -131,6 +119,33 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerConfigurationChangeHandlers() {
|
||||
// Register handlers for protocol state switching
|
||||
// Assuming ids will change too often, it is cleaner to register them here instead of the base protocols,
|
||||
// even if there will be multiple of these handlers
|
||||
final SU configurationAcknowledgedPacket = configurationAcknowledgedPacket();
|
||||
if (configurationAcknowledgedPacket != null) {
|
||||
registerServerbound(configurationAcknowledgedPacket, setClientStateHandler(State.CONFIGURATION));
|
||||
}
|
||||
|
||||
final CU startConfigurationPacket = startConfigurationPacket();
|
||||
if (startConfigurationPacket != null) {
|
||||
registerClientbound(startConfigurationPacket, setServerStateHandler(State.CONFIGURATION));
|
||||
}
|
||||
|
||||
final ServerboundPacketType finishConfigurationPacket = serverboundFinishConfigurationPacket();
|
||||
if (finishConfigurationPacket != null) {
|
||||
final int id = finishConfigurationPacket.getId();
|
||||
registerServerbound(State.CONFIGURATION, id, id, setClientStateHandler(State.PLAY));
|
||||
}
|
||||
|
||||
final ClientboundPacketType clientboundFinishConfigurationPacket = clientboundFinishConfigurationPacket();
|
||||
if (clientboundFinishConfigurationPacket != null) {
|
||||
final int id = clientboundFinishConfigurationPacket.getId();
|
||||
registerClientbound(State.CONFIGURATION, id, id, setServerStateHandler(State.PLAY));
|
||||
}
|
||||
}
|
||||
|
||||
private <U extends PacketType, M extends PacketType> void registerPacketIdChanges(
|
||||
Map<State, PacketTypeMap<U>> unmappedPacketTypes,
|
||||
Map<State, PacketTypeMap<M>> mappedPacketTypes,
|
||||
@@ -228,7 +243,18 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
return packetTypeMap != null ? packetTypeMap.typeByName("CONFIGURATION_ACKNOWLEDGED") : null;
|
||||
}
|
||||
|
||||
protected @Nullable ServerboundPacketType finishConfigurationPacket() {
|
||||
protected @Nullable CU startConfigurationPacket() {
|
||||
final Map<State, PacketTypeMap<CU>> packetTypes = packetTypesProvider.unmappedClientboundPacketTypes();
|
||||
final PacketTypeMap<CU> packetTypeMap = packetTypes.get(State.PLAY);
|
||||
return packetTypeMap != null ? packetTypeMap.typeByName("START_CONFIGURATION") : null;
|
||||
}
|
||||
|
||||
protected @Nullable ServerboundPacketType serverboundFinishConfigurationPacket() {
|
||||
// To be overridden
|
||||
return null;
|
||||
}
|
||||
|
||||
protected @Nullable ClientboundPacketType clientboundFinishConfigurationPacket() {
|
||||
// To be overridden
|
||||
return null;
|
||||
}
|
||||
@@ -429,6 +455,14 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
}
|
||||
}
|
||||
|
||||
protected PacketHandler setClientStateHandler(final State state) {
|
||||
return wrapper -> wrapper.user().getProtocolInfo().setClientState(state);
|
||||
}
|
||||
|
||||
protected PacketHandler setServerStateHandler(final State state) {
|
||||
return wrapper -> wrapper.user().getProtocolInfo().setClientState(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketTypesProvider<CU, CM, SM, SU> getPacketTypesProvider() {
|
||||
return packetTypesProvider;
|
||||
|
||||
@@ -69,10 +69,17 @@ public interface ProtocolPipeline extends SimpleProtocol {
|
||||
/**
|
||||
* Returns the list of protocols this pipeline contains.
|
||||
*
|
||||
* @return list of protocols in this pipe
|
||||
* @return immutable list of protocols in this pipe
|
||||
*/
|
||||
List<Protocol> pipes();
|
||||
|
||||
/**
|
||||
* Returns the list of protocols this pipeline contains in reversed order.
|
||||
*
|
||||
* @return immutable list of protocols in reversed direction
|
||||
*/
|
||||
List<Protocol> reversedPipes();
|
||||
|
||||
/**
|
||||
* Returns whether this pipe has protocols that are not base protocols, as given by {@link Protocol#isBaseProtocol()}.
|
||||
*
|
||||
|
||||
@@ -27,6 +27,6 @@ public enum State {
|
||||
HANDSHAKE,
|
||||
STATUS,
|
||||
LOGIN,
|
||||
PLAY,
|
||||
CONFIGURATION
|
||||
CONFIGURATION,
|
||||
PLAY
|
||||
}
|
||||
@@ -28,9 +28,8 @@ import com.viaversion.viaversion.api.type.Type;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
import io.netty.buffer.ByteBufOutputStream;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class NBTType extends Type<CompoundTag> {
|
||||
|
||||
@@ -42,37 +41,31 @@ public class NBTType extends Type<CompoundTag> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag read(ByteBuf buffer) throws Exception {
|
||||
public CompoundTag read(final ByteBuf buffer) throws Exception {
|
||||
return read(buffer, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, CompoundTag object) throws Exception {
|
||||
public void write(final ByteBuf buffer, final CompoundTag object) throws Exception {
|
||||
write(buffer, object, "");
|
||||
}
|
||||
|
||||
public static CompoundTag read(final ByteBuf buffer, final boolean readName) throws Exception {
|
||||
final int readerIndex = buffer.readerIndex();
|
||||
final byte b = buffer.readByte();
|
||||
if (b == 0) {
|
||||
final byte id = buffer.readByte();
|
||||
if (id == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
buffer.readerIndex(readerIndex);
|
||||
|
||||
final ByteBufInputStream in = new ByteBufInputStream(buffer);
|
||||
final int id = in.readByte();
|
||||
if (id != CompoundTag.ID) {
|
||||
throw new IOException(String.format("Expected root tag to be a CompoundTag, was %s", id));
|
||||
}
|
||||
|
||||
if (readName) {
|
||||
in.skipBytes(in.readUnsignedShort());
|
||||
buffer.skipBytes(buffer.readUnsignedShort());
|
||||
}
|
||||
|
||||
final TagLimiter tagLimiter = TagLimiter.create(MAX_NBT_BYTES, MAX_NESTING_LEVEL);
|
||||
final CompoundTag tag = new CompoundTag();
|
||||
tag.read(in, tagLimiter);
|
||||
tag.read(new ByteBufInputStream(buffer), tagLimiter);
|
||||
return tag;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ fun Project.latestCommitMessage(): String {
|
||||
fun Project.branchName(): String {
|
||||
val byteOut = ByteArrayOutputStream()
|
||||
exec {
|
||||
commandLine = listOf("git", "branch")
|
||||
commandLine = listOf("git", "rev-parse", "--abbrev-ref", "HEAD")
|
||||
standardOutput = byteOut
|
||||
}
|
||||
return byteOut.toString(Charsets.UTF_8.name()).trim()
|
||||
|
||||
@@ -46,8 +46,8 @@ public class JoinListener implements Listener {
|
||||
Field gamePacketListenerField = null, connectionField = null, channelField = null;
|
||||
try {
|
||||
getHandleMethod = NMSUtil.obc("entity.CraftPlayer").getDeclaredMethod("getHandle");
|
||||
gamePacketListenerField = findField(getHandleMethod.getReturnType(), "PlayerConnection", "ServerGamePacketListenerImpl");
|
||||
connectionField = findField(gamePacketListenerField.getType(), "NetworkManager", "Connection");
|
||||
gamePacketListenerField = findField(false, getHandleMethod.getReturnType(), "PlayerConnection", "ServerGamePacketListenerImpl");
|
||||
connectionField = findField(true, gamePacketListenerField.getType(), "NetworkManager", "Connection");
|
||||
channelField = findField(connectionField.getType(), Class.forName("io.netty.channel.Channel"));
|
||||
} catch (NoSuchMethodException | NoSuchFieldException | ClassNotFoundException e) {
|
||||
Via.getPlatform().getLogger().log(
|
||||
@@ -63,8 +63,8 @@ public class JoinListener implements Listener {
|
||||
}
|
||||
|
||||
// Loosely search a field with any name, as long as it matches a type name.
|
||||
private static Field findField(Class<?> clazz, String... types) throws NoSuchFieldException {
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
private static Field findField(boolean all, Class<?> clazz, String... types) throws NoSuchFieldException {
|
||||
for (Field field : all ? clazz.getFields() : clazz.getDeclaredFields()) {
|
||||
String fieldTypeName = field.getType().getSimpleName();
|
||||
for (String type : types) {
|
||||
if (!fieldTypeName.equals(type)) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.connection;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.ProtocolInfo;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.ProtocolPipeline;
|
||||
@@ -26,25 +27,42 @@ import java.util.UUID;
|
||||
|
||||
public class ProtocolInfoImpl implements ProtocolInfo {
|
||||
private final UserConnection connection;
|
||||
private State state = State.HANDSHAKE;
|
||||
private State clientState = State.HANDSHAKE;
|
||||
private State serverState = State.HANDSHAKE;
|
||||
private int protocolVersion = -1;
|
||||
private int serverProtocolVersion = -1;
|
||||
private String username;
|
||||
private UUID uuid;
|
||||
private ProtocolPipeline pipeline;
|
||||
|
||||
public ProtocolInfoImpl(UserConnection connection) {
|
||||
public ProtocolInfoImpl(final UserConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getState() {
|
||||
return state;
|
||||
public State getClientState() {
|
||||
return clientState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
public void setClientState(final State clientState) {
|
||||
if (Via.getManager().debugHandler().enabled()) {
|
||||
Via.getPlatform().getLogger().info("Client state changed from " + this.clientState + " to " + clientState + " for " + connection.getProtocolInfo().getUuid());
|
||||
}
|
||||
this.clientState = clientState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getServerState() {
|
||||
return serverState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServerState(final State serverState) {
|
||||
if (Via.getManager().debugHandler().enabled()) {
|
||||
Via.getPlatform().getLogger().info("Server state changed from " + this.serverState + " to " + serverState + " for " + connection.getProtocolInfo().getUuid());
|
||||
}
|
||||
this.serverState = serverState;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -108,7 +126,8 @@ public class ProtocolInfoImpl implements ProtocolInfo {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ProtocolInfo{" +
|
||||
"state=" + state +
|
||||
"clientState=" + clientState +
|
||||
", serverState=" + serverState +
|
||||
", protocolVersion=" + protocolVersion +
|
||||
", serverProtocolVersion=" + serverProtocolVersion +
|
||||
", username='" + username + '\'' +
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.Direction;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketTracker;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.exception.CancelException;
|
||||
import com.viaversion.viaversion.protocol.packet.PacketWrapperImpl;
|
||||
@@ -324,8 +325,9 @@ public class UserConnectionImpl implements UserConnection {
|
||||
}
|
||||
|
||||
PacketWrapper wrapper = new PacketWrapperImpl(id, buf, this);
|
||||
State state = protocolInfo.getState(direction);
|
||||
try {
|
||||
protocolInfo.getPipeline().transform(direction, protocolInfo.getState(), wrapper);
|
||||
protocolInfo.getPipeline().transform(direction, state, wrapper);
|
||||
} catch (CancelException ex) {
|
||||
throw cancelSupplier.apply(ex);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class EntityTrackerBase implements EntityTracker, ClientEntityIdChangeLis
|
||||
private final UserConnection connection;
|
||||
private final EntityType playerType;
|
||||
private int clientEntityId = -1;
|
||||
private int currentWorldSectionHeight = 16;
|
||||
private int currentWorldSectionHeight = -1;
|
||||
private int currentMinY;
|
||||
private String currentWorld;
|
||||
private int biomesSent = -1;
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.protocol;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.debug.DebugHandler;
|
||||
@@ -30,9 +29,10 @@ import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.logging.Level;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
@@ -42,8 +42,10 @@ public class ProtocolPipelineImpl extends AbstractSimpleProtocol implements Prot
|
||||
/**
|
||||
* Protocol list ordered from client to server transforation with the base protocols at the end.
|
||||
*/
|
||||
private List<Protocol> protocolList;
|
||||
private Set<Class<? extends Protocol>> protocolSet;
|
||||
private final List<Protocol> protocolList = new CopyOnWriteArrayList<>();
|
||||
private final Set<Class<? extends Protocol>> protocolSet = new HashSet<>();
|
||||
private List<Protocol> reversedProtocolList = new CopyOnWriteArrayList<>();
|
||||
private int baseProtocols;
|
||||
|
||||
public ProtocolPipelineImpl(UserConnection userConnection) {
|
||||
this.userConnection = userConnection;
|
||||
@@ -53,14 +55,12 @@ public class ProtocolPipelineImpl extends AbstractSimpleProtocol implements Prot
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
protocolList = new CopyOnWriteArrayList<>();
|
||||
// Create a backing set for faster contains calls with larger pipes
|
||||
protocolSet = Sets.newSetFromMap(new ConcurrentHashMap<>());
|
||||
|
||||
// This is a pipeline so we register basic pipes
|
||||
Protocol baseProtocol = Via.getManager().getProtocolManager().getBaseProtocol();
|
||||
final Protocol<?, ?, ?, ?> baseProtocol = Via.getManager().getProtocolManager().getBaseProtocol();
|
||||
protocolList.add(baseProtocol);
|
||||
reversedProtocolList.add(baseProtocol);
|
||||
protocolSet.add(baseProtocol.getClass());
|
||||
baseProtocols++;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,44 +69,38 @@ public class ProtocolPipelineImpl extends AbstractSimpleProtocol implements Prot
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Protocol protocol) {
|
||||
protocolList.add(protocol);
|
||||
public synchronized void add(final Protocol protocol) {
|
||||
if (protocol.isBaseProtocol()) {
|
||||
// Add base protocol on top of previous ones
|
||||
protocolList.add(baseProtocols, protocol);
|
||||
reversedProtocolList.add(baseProtocols, protocol);
|
||||
baseProtocols++;
|
||||
} else {
|
||||
protocolList.add(protocol);
|
||||
reversedProtocolList.add(0, protocol);
|
||||
}
|
||||
|
||||
protocolSet.add(protocol.getClass());
|
||||
protocol.init(userConnection);
|
||||
|
||||
if (!protocol.isBaseProtocol()) {
|
||||
moveBaseProtocolsToTail();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Collection<Protocol> protocols) {
|
||||
public synchronized void add(final Collection<Protocol> protocols) {
|
||||
protocolList.addAll(protocols);
|
||||
for (Protocol protocol : protocols) {
|
||||
for (final Protocol protocol : protocols) {
|
||||
protocol.init(userConnection);
|
||||
this.protocolSet.add(protocol.getClass());
|
||||
protocolSet.add(protocol.getClass());
|
||||
}
|
||||
|
||||
moveBaseProtocolsToTail();
|
||||
refreshReversedList();
|
||||
}
|
||||
|
||||
private void moveBaseProtocolsToTail() {
|
||||
// Move base Protocols to the end, so the login packets can be modified by other protocols
|
||||
List<Protocol> baseProtocols = null;
|
||||
for (Protocol protocol : protocolList) {
|
||||
if (protocol.isBaseProtocol()) {
|
||||
if (baseProtocols == null) {
|
||||
baseProtocols = new ArrayList<>();
|
||||
}
|
||||
|
||||
baseProtocols.add(protocol);
|
||||
}
|
||||
}
|
||||
|
||||
if (baseProtocols != null) {
|
||||
protocolList.removeAll(baseProtocols);
|
||||
protocolList.addAll(baseProtocols);
|
||||
}
|
||||
private synchronized void refreshReversedList() {
|
||||
final List<Protocol> protocols = new ArrayList<>(protocolList.subList(0, this.baseProtocols));
|
||||
final List<Protocol> additionalProtocols = new ArrayList<>(protocolList.subList(this.baseProtocols, protocolList.size()));
|
||||
Collections.reverse(additionalProtocols);
|
||||
protocols.addAll(additionalProtocols);
|
||||
reversedProtocolList = new CopyOnWriteArrayList<>(protocols);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,7 +113,7 @@ public class ProtocolPipelineImpl extends AbstractSimpleProtocol implements Prot
|
||||
}
|
||||
|
||||
// Apply protocols
|
||||
packetWrapper.apply(direction, state, 0, protocolList, direction == Direction.CLIENTBOUND);
|
||||
packetWrapper.apply(direction, state, 0, protocolListFor(direction));
|
||||
super.transform(direction, state, packetWrapper);
|
||||
|
||||
if (debugHandler.enabled() && debugHandler.logPostPacketTransform() && debugHandler.shouldLog(packetWrapper, direction)) {
|
||||
@@ -127,6 +121,10 @@ public class ProtocolPipelineImpl extends AbstractSimpleProtocol implements Prot
|
||||
}
|
||||
}
|
||||
|
||||
private List<Protocol> protocolListFor(final Direction direction) {
|
||||
return Collections.unmodifiableList(direction == Direction.SERVERBOUND ? protocolList : reversedProtocolList);
|
||||
}
|
||||
|
||||
private void logPacket(Direction direction, State state, PacketWrapper packetWrapper, int originalID) {
|
||||
// Debug packet
|
||||
int clientProtocol = userConnection.getProtocolInfo().getProtocolVersion();
|
||||
@@ -166,7 +164,12 @@ public class ProtocolPipelineImpl extends AbstractSimpleProtocol implements Prot
|
||||
|
||||
@Override
|
||||
public List<Protocol> pipes() {
|
||||
return protocolList;
|
||||
return Collections.unmodifiableList(protocolList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Protocol> reversedPipes() {
|
||||
return Collections.unmodifiableList(reversedProtocolList);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+27
-10
@@ -19,6 +19,7 @@ package com.viaversion.viaversion.protocol.packet;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.ProtocolInfo;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.Direction;
|
||||
@@ -308,12 +309,18 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
* @throws Exception if it fails to write
|
||||
*/
|
||||
private ByteBuf constructPacket(Class<? extends Protocol> packetProtocol, boolean skipCurrentPipeline, Direction direction) throws Exception {
|
||||
// Apply current pipeline - for outgoing protocol, the collection will be reversed in the apply method
|
||||
Protocol[] protocols = user().getProtocolInfo().getPipeline().pipes().toArray(PROTOCOL_ARRAY);
|
||||
boolean reverse = direction == Direction.CLIENTBOUND;
|
||||
final ProtocolInfo protocolInfo = user().getProtocolInfo();
|
||||
final List<Protocol> pipes = direction == Direction.SERVERBOUND ? protocolInfo.getPipeline().pipes() : protocolInfo.getPipeline().reversedPipes();
|
||||
final List<Protocol> protocols = new ArrayList<>();
|
||||
int index = -1;
|
||||
for (int i = 0; i < protocols.length; i++) {
|
||||
if (protocols[i].getClass() == packetProtocol) {
|
||||
for (int i = 0; i < pipes.size(); i++) {
|
||||
// Always add base protocols to the head
|
||||
final Protocol protocol = pipes.get(i);
|
||||
if (protocol.isBaseProtocol()) {
|
||||
protocols.add(protocol);
|
||||
}
|
||||
|
||||
if (protocol.getClass() == packetProtocol) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
@@ -325,15 +332,18 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
}
|
||||
|
||||
if (skipCurrentPipeline) {
|
||||
index = reverse ? index - 1 : index + 1;
|
||||
index = Math.min(index + 1, pipes.size());
|
||||
}
|
||||
|
||||
// Add remaining protocols on top
|
||||
protocols.addAll(pipes.subList(index, pipes.size()));
|
||||
|
||||
// Reset reader before we start
|
||||
resetReader();
|
||||
|
||||
// Apply other protocols
|
||||
apply(direction, user().getProtocolInfo().getState(), index, protocols, reverse);
|
||||
ByteBuf output = inputBuffer == null ? user().getChannel().alloc().buffer() : inputBuffer.alloc().buffer();
|
||||
apply(direction, protocolInfo.getState(direction), 0, protocols);
|
||||
final ByteBuf output = inputBuffer == null ? user().getChannel().alloc().buffer() : inputBuffer.alloc().buffer();
|
||||
try {
|
||||
writeToBuffer(output);
|
||||
return output.retain();
|
||||
@@ -402,15 +412,22 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
|
||||
private PacketWrapperImpl apply(Direction direction, State state, int index, Protocol[] pipeline, boolean reverse) throws Exception {
|
||||
// Reset the reader after every transformation for the packetWrapper, so it can be recycled across packets
|
||||
State updatedState = state; // The state might change while transforming, so we need to check for that
|
||||
if (reverse) {
|
||||
for (int i = index; i >= 0; i--) {
|
||||
pipeline[i].transform(direction, state, this);
|
||||
pipeline[i].transform(direction, updatedState, this);
|
||||
resetReader();
|
||||
if (this.packetType != null) {
|
||||
updatedState = this.packetType.state();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = index; i < pipeline.length; i++) {
|
||||
pipeline[i].transform(direction, state, this);
|
||||
pipeline[i].transform(direction, updatedState, this);
|
||||
resetReader();
|
||||
if (this.packetType != null) {
|
||||
updatedState = this.packetType.state();
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
||||
@@ -33,12 +33,10 @@ import com.viaversion.viaversion.api.protocol.version.VersionProvider;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.protocol.ProtocolManagerImpl;
|
||||
import com.viaversion.viaversion.protocol.ServerProtocolVersionSingleton;
|
||||
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ServerboundConfigurationPackets1_20_2;
|
||||
import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8;
|
||||
import com.viaversion.viaversion.util.ChatColorUtil;
|
||||
import com.viaversion.viaversion.util.GsonUtil;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
@@ -121,7 +119,7 @@ public class BaseProtocol1_7 extends AbstractProtocol {
|
||||
// Login Success Packet
|
||||
registerClientbound(ClientboundLoginPackets.GAME_PROFILE, wrapper -> {
|
||||
ProtocolInfo info = wrapper.user().getProtocolInfo();
|
||||
if (info.getProtocolVersion() < ProtocolVersion.v1_20_2.getVersion()) {
|
||||
if (info.getProtocolVersion() < ProtocolVersion.v1_20_2.getVersion()) { // On 1.20.2+, wait for the login ack
|
||||
info.setState(State.PLAY);
|
||||
}
|
||||
|
||||
@@ -165,7 +163,10 @@ public class BaseProtocol1_7 extends AbstractProtocol {
|
||||
}
|
||||
});
|
||||
|
||||
registerServerbound(ServerboundLoginPackets.LOGIN_ACKNOWLEDGED, wrapper -> wrapper.user().getProtocolInfo().setState(State.CONFIGURATION));
|
||||
registerServerbound(ServerboundLoginPackets.LOGIN_ACKNOWLEDGED, wrapper -> {
|
||||
final ProtocolInfo info = wrapper.user().getProtocolInfo();
|
||||
info.setState(State.CONFIGURATION);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -44,8 +44,8 @@ public final class WorldPackets {
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_18.CHUNK_DATA, wrapper -> {
|
||||
final EntityTracker tracker = protocol.getEntityRewriter().tracker(wrapper.user());
|
||||
Preconditions.checkArgument(tracker.biomesSent() != 0, "Biome count not set");
|
||||
Preconditions.checkArgument(tracker.currentWorldSectionHeight() != 0, "Section height not set");
|
||||
Preconditions.checkArgument(tracker.biomesSent() != -1, "Biome count not set");
|
||||
Preconditions.checkArgument(tracker.currentWorldSectionHeight() != -1, "Section height not set");
|
||||
final Chunk1_18Type chunkType = new Chunk1_18Type(tracker.currentWorldSectionHeight(),
|
||||
MathUtil.ceilLog2(protocol.getMappingData().getBlockStateMappings().mappedSize()),
|
||||
MathUtil.ceilLog2(tracker.biomesSent()));
|
||||
|
||||
+3
-2
@@ -29,6 +29,7 @@ public class AckSequenceProvider implements Provider {
|
||||
public void handleSequence(final UserConnection connection, final int sequence) throws Exception {
|
||||
final PacketWrapper ackPacket = PacketWrapper.create(ClientboundPackets1_19.BLOCK_CHANGED_ACK, connection);
|
||||
ackPacket.write(Type.VAR_INT, sequence);
|
||||
ackPacket.scheduleSend(Protocol1_19To1_18_2.class);
|
||||
ackPacket.send(Protocol1_19To1_18_2.class);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+57
-17
@@ -20,6 +20,7 @@ package com.viaversion.viaversion.protocols.protocol1_20_2to1_20;
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.ProtocolInfo;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.data.MappingData;
|
||||
import com.viaversion.viaversion.api.data.MappingDataBase;
|
||||
@@ -70,6 +71,21 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
||||
soundRewriter.register1_19_3Sound(ClientboundPackets1_19_4.SOUND);
|
||||
soundRewriter.registerEntitySound(ClientboundPackets1_19_4.ENTITY_SOUND);
|
||||
|
||||
registerClientbound(ClientboundPackets1_19_4.PLUGIN_MESSAGE, wrapper -> {
|
||||
final String channel = wrapper.passthrough(Type.STRING);
|
||||
if (channel.equals("minecraft:brand")) {
|
||||
wrapper.passthrough(Type.STRING);
|
||||
wrapper.read(Type.REMAINING_BYTES);
|
||||
}
|
||||
});
|
||||
registerServerbound(ServerboundPackets1_20_2.PLUGIN_MESSAGE, wrapper -> {
|
||||
final String channel = wrapper.passthrough(Type.STRING);
|
||||
if (channel.equals("minecraft:brand")) {
|
||||
wrapper.passthrough(Type.STRING);
|
||||
wrapper.read(Type.REMAINING_BYTES);
|
||||
}
|
||||
});
|
||||
|
||||
registerClientbound(ClientboundPackets1_19_4.RESOURCE_PACK, wrapper -> {
|
||||
final String url = wrapper.passthrough(Type.STRING);
|
||||
final String hash = wrapper.passthrough(Type.STRING);
|
||||
@@ -98,33 +114,52 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
||||
// during the configuration phase before finally transitioning to the play state with the client as well.
|
||||
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE.getId(), ClientboundLoginPackets.GAME_PROFILE.getId(), wrapper -> {
|
||||
wrapper.user().get(ConfigurationState.class).setBridgePhase(BridgePhase.PROFILE_SENT);
|
||||
|
||||
// Set the state according to what the server expects. All packets between now and when the client
|
||||
// switches to PLAY as well will be discarded after being dealt with.
|
||||
wrapper.user().getProtocolInfo().setState(State.PLAY);
|
||||
wrapper.user().getProtocolInfo().setServerState(State.PLAY);
|
||||
});
|
||||
|
||||
registerServerbound(State.LOGIN, ServerboundLoginPackets.LOGIN_ACKNOWLEDGED.getId(), -1, wrapper -> {
|
||||
wrapper.cancel();
|
||||
|
||||
// Overwrite the state set in the base protocol to what the server actually keeps sending
|
||||
wrapper.user().getProtocolInfo().setServerState(State.PLAY);
|
||||
|
||||
final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class);
|
||||
configurationState.setBridgePhase(BridgePhase.CONFIGURATION);
|
||||
configurationState.sendQueuedPackets(wrapper.user());
|
||||
});
|
||||
cancelServerbound(State.LOGIN, ServerboundLoginPackets.CUSTOM_QUERY_ANSWER.getId());
|
||||
|
||||
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.FINISH_CONFIGURATION.getId(), -1, wrapper -> {
|
||||
wrapper.cancel();
|
||||
|
||||
wrapper.user().getProtocolInfo().setClientState(State.PLAY);
|
||||
|
||||
final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class);
|
||||
configurationState.setBridgePhase(BridgePhase.NONE);
|
||||
configurationState.sendQueuedPackets(wrapper.user());
|
||||
configurationState.clear();
|
||||
});
|
||||
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.CLIENT_INFORMATION.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.CLIENT_SETTINGS));
|
||||
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.CLIENT_INFORMATION.getId(), -1, wrapper -> {
|
||||
final ConfigurationState.ClientInformation clientInformation = new ConfigurationState.ClientInformation(
|
||||
wrapper.read(Type.STRING), // Language
|
||||
wrapper.read(Type.BYTE), // View distance
|
||||
wrapper.read(Type.VAR_INT), // Chat visibility
|
||||
wrapper.read(Type.BOOLEAN), // Chat colors
|
||||
wrapper.read(Type.UNSIGNED_BYTE), // Model customization
|
||||
wrapper.read(Type.VAR_INT), // Main hand
|
||||
wrapper.read(Type.BOOLEAN), // Text filtering enabled
|
||||
wrapper.read(Type.BOOLEAN) // Allow listing in server list preview
|
||||
);
|
||||
|
||||
// Store it to re-send it when another ClientboundLoginPacket is sent, since the client will only send it
|
||||
// once per connection right after the handshake
|
||||
final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class);
|
||||
configurationState.setClientInformation(clientInformation);
|
||||
wrapper.cancel();
|
||||
});
|
||||
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.PLUGIN_MESSAGE));
|
||||
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.KEEP_ALIVE.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.KEEP_ALIVE));
|
||||
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.PONG.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.PONG));
|
||||
|
||||
// Cancel this, as it will always just be the response to a re-sent pack from us
|
||||
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.RESOURCE_PACK.getId(), -1, PacketWrapper::cancel);
|
||||
|
||||
@@ -138,6 +173,7 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
||||
}
|
||||
|
||||
// Reenter the configuration state
|
||||
wrapper.user().getProtocolInfo().setClientState(State.CONFIGURATION);
|
||||
configurationState.setBridgePhase(BridgePhase.CONFIGURATION);
|
||||
|
||||
final LastResourcePack lastResourcePack = wrapper.user().get(LastResourcePack.class);
|
||||
@@ -165,6 +201,12 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
||||
|
||||
@Override
|
||||
public void transform(final Direction direction, final State state, final PacketWrapper packetWrapper) throws Exception {
|
||||
if (direction == Direction.SERVERBOUND) {
|
||||
// The client will have the correct state set
|
||||
super.transform(direction, state, packetWrapper);
|
||||
return;
|
||||
}
|
||||
|
||||
final ConfigurationState configurationBridge = packetWrapper.user().get(ConfigurationState.class);
|
||||
if (configurationBridge == null) {
|
||||
// Bad state during an unexpected disconnect
|
||||
@@ -177,13 +219,6 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
||||
return;
|
||||
}
|
||||
|
||||
if (direction == Direction.SERVERBOUND) {
|
||||
// Client and server will be on different protocol states, pick the right client protocol state
|
||||
super.transform(direction, phase == BridgePhase.PROFILE_SENT ? State.LOGIN
|
||||
: phase == BridgePhase.REENTERING_CONFIGURATION ? State.PLAY : State.CONFIGURATION, packetWrapper);
|
||||
return;
|
||||
}
|
||||
|
||||
if (phase == BridgePhase.PROFILE_SENT || phase == BridgePhase.REENTERING_CONFIGURATION) {
|
||||
// Queue packets sent by the server while we wait for the client to transition to the configuration state
|
||||
configurationBridge.addPacketToQueue(packetWrapper, true);
|
||||
@@ -194,7 +229,7 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
||||
// Map some of them to their configuration state counterparts, but make sure to let join game through
|
||||
final int unmappedId = packetWrapper.getId();
|
||||
if (unmappedId == ClientboundPackets1_19_4.JOIN_GAME.getId()) {
|
||||
super.transform(direction, state, packetWrapper);
|
||||
super.transform(direction, State.PLAY, packetWrapper);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -237,6 +272,9 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
||||
}
|
||||
|
||||
public static void sendConfigurationPackets(final UserConnection connection, final CompoundTag dimensionRegistry, @Nullable final LastResourcePack lastResourcePack) throws Exception {
|
||||
final ProtocolInfo protocolInfo = connection.getProtocolInfo();
|
||||
protocolInfo.setServerState(State.CONFIGURATION);
|
||||
|
||||
final PacketWrapper registryDataPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.REGISTRY_DATA, connection);
|
||||
registryDataPacket.write(Type.NAMELESS_NBT, dimensionRegistry);
|
||||
registryDataPacket.send(Protocol1_20_2To1_20.class);
|
||||
@@ -260,6 +298,8 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
||||
|
||||
final PacketWrapper finishConfigurationPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION, connection);
|
||||
finishConfigurationPacket.send(Protocol1_20_2To1_20.class);
|
||||
|
||||
protocolInfo.setServerState(State.PLAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -268,8 +308,8 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ServerboundPackets1_20_2 configurationAcknowledgedPacket() {
|
||||
return null; // Don't handle it in the transitioning protocol
|
||||
protected void registerConfigurationChangeHandlers() {
|
||||
// Don't handle it in the transitioning protocol
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -287,4 +327,4 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
|
||||
public ItemRewriter<Protocol1_20_2To1_20> getItemRewriter() {
|
||||
return itemPacketRewriter;
|
||||
}
|
||||
}
|
||||
}
|
||||
+120
-58
@@ -19,7 +19,10 @@ package com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.IntTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.ListTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.NumberTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
||||
import com.viaversion.viaversion.api.data.ParticleMappings;
|
||||
import com.viaversion.viaversion.api.data.entity.EntityTracker;
|
||||
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
|
||||
@@ -38,51 +41,14 @@ import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.rewriter.Recip
|
||||
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.type.ChunkType1_20_2;
|
||||
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.util.PotionEffects;
|
||||
import com.viaversion.viaversion.rewriter.BlockRewriter;
|
||||
import com.viaversion.viaversion.rewriter.ItemRewriter;
|
||||
import com.viaversion.viaversion.util.Key;
|
||||
import com.viaversion.viaversion.util.MathUtil;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<ClientboundPackets1_19_4, ServerboundPackets1_20_2, Protocol1_20_2To1_20> {
|
||||
|
||||
public static final String[] POTION_EFFECTS = {
|
||||
"", // No effect
|
||||
"speed",
|
||||
"slowness",
|
||||
"haste",
|
||||
"mining_fatigue",
|
||||
"strength",
|
||||
"instant_health",
|
||||
"instant_damage",
|
||||
"jump_boost",
|
||||
"nausea",
|
||||
"regeneration",
|
||||
"resistance",
|
||||
"fire_resistance",
|
||||
"water_breathing",
|
||||
"invisibility",
|
||||
"blindness",
|
||||
"night_vision",
|
||||
"hunger",
|
||||
"weakness",
|
||||
"poison",
|
||||
"wither",
|
||||
"health_boost",
|
||||
"absorption",
|
||||
"saturation",
|
||||
"glowing",
|
||||
"levitation",
|
||||
"luck",
|
||||
"unluck",
|
||||
"slow_falling",
|
||||
"conduit_power",
|
||||
"dolphins_grace",
|
||||
"bad_omen",
|
||||
"hero_of_the_village",
|
||||
"darkness"
|
||||
};
|
||||
|
||||
public BlockItemPacketRewriter1_20_2(final Protocol1_20_2To1_20 protocol) {
|
||||
super(protocol);
|
||||
}
|
||||
@@ -96,8 +62,11 @@ public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<Clientboun
|
||||
blockRewriter.registerEffect(ClientboundPackets1_19_4.EFFECT, 1010, 2001);
|
||||
|
||||
protocol.registerServerbound(ServerboundPackets1_20_2.SET_BEACON_EFFECT, wrapper -> {
|
||||
if (wrapper.passthrough(Type.BOOLEAN)) {
|
||||
// Effects start at 1 before 1.20.2
|
||||
// Effects start at 1 before 1.20.2
|
||||
if (wrapper.passthrough(Type.BOOLEAN)) { // Primary effect
|
||||
wrapper.write(Type.VAR_INT, wrapper.read(Type.VAR_INT) + 1);
|
||||
}
|
||||
if (wrapper.passthrough(Type.BOOLEAN)) { // Secondary effect
|
||||
wrapper.write(Type.VAR_INT, wrapper.read(Type.VAR_INT) + 1);
|
||||
}
|
||||
});
|
||||
@@ -151,8 +120,12 @@ public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<Clientboun
|
||||
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_VAR_INT_ITEM_ARRAY_VAR_INT)); // Items
|
||||
wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM)); // Carried item
|
||||
final Item[] items = wrapper.read(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT);
|
||||
for (final Item item : items) {
|
||||
handleItemToClient(item);
|
||||
}
|
||||
wrapper.write(Type.ITEM1_20_2_VAR_INT_ARRAY, items);
|
||||
wrapper.write(Type.ITEM1_20_2, handleItemToClient(wrapper.read(Type.FLAT_VAR_INT_ITEM))); // Carried item
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -162,7 +135,7 @@ public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<Clientboun
|
||||
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
|
||||
handler(wrapper -> wrapper.write(Type.ITEM1_20_2, handleItemToClient(wrapper.read(Type.FLAT_VAR_INT_ITEM))));
|
||||
}
|
||||
});
|
||||
protocol.registerClientbound(ClientboundPackets1_19_4.ADVANCEMENTS, wrapper -> {
|
||||
@@ -179,7 +152,7 @@ public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<Clientboun
|
||||
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.write(Type.ITEM1_20_2, handleItemToClient(wrapper.read(Type.FLAT_VAR_INT_ITEM))); // Icon
|
||||
wrapper.passthrough(Type.VAR_INT); // Frame type
|
||||
final int flags = wrapper.passthrough(Type.INT); // Flags
|
||||
if ((flags & 1) != 0) {
|
||||
@@ -208,7 +181,7 @@ public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<Clientboun
|
||||
byte slot;
|
||||
do {
|
||||
slot = wrapper.passthrough(Type.BYTE);
|
||||
wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM));
|
||||
wrapper.write(Type.ITEM1_20_2, handleItemToClient(wrapper.read(Type.FLAT_VAR_INT_ITEM)));
|
||||
} while ((slot & 0xFFFFFF80) != 0);
|
||||
});
|
||||
}
|
||||
@@ -227,11 +200,11 @@ public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<Clientboun
|
||||
final 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));
|
||||
wrapper.write(Type.FLAT_VAR_INT_ITEM, handleItemToServer(wrapper.read(Type.ITEM1_20_2)));
|
||||
}
|
||||
|
||||
// Carried item
|
||||
wrapper.write(Type.FLAT_VAR_INT_ITEM, wrapper.read(Type.ITEM1_20_2));
|
||||
wrapper.write(Type.FLAT_VAR_INT_ITEM, handleItemToServer(wrapper.read(Type.ITEM1_20_2)));
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -239,9 +212,9 @@ public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<Clientboun
|
||||
wrapper.passthrough(Type.VAR_INT); // Container id
|
||||
final 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.write(Type.ITEM1_20_2, handleItemToClient(wrapper.read(Type.FLAT_VAR_INT_ITEM))); // Input
|
||||
wrapper.write(Type.ITEM1_20_2, handleItemToClient(wrapper.read(Type.FLAT_VAR_INT_ITEM))); // Output
|
||||
wrapper.write(Type.ITEM1_20_2, handleItemToClient(wrapper.read(Type.FLAT_VAR_INT_ITEM))); // Second Item
|
||||
|
||||
wrapper.passthrough(Type.BOOLEAN); // Trade disabled
|
||||
wrapper.passthrough(Type.INT); // Number of tools uses
|
||||
@@ -257,7 +230,7 @@ public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<Clientboun
|
||||
@Override
|
||||
public void register() {
|
||||
map(Type.SHORT); // 0 - Slot
|
||||
map(Type.ITEM1_20_2, Type.FLAT_VAR_INT_ITEM); // 1 - Clicked Item
|
||||
handler(wrapper -> wrapper.write(Type.FLAT_VAR_INT_ITEM, handleItemToServer(wrapper.read(Type.ITEM1_20_2)))); // 1 - Clicked Item
|
||||
}
|
||||
});
|
||||
protocol.registerClientbound(ClientboundPackets1_19_4.SPAWN_PARTICLE, new PacketHandlers() {
|
||||
@@ -280,7 +253,7 @@ public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<Clientboun
|
||||
final int data = wrapper.read(Type.VAR_INT);
|
||||
wrapper.write(Type.VAR_INT, protocol.getMappingData().getNewBlockStateId(data));
|
||||
} else if (mappings.isItemParticle(id)) {
|
||||
wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM));
|
||||
wrapper.write(Type.ITEM1_20_2, handleItemToClient(wrapper.read(Type.FLAT_VAR_INT_ITEM)));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -370,6 +343,99 @@ public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<Clientboun
|
||||
}.register(ClientboundPackets1_19_4.DECLARE_RECIPES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Item handleItemToClient(@Nullable final Item item) {
|
||||
if (item == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (item.tag() != null) {
|
||||
to1_20_2Effects(item);
|
||||
}
|
||||
|
||||
return super.handleItemToClient(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Item handleItemToServer(@Nullable final Item item) {
|
||||
if (item == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (item.tag() != null) {
|
||||
to1_20_1Effects(item);
|
||||
}
|
||||
|
||||
return super.handleItemToServer(item);
|
||||
}
|
||||
|
||||
public static void to1_20_2Effects(final Item item) {
|
||||
final Tag customPotionEffectsTag = item.tag().remove("CustomPotionEffects");
|
||||
if (customPotionEffectsTag instanceof ListTag) {
|
||||
final ListTag effectsTag = (ListTag) customPotionEffectsTag;
|
||||
item.tag().put("custom_potion_effects", customPotionEffectsTag);
|
||||
|
||||
for (final Tag tag : effectsTag) {
|
||||
if (!(tag instanceof CompoundTag)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final CompoundTag effectTag = (CompoundTag) tag;
|
||||
final Tag idTag = effectTag.remove("Id");
|
||||
if (idTag instanceof NumberTag) {
|
||||
final String key = PotionEffects.idToKey(((NumberTag) idTag).asInt());
|
||||
if (key != null) {
|
||||
effectTag.put("id", new StringTag(key));
|
||||
}
|
||||
}
|
||||
|
||||
renameTag(effectTag, "Amplifier", "amplifier");
|
||||
renameTag(effectTag, "Duration", "duration");
|
||||
renameTag(effectTag, "Ambient", "ambient");
|
||||
renameTag(effectTag, "ShowParticles", "show_particles");
|
||||
renameTag(effectTag, "ShowIcon", "show_icon");
|
||||
renameTag(effectTag, "HiddenEffect", "hidden_effect");
|
||||
renameTag(effectTag, "FactorCalculationData", "factor_calculation_data");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void to1_20_1Effects(final Item item) {
|
||||
final Tag customPotionEffectsTag = item.tag().remove("custom_potion_effects");
|
||||
if (customPotionEffectsTag instanceof ListTag) {
|
||||
final ListTag effectsTag = (ListTag) customPotionEffectsTag;
|
||||
item.tag().put("CustomPotionEffects", effectsTag);
|
||||
|
||||
for (final Tag tag : effectsTag) {
|
||||
if (!(tag instanceof CompoundTag)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final CompoundTag effectTag = (CompoundTag) tag;
|
||||
final Tag idTag = effectTag.remove("id");
|
||||
if (idTag instanceof StringTag) {
|
||||
final int id = PotionEffects.keyToId(((StringTag) idTag).getValue());
|
||||
effectTag.put("Id", new IntTag(id));
|
||||
}
|
||||
|
||||
renameTag(effectTag, "amplifier", "Amplifier");
|
||||
renameTag(effectTag, "duration", "Duration");
|
||||
renameTag(effectTag, "ambient", "Ambient");
|
||||
renameTag(effectTag, "show_particles", "ShowParticles");
|
||||
renameTag(effectTag, "show_icon", "ShowIcon");
|
||||
renameTag(effectTag, "hidden_effect", "HiddenEffect");
|
||||
renameTag(effectTag, "factor_calculation_data", "FactorCalculationData");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void renameTag(final CompoundTag tag, final String entryName, final String toEntryName) {
|
||||
final Tag entry = tag.remove(entryName);
|
||||
if (entry != null) {
|
||||
tag.put(toEntryName, entry);
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable CompoundTag handleBlockEntity(@Nullable final CompoundTag tag) {
|
||||
if (tag == null) {
|
||||
return null;
|
||||
@@ -377,17 +443,13 @@ public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<Clientboun
|
||||
|
||||
final IntTag primaryEffect = tag.remove("Primary");
|
||||
if (primaryEffect != null && primaryEffect.asInt() != 0) {
|
||||
tag.put("primary_effect", new StringTag(effect(primaryEffect.asInt())));
|
||||
tag.put("primary_effect", new StringTag(PotionEffects.idToKeyOrLuck(primaryEffect.asInt())));
|
||||
}
|
||||
|
||||
final IntTag secondaryEffect = tag.remove("Secondary");
|
||||
if (secondaryEffect != null && secondaryEffect.asInt() != 0) {
|
||||
tag.put("secondary_effect", new StringTag(effect(secondaryEffect.asInt())));
|
||||
tag.put("secondary_effect", new StringTag(PotionEffects.idToKeyOrLuck(secondaryEffect.asInt())));
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
private String effect(final int id) {
|
||||
return id >= 1 && id < POTION_EFFECTS.length ? Key.namespaced(POTION_EFFECTS[id]) : "minecraft:luck";
|
||||
}
|
||||
}
|
||||
+4
@@ -101,6 +101,10 @@ public final class EntityPacketRewriter1_20_2 extends EntityRewriter<Clientbound
|
||||
final ConfigurationState configurationBridge = wrapper.user().get(ConfigurationState.class);
|
||||
if (!configurationBridge.setLastDimensionRegistry(dimensionRegistry)) {
|
||||
// No change, so no need to re-enter the configuration state - just let this one through
|
||||
final PacketWrapper clientInformationPacket = configurationBridge.clientInformationPacket(wrapper.user());
|
||||
if (clientInformationPacket != null) {
|
||||
clientInformationPacket.sendToServer(Protocol1_20_2To1_20.class);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+56
-1
@@ -22,6 +22,8 @@ import com.viaversion.viaversion.api.connection.StorableObject;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ServerboundPackets1_19_4;
|
||||
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.Protocol1_20_2To1_20;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
@@ -37,6 +39,7 @@ public class ConfigurationState implements StorableObject {
|
||||
private QueuedPacket joinGamePacket;
|
||||
private boolean queuedJoinGame;
|
||||
private CompoundTag lastDimensionRegistry;
|
||||
private ClientInformation clientInformation;
|
||||
|
||||
public BridgePhase bridgePhase() {
|
||||
return bridgePhase;
|
||||
@@ -62,6 +65,10 @@ public class ConfigurationState implements StorableObject {
|
||||
return !equals;
|
||||
}
|
||||
|
||||
public void setClientInformation(final ClientInformation clientInformation) {
|
||||
this.clientInformation = clientInformation;
|
||||
}
|
||||
|
||||
public void addPacketToQueue(final PacketWrapper wrapper, final boolean clientbound) throws Exception {
|
||||
packetQueue.add(toQueuedPacket(wrapper, clientbound, false));
|
||||
}
|
||||
@@ -99,11 +106,17 @@ public class ConfigurationState implements StorableObject {
|
||||
}
|
||||
|
||||
public void sendQueuedPackets(final UserConnection connection) throws Exception {
|
||||
if (joinGamePacket != null) {
|
||||
final boolean hasJoinGamePacket = joinGamePacket != null;
|
||||
if (hasJoinGamePacket) {
|
||||
packetQueue.add(0, joinGamePacket);
|
||||
joinGamePacket = null;
|
||||
}
|
||||
|
||||
final PacketWrapper clientInformationPacket = clientInformationPacket(connection);
|
||||
if (clientInformationPacket != null) {
|
||||
packetQueue.add(hasJoinGamePacket ? 1 : 0, toQueuedPacket(clientInformationPacket, false, true));
|
||||
}
|
||||
|
||||
final ConfigurationState.QueuedPacket[] queuedPackets = packetQueue.toArray(new ConfigurationState.QueuedPacket[0]);
|
||||
packetQueue.clear();
|
||||
|
||||
@@ -142,6 +155,24 @@ public class ConfigurationState implements StorableObject {
|
||||
NONE, PROFILE_SENT, CONFIGURATION, REENTERING_CONFIGURATION
|
||||
}
|
||||
|
||||
public @Nullable PacketWrapper clientInformationPacket(final UserConnection connection) {
|
||||
if (clientInformation == null) {
|
||||
// Should never be null, but we also shouldn't error
|
||||
return null;
|
||||
}
|
||||
|
||||
final PacketWrapper settingsPacket = PacketWrapper.create(ServerboundPackets1_19_4.CLIENT_SETTINGS, connection);
|
||||
settingsPacket.write(Type.STRING, clientInformation.language);
|
||||
settingsPacket.write(Type.BYTE, clientInformation.viewDistance);
|
||||
settingsPacket.write(Type.VAR_INT, clientInformation.chatVisibility);
|
||||
settingsPacket.write(Type.BOOLEAN, clientInformation.showChatColors);
|
||||
settingsPacket.write(Type.UNSIGNED_BYTE, clientInformation.modelCustomization);
|
||||
settingsPacket.write(Type.VAR_INT, clientInformation.mainHand);
|
||||
settingsPacket.write(Type.BOOLEAN, clientInformation.textFiltering);
|
||||
settingsPacket.write(Type.BOOLEAN, clientInformation.allowListing);
|
||||
return settingsPacket;
|
||||
}
|
||||
|
||||
public static final class QueuedPacket {
|
||||
private final ByteBuf buf;
|
||||
private final boolean clientbound;
|
||||
@@ -189,4 +220,28 @@ public class ConfigurationState implements StorableObject {
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ClientInformation {
|
||||
private final String language;
|
||||
private final byte viewDistance;
|
||||
private final int chatVisibility;
|
||||
private final boolean showChatColors;
|
||||
private final short modelCustomization;
|
||||
private final int mainHand;
|
||||
private final boolean textFiltering;
|
||||
private final boolean allowListing;
|
||||
|
||||
public ClientInformation(final String language, final byte viewDistance, final int chatVisibility,
|
||||
final boolean showChatColors, final short modelCustomization, final int mainHand,
|
||||
final boolean textFiltering, final boolean allowListing) {
|
||||
this.language = language;
|
||||
this.viewDistance = viewDistance;
|
||||
this.chatVisibility = chatVisibility;
|
||||
this.showChatColors = showChatColors;
|
||||
this.modelCustomization = modelCustomization;
|
||||
this.mainHand = mainHand;
|
||||
this.textFiltering = textFiltering;
|
||||
this.allowListing = allowListing;
|
||||
}
|
||||
}
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import com.viaversion.viaversion.util.Key;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public final class PotionEffects {
|
||||
|
||||
private static final Object2IntMap<String> KEY_TO_ID = new Object2IntOpenHashMap<>();
|
||||
private static final String[] POTION_EFFECTS = {
|
||||
"", // No effect
|
||||
"speed",
|
||||
"slowness",
|
||||
"haste",
|
||||
"mining_fatigue",
|
||||
"strength",
|
||||
"instant_health",
|
||||
"instant_damage",
|
||||
"jump_boost",
|
||||
"nausea",
|
||||
"regeneration",
|
||||
"resistance",
|
||||
"fire_resistance",
|
||||
"water_breathing",
|
||||
"invisibility",
|
||||
"blindness",
|
||||
"night_vision",
|
||||
"hunger",
|
||||
"weakness",
|
||||
"poison",
|
||||
"wither",
|
||||
"health_boost",
|
||||
"absorption",
|
||||
"saturation",
|
||||
"glowing",
|
||||
"levitation",
|
||||
"luck",
|
||||
"unluck",
|
||||
"slow_falling",
|
||||
"conduit_power",
|
||||
"dolphins_grace",
|
||||
"bad_omen",
|
||||
"hero_of_the_village",
|
||||
"darkness"
|
||||
};
|
||||
|
||||
static {
|
||||
for (int i = 1; i < POTION_EFFECTS.length; i++) {
|
||||
final String effect = POTION_EFFECTS[i];
|
||||
KEY_TO_ID.put(effect, i);
|
||||
}
|
||||
}
|
||||
|
||||
public static @Nullable String idToKey(final int id) {
|
||||
return id >= 1 && id < POTION_EFFECTS.length ? Key.namespaced(POTION_EFFECTS[id]) : null;
|
||||
}
|
||||
|
||||
public static String idToKeyOrLuck(final int id) {
|
||||
return id >= 1 && id < POTION_EFFECTS.length ? Key.namespaced(POTION_EFFECTS[id]) : "minecraft:luck";
|
||||
}
|
||||
|
||||
public static int keyToId(final String key) {
|
||||
return KEY_TO_ID.getInt(Key.stripMinecraftNamespace(key));
|
||||
}
|
||||
}
|
||||
+6
-4
@@ -172,17 +172,19 @@ public final class InventoryPackets extends ItemRewriter<ClientboundPackets1_19_
|
||||
|
||||
final ListTag messages = new ListTag(StringTag.class);
|
||||
for (int i = 1; i < 5; i++) {
|
||||
final Tag text = tag.get("Text" + i);
|
||||
final Tag text = tag.remove("Text" + i);
|
||||
messages.add(text != null ? text : new StringTag(ChatRewriter.emptyComponentString()));
|
||||
}
|
||||
frontText.put("messages", messages);
|
||||
|
||||
final ListTag filteredMessages = new ListTag(StringTag.class);
|
||||
for (int i = 1; i < 5; i++) {
|
||||
final Tag text = tag.get("FilteredText" + i);
|
||||
filteredMessages.add(text != null ? text : new StringTag(ChatRewriter.emptyComponentString()));
|
||||
final Tag text = tag.remove("FilteredText" + i);
|
||||
filteredMessages.add(text != null ? text : messages.get(i - 1));
|
||||
}
|
||||
if (!filteredMessages.equals(messages)) {
|
||||
frontText.put("filtered_messages", filteredMessages);
|
||||
}
|
||||
frontText.put("filtered_messages", filteredMessages);
|
||||
|
||||
final Tag color = tag.remove("Color");
|
||||
if (color != null) {
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ import java.util.logging.Level;
|
||||
public class MovementTransmitterProvider implements Provider {
|
||||
|
||||
public void sendPlayer(UserConnection userConnection) {
|
||||
if (userConnection.getProtocolInfo().getState() != State.PLAY || userConnection.getEntityTracker(Protocol1_9To1_8.class).clientEntityId() == -1) {
|
||||
if (userConnection.getProtocolInfo().getClientState() != State.PLAY || userConnection.getEntityTracker(Protocol1_9To1_8.class).clientEntityId() == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -172,8 +172,8 @@ public class BlockRewriter<C extends ClientboundPacketType> {
|
||||
public PacketHandler chunkDataHandler1_19(ChunkTypeSupplier chunkTypeSupplier, @Nullable Consumer<BlockEntity> blockEntityHandler) {
|
||||
return wrapper -> {
|
||||
final EntityTracker tracker = protocol.getEntityRewriter().tracker(wrapper.user());
|
||||
Preconditions.checkArgument(tracker.biomesSent() != 0, "Biome count not set");
|
||||
Preconditions.checkArgument(tracker.currentWorldSectionHeight() != 0, "Section height not set");
|
||||
Preconditions.checkArgument(tracker.biomesSent() != -1, "Biome count not set");
|
||||
Preconditions.checkArgument(tracker.currentWorldSectionHeight() != -1, "Section height not set");
|
||||
final Type<Chunk> chunkType = chunkTypeSupplier.supply(tracker.currentWorldSectionHeight(),
|
||||
MathUtil.ceilLog2(protocol.getMappingData().getBlockStateMappings().mappedSize()),
|
||||
MathUtil.ceilLog2(tracker.biomesSent()));
|
||||
|
||||
@@ -104,11 +104,10 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
|
||||
public void handleMetadata(final int entityId, final List<Metadata> metadataList, final UserConnection connection) {
|
||||
final TrackedEntity entity = tracker(connection).entity(entityId);
|
||||
final EntityType type = entity != null ? entity.entityType() : null;
|
||||
int i = 0; // Count index for fast removal
|
||||
for (final Metadata metadata : metadataList.toArray(EMPTY_ARRAY)) { // Copy the list to allow mutation
|
||||
// Call handlers implementing the old handleMetadata
|
||||
if (!callOldMetaHandler(entityId, type, metadata, metadataList, connection)) {
|
||||
metadataList.remove(i--);
|
||||
metadataList.remove(metadata);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -126,22 +125,22 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
|
||||
filter.handler().handle(event, metadata);
|
||||
} catch (final Exception e) {
|
||||
logException(e, type, metadataList, metadata);
|
||||
metadataList.remove(i--);
|
||||
metadataList.remove(metadata);
|
||||
break;
|
||||
}
|
||||
|
||||
if (event.cancelled()) {
|
||||
// Remove meta, decrease list index counter, and break current filter loop
|
||||
metadataList.remove(i--);
|
||||
// Remove meta, and break current filter loop
|
||||
metadataList.remove(metadata);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (event != null && event.extraMeta() != null) {
|
||||
final List<Metadata> extraMeta = event != null ? event.extraMeta() : null;
|
||||
if (extraMeta != null) {
|
||||
// Finally, add newly created meta
|
||||
metadataList.addAll(event.extraMeta());
|
||||
metadataList.addAll(extraMeta);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (entity != null) {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
# Project properties - we put these here so they can be modified without causing a recompile of the build scripts
|
||||
projectVersion=4.8.0
|
||||
projectVersion=4.8.1
|
||||
|
||||
# Smile emoji
|
||||
mcVersions=1.20.2, 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2, 1.18.1, 1.18, 1.17.1, 1.17, 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16, 1.15.2, 1.15.1, 1.15, 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14, 1.13.2, 1.13.1, 1.13, 1.12.2, 1.12.1, 1.12, 1.11.2, 1.11.1, 1.11, 1.10.2, 1.10.1, 1.10, 1.9.4, 1.9.3, 1.9.2, 1.9.1, 1.9, 1.8.9
|
||||
|
||||
+52
-49
@@ -46,59 +46,62 @@ publishShadowJar()
|
||||
val branch = rootProject.branchName()
|
||||
val baseVersion = project.version as String
|
||||
val isRelease = !baseVersion.contains('-')
|
||||
val suffixedVersion = if (isRelease) baseVersion else baseVersion + "+" + System.getenv("GITHUB_RUN_NUMBER")
|
||||
val changelogContent = if (isRelease) {
|
||||
"See [GitHub](https://github.com/ViaVersion/ViaVersion) for release notes."
|
||||
} else {
|
||||
val commitHash = rootProject.latestCommitHash()
|
||||
"[$commitHash](https://github.com/ViaVersion/ViaVersion/commit/$commitHash) ${rootProject.latestCommitMessage()}"
|
||||
}
|
||||
val isMainBranch = branch == "master"
|
||||
modrinth {
|
||||
val mcVersions: List<String> = (property("mcVersions") as String)
|
||||
.split(",")
|
||||
.map { it.trim() }
|
||||
token.set(System.getenv("MODRINTH_TOKEN"))
|
||||
projectId.set("viaversion")
|
||||
versionType.set(if (isRelease) "release" else if (isMainBranch) "beta" else "alpha")
|
||||
versionNumber.set(suffixedVersion)
|
||||
versionName.set(suffixedVersion)
|
||||
changelog.set(changelogContent)
|
||||
uploadFile.set(tasks.shadowJar.flatMap { it.archiveFile })
|
||||
gameVersions.set(mcVersions)
|
||||
loaders.add("fabric")
|
||||
loaders.add("paper")
|
||||
loaders.add("folia")
|
||||
loaders.add("velocity")
|
||||
loaders.add("bungeecord")
|
||||
loaders.add("sponge")
|
||||
autoAddDependsOn.set(false)
|
||||
detectLoaders.set(false)
|
||||
dependencies {
|
||||
optional.project("viafabric")
|
||||
optional.project("viafabricplus")
|
||||
if (!isRelease || isMainBranch) { // Only publish releases from the main branch
|
||||
val suffixedVersion = if (isRelease) baseVersion else baseVersion + "+" + System.getenv("GITHUB_RUN_NUMBER")
|
||||
val changelogContent = if (isRelease) {
|
||||
"See [GitHub](https://github.com/ViaVersion/ViaVersion) for release notes."
|
||||
} else {
|
||||
val commitHash = rootProject.latestCommitHash()
|
||||
"[$commitHash](https://github.com/ViaVersion/ViaVersion/commit/$commitHash) ${rootProject.latestCommitMessage()}"
|
||||
}
|
||||
}
|
||||
|
||||
hangarPublish {
|
||||
publications.register("plugin") {
|
||||
version.set(suffixedVersion)
|
||||
id.set("ViaVersion")
|
||||
channel.set(if (isRelease) "Release" else if (isMainBranch) "Snapshot" else "Alpha")
|
||||
modrinth {
|
||||
val mcVersions: List<String> = (property("mcVersions") as String)
|
||||
.split(",")
|
||||
.map { it.trim() }
|
||||
token.set(System.getenv("MODRINTH_TOKEN"))
|
||||
projectId.set("viaversion")
|
||||
versionType.set(if (isRelease) "release" else if (isMainBranch) "beta" else "alpha")
|
||||
versionNumber.set(suffixedVersion)
|
||||
versionName.set(suffixedVersion)
|
||||
changelog.set(changelogContent)
|
||||
apiKey.set(System.getenv("HANGAR_TOKEN"))
|
||||
platforms {
|
||||
register(Platforms.PAPER) {
|
||||
jar.set(tasks.shadowJar.flatMap { it.archiveFile })
|
||||
platformVersions.set(listOf(property("mcVersionRange") as String))
|
||||
}
|
||||
register(Platforms.VELOCITY) {
|
||||
jar.set(tasks.shadowJar.flatMap { it.archiveFile })
|
||||
platformVersions.set(listOf(property("velocityVersion") as String))
|
||||
}
|
||||
register(Platforms.WATERFALL) {
|
||||
jar.set(tasks.shadowJar.flatMap { it.archiveFile })
|
||||
platformVersions.set(listOf(property("waterfallVersion") as String))
|
||||
uploadFile.set(tasks.shadowJar.flatMap { it.archiveFile })
|
||||
gameVersions.set(mcVersions)
|
||||
loaders.add("fabric")
|
||||
loaders.add("paper")
|
||||
loaders.add("folia")
|
||||
loaders.add("velocity")
|
||||
loaders.add("bungeecord")
|
||||
loaders.add("sponge")
|
||||
autoAddDependsOn.set(false)
|
||||
detectLoaders.set(false)
|
||||
dependencies {
|
||||
optional.project("viafabric")
|
||||
optional.project("viafabricplus")
|
||||
}
|
||||
}
|
||||
|
||||
hangarPublish {
|
||||
publications.register("plugin") {
|
||||
version.set(suffixedVersion)
|
||||
id.set("ViaVersion")
|
||||
channel.set(if (isRelease) "Release" else if (isMainBranch) "Snapshot" else "Alpha")
|
||||
changelog.set(changelogContent)
|
||||
apiKey.set(System.getenv("HANGAR_TOKEN"))
|
||||
platforms {
|
||||
register(Platforms.PAPER) {
|
||||
jar.set(tasks.shadowJar.flatMap { it.archiveFile })
|
||||
platformVersions.set(listOf(property("mcVersionRange") as String))
|
||||
}
|
||||
register(Platforms.VELOCITY) {
|
||||
jar.set(tasks.shadowJar.flatMap { it.archiveFile })
|
||||
platformVersions.set(listOf(property("velocityVersion") as String))
|
||||
}
|
||||
register(Platforms.WATERFALL) {
|
||||
jar.set(tasks.shadowJar.flatMap { it.archiveFile })
|
||||
platformVersions.set(listOf(property("waterfallVersion") as String))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user