mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-12 00:07:45 +00:00
Remove reflective implementation of ICustomPacket. (#8973)
Make vanilla custom packets able to be sent multiple times. Closes #8969
This commit is contained in:
1 parent
82e8d06e54
commit
41deadc1e2
8 files changed
+79
-87
No files matched your search
+14
-2
@@ -25,7 +25,7 @@
|
||||
}
|
||||
|
||||
public ClientboundCustomPayloadPacket(FriendlyByteBuf p_178836_) {
|
||||
@@ -43,6 +_,7 @@
|
||||
@@ -43,15 +_,17 @@
|
||||
} else {
|
||||
throw new IllegalArgumentException("Payload may not be larger than 1048576 bytes");
|
||||
}
|
||||
@@ -33,7 +33,10 @@
|
||||
}
|
||||
|
||||
public void m_5779_(FriendlyByteBuf p_132044_) {
|
||||
@@ -52,6 +_,7 @@
|
||||
p_132044_.m_130085_(this.f_132029_);
|
||||
- p_132044_.writeBytes(this.f_132030_.copy());
|
||||
+ p_132044_.writeBytes(this.f_132030_.slice()); // Use Slice instead of copy, to not update the read index, allowing packet to be sent multiple times.
|
||||
}
|
||||
|
||||
public void m_5797_(ClientGamePacketListener p_132041_) {
|
||||
p_132041_.m_7413_(this);
|
||||
@@ -41,3 +44,12 @@
|
||||
}
|
||||
|
||||
public ResourceLocation m_132042_() {
|
||||
@@ -61,4 +_,8 @@
|
||||
public FriendlyByteBuf m_132045_() {
|
||||
return new FriendlyByteBuf(this.f_132030_.copy());
|
||||
}
|
||||
+
|
||||
+ @Override public int getIndex() { return Integer.MAX_VALUE; }
|
||||
+ @Override public ResourceLocation getName() { return m_132042_(); }
|
||||
+ @org.jetbrains.annotations.Nullable @Override public FriendlyByteBuf getInternalData() { return this.f_132030_; }
|
||||
}
|
||||
+10
-1
@@ -14,7 +14,16 @@
|
||||
public void m_5779_(FriendlyByteBuf p_133994_) {
|
||||
p_133994_.m_130085_(this.f_133980_);
|
||||
- p_133994_.writeBytes((ByteBuf)this.f_133981_);
|
||||
+ p_133994_.writeBytes((ByteBuf)this.f_133981_.copy()); //This may be access multiple times, from multiple threads, lets be safe like the S->C packet
|
||||
+ p_133994_.writeBytes((ByteBuf)this.f_133981_.slice()); // Use Slice instead of copy, to not update the read index, allowing packet to be sent multiple times.
|
||||
}
|
||||
|
||||
public void m_5797_(ServerGamePacketListener p_133992_) {
|
||||
@@ -43,4 +_,8 @@
|
||||
public FriendlyByteBuf m_179590_() {
|
||||
return this.f_133981_;
|
||||
}
|
||||
+
|
||||
+ @Override public int getIndex() { return Integer.MAX_VALUE; }
|
||||
+ @Override public ResourceLocation getName() { return m_179589_(); }
|
||||
+ @org.jetbrains.annotations.Nullable @Override public FriendlyByteBuf getInternalData() { return m_179590_(); }
|
||||
}
|
||||
+18
@@ -9,3 +9,21 @@
|
||||
private static final int f_179804_ = 1048576;
|
||||
private final int f_134745_;
|
||||
private final ResourceLocation f_134746_;
|
||||
@@ -30,7 +_,7 @@
|
||||
public void m_5779_(FriendlyByteBuf p_134757_) {
|
||||
p_134757_.m_130130_(this.f_134745_);
|
||||
p_134757_.m_130085_(this.f_134746_);
|
||||
- p_134757_.writeBytes(this.f_134747_.copy());
|
||||
+ p_134757_.writeBytes(this.f_134747_.slice()); // Use Slice instead of copy, to not update the read index, allowing packet to be sent multiple times.
|
||||
}
|
||||
|
||||
public void m_5797_(ClientLoginPacketListener p_134754_) {
|
||||
@@ -48,4 +_,8 @@
|
||||
public FriendlyByteBuf m_179812_() {
|
||||
return this.f_134747_;
|
||||
}
|
||||
+
|
||||
+ @Override public int getIndex() { return m_134755_(); }
|
||||
+ @Override public ResourceLocation getName() { return m_179811_(); }
|
||||
+ @org.jetbrains.annotations.Nullable @Override public FriendlyByteBuf getInternalData() { return m_179812_(); }
|
||||
}
|
||||
+9
@@ -10,3 +10,12 @@
|
||||
private static final int f_179821_ = 1048576;
|
||||
private final int f_134825_;
|
||||
@Nullable
|
||||
@@ -46,4 +_,8 @@
|
||||
public FriendlyByteBuf m_179825_() {
|
||||
return this.f_134826_;
|
||||
}
|
||||
+
|
||||
+ @Override public int getIndex() { return m_179824_(); }
|
||||
+ @Override public net.minecraft.resources.ResourceLocation getName() { return net.minecraftforge.network.LoginWrapper.WRAPPER; }
|
||||
+ @org.jetbrains.annotations.Nullable @Override public FriendlyByteBuf getInternalData() { return m_179825_(); }
|
||||
}
|
||||
@@ -5,83 +5,24 @@
|
||||
|
||||
package net.minecraftforge.network;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ReferenceArrayMap;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.protocol.login.ServerboundCustomQueryPacket;
|
||||
import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket;
|
||||
import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.fml.unsafe.UnsafeHacks;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public interface ICustomPacket<T extends Packet<?>> {
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
enum Fields {
|
||||
CPACKETCUSTOMPAYLOAD(ServerboundCustomPayloadPacket.class),
|
||||
SPACKETCUSTOMPAYLOAD(ClientboundCustomPayloadPacket.class),
|
||||
CPACKETCUSTOMLOGIN(ServerboundCustomQueryPacket.class),
|
||||
SPACKETCUSTOMLOGIN(ClientboundCustomQueryPacket.class),
|
||||
;
|
||||
/**
|
||||
* Returns a unsafe reference to this packet's internal data.
|
||||
* Any modifications to this buffer will be reflected in the main buffer.
|
||||
*/
|
||||
@Nullable
|
||||
FriendlyByteBuf getInternalData();
|
||||
|
||||
static final Reference2ReferenceArrayMap<Class<?>, Fields> lookup;
|
||||
static {
|
||||
lookup = Stream.of(values()).
|
||||
collect(Collectors.toMap(Fields::getClazz, Function.identity(), (m1, m2)->m1, Reference2ReferenceArrayMap::new));
|
||||
}
|
||||
ResourceLocation getName();
|
||||
|
||||
private final Class<?> clazz;
|
||||
|
||||
final Optional<Field> data;
|
||||
final Optional<Field> channel;
|
||||
final Optional<Field> index;
|
||||
|
||||
Fields(Class<?> customPacketClass)
|
||||
{
|
||||
this.clazz = customPacketClass;
|
||||
Field[] fields = customPacketClass.getDeclaredFields();
|
||||
data = Arrays.stream(fields).filter(f-> !Modifier.isStatic(f.getModifiers()) && f.getType() == FriendlyByteBuf.class).findFirst();
|
||||
channel = Arrays.stream(fields).filter(f->!Modifier.isStatic(f.getModifiers()) && f.getType() == ResourceLocation.class).findFirst();
|
||||
index = Arrays.stream(fields).filter(f->!Modifier.isStatic(f.getModifiers()) && f.getType() == int.class).findFirst();
|
||||
}
|
||||
|
||||
private Class<?> getClazz()
|
||||
{
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
|
||||
default FriendlyByteBuf getInternalData() {
|
||||
return Fields.lookup.get(this.getClass()).data.map(f->UnsafeHacks.<FriendlyByteBuf>getField(f, this)).orElse(null);
|
||||
}
|
||||
|
||||
default ResourceLocation getName() {
|
||||
return Fields.lookup.get(this.getClass()).channel.map(f->UnsafeHacks.<ResourceLocation>getField(f, this)).orElse(LoginWrapper.WRAPPER);
|
||||
}
|
||||
|
||||
default int getIndex() {
|
||||
return Fields.lookup.get(this.getClass()).index.map(f->UnsafeHacks.getIntField(f, this)).orElse(Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
default void setData(FriendlyByteBuf buffer) {
|
||||
Fields.lookup.get(this.getClass()).data.ifPresent(f->UnsafeHacks.setField(f, this, buffer));
|
||||
}
|
||||
|
||||
default void setName(ResourceLocation channelName) {
|
||||
Fields.lookup.get(this.getClass()).channel.ifPresent(f->UnsafeHacks.setField(f, this, channelName));
|
||||
}
|
||||
|
||||
default void setIndex(int index) {
|
||||
Fields.lookup.get(this.getClass()).index.ifPresent(f->UnsafeHacks.setIntField(f, this, index));
|
||||
}
|
||||
int getIndex();
|
||||
|
||||
default NetworkDirection getDirection() {
|
||||
return NetworkDirection.directionFor(this.getClass());
|
||||
|
||||
@@ -13,6 +13,7 @@ import net.minecraftforge.network.event.EventNetworkChannel;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* Wrapper for custom login packets. Transforms unnamed login channel messages into channels dispatched the same
|
||||
@@ -21,7 +22,8 @@ import org.apache.logging.log4j.Logger;
|
||||
public class LoginWrapper
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
static final ResourceLocation WRAPPER = new ResourceLocation("fml:loginwrapper");
|
||||
@ApiStatus.Internal
|
||||
public static final ResourceLocation WRAPPER = new ResourceLocation("fml:loginwrapper");
|
||||
private EventNetworkChannel wrapperChannel;
|
||||
|
||||
LoginWrapper() {
|
||||
|
||||
@@ -14,7 +14,6 @@ import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import net.minecraftforge.fml.unsafe.UnsafeHacks;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
@@ -25,15 +24,16 @@ import java.util.stream.Stream;
|
||||
|
||||
public enum NetworkDirection
|
||||
{
|
||||
PLAY_TO_SERVER(NetworkEvent.ClientCustomPayloadEvent::new, LogicalSide.CLIENT, ServerboundCustomPayloadPacket.class, 1),
|
||||
PLAY_TO_CLIENT(NetworkEvent.ServerCustomPayloadEvent::new, LogicalSide.SERVER, ClientboundCustomPayloadPacket.class, 0),
|
||||
LOGIN_TO_SERVER(NetworkEvent.ClientCustomPayloadLoginEvent::new, LogicalSide.CLIENT, ServerboundCustomQueryPacket.class, 3),
|
||||
LOGIN_TO_CLIENT(NetworkEvent.ServerCustomPayloadLoginEvent::new, LogicalSide.SERVER, ClientboundCustomQueryPacket.class, 2);
|
||||
PLAY_TO_SERVER(NetworkEvent.ClientCustomPayloadEvent::new, LogicalSide.CLIENT, ServerboundCustomPayloadPacket.class, 1, (d, i, n) -> new ServerboundCustomPayloadPacket(n, d)),
|
||||
PLAY_TO_CLIENT(NetworkEvent.ServerCustomPayloadEvent::new, LogicalSide.SERVER, ClientboundCustomPayloadPacket.class, 0, (d, i, n) -> new ClientboundCustomPayloadPacket(n, d)),
|
||||
LOGIN_TO_SERVER(NetworkEvent.ClientCustomPayloadLoginEvent::new, LogicalSide.CLIENT, ServerboundCustomQueryPacket.class, 3, (d, i, n) -> new ServerboundCustomQueryPacket(i, d)),
|
||||
LOGIN_TO_CLIENT(NetworkEvent.ServerCustomPayloadLoginEvent::new, LogicalSide.SERVER, ClientboundCustomQueryPacket.class, 2, (d, i, n) -> new ClientboundCustomQueryPacket(i, n, d));
|
||||
|
||||
private final BiFunction<ICustomPacket<?>, Supplier<NetworkEvent.Context>, NetworkEvent> eventSupplier;
|
||||
private final LogicalSide logicalSide;
|
||||
private final Class<? extends Packet> packetClass;
|
||||
private final int otherWay;
|
||||
private final Factory factory;
|
||||
|
||||
private static final Reference2ReferenceArrayMap<Class<? extends Packet>, NetworkDirection> packetLookup;
|
||||
|
||||
@@ -42,12 +42,13 @@ public enum NetworkDirection
|
||||
collect(Collectors.toMap(NetworkDirection::getPacketClass, Function.identity(), (m1,m2)->m1, Reference2ReferenceArrayMap::new));
|
||||
}
|
||||
|
||||
NetworkDirection(BiFunction<ICustomPacket<?>, Supplier<NetworkEvent.Context>, NetworkEvent> eventSupplier, LogicalSide logicalSide, Class<? extends Packet> clazz, int i)
|
||||
private NetworkDirection(BiFunction<ICustomPacket<?>, Supplier<NetworkEvent.Context>, NetworkEvent> eventSupplier, LogicalSide logicalSide, Class<? extends Packet> clazz, int i, Factory factory)
|
||||
{
|
||||
this.eventSupplier = eventSupplier;
|
||||
this.logicalSide = logicalSide;
|
||||
this.packetClass = clazz;
|
||||
this.otherWay = i;
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
private Class<? extends Packet> getPacketClass() {
|
||||
@@ -75,10 +76,10 @@ public enum NetworkDirection
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Packet<?>> ICustomPacket<T> buildPacket(Pair<FriendlyByteBuf,Integer> packetData, ResourceLocation channelName)
|
||||
{
|
||||
ICustomPacket<T> packet = (ICustomPacket<T>)UnsafeHacks.newInstance(getPacketClass());
|
||||
packet.setName(channelName);
|
||||
packet.setData(packetData.getLeft());
|
||||
packet.setIndex(packetData.getRight());
|
||||
return packet;
|
||||
return this.factory.create(packetData.getLeft(), packetData.getRight(), channelName);
|
||||
}
|
||||
|
||||
private interface Factory<T extends Packet<?>> {
|
||||
ICustomPacket<T> create(FriendlyByteBuf data, Integer index, ResourceLocation channelName);
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,7 @@ public class IndexedMessageCodec
|
||||
}
|
||||
|
||||
void consume(FriendlyByteBuf payload, int payloadIndex, Supplier<NetworkEvent.Context> context) {
|
||||
if (payload == null) {
|
||||
if (payload == null || !payload.isReadable()) {
|
||||
LOGGER.error(SIMPLENET, "Received empty payload on channel {}", Optional.ofNullable(networkInstance).map(NetworkInstance::getChannelName).map(Objects::toString).orElse("MISSING CHANNEL"));
|
||||
if (!HandshakeHandler.packetNeedsResponse(context.get().getNetworkManager(), payloadIndex))
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user