[ci skip] Port to NeoForge 24w14a

Signed-off-by: shedaniel <daniel@shedaniel.me>
This commit is contained in:
shedaniel
2024-04-09 18:16:18 +09:00
parent d19cb9a8f1
commit 4e15fa3bbb
88 changed files with 5191 additions and 569 deletions

View File

@@ -46,9 +46,9 @@ public interface LootEvent {
*
* <h2>Example: adding diamonds as a drop for dirt</h2>
* <pre>{@code
* LootEvent.MODIFY_LOOT_TABLE.register((lootTables, id, context, builtin) -> {
* LootEvent.MODIFY_LOOT_TABLE.register((key, context, builtin) -> {
* // Check that the loot table is dirt and built-in
* if (builtin && Blocks.DIRT.getLootTable().equals(id)) {
* if (builtin && Blocks.DIRT.getLootTable().equals(key)) {
* // Create a loot pool with a single item entry of Items.DIAMOND
* LootPool.Builder pool = LootPool.lootPool().add(LootItem.lootTableItem(Items.DIAMOND));
* context.addPool(pool);
@@ -58,7 +58,7 @@ public interface LootEvent {
*
* @see ModifyLootTable#modifyLootTable(ResourceKey, LootTableModificationContext, boolean)
*/
// Event<ModifyLootTable> MODIFY_LOOT_TABLE = EventFactory.createLoop();
Event<ModifyLootTable> MODIFY_LOOT_TABLE = EventFactory.createLoop();
@FunctionalInterface
interface ModifyLootTable {

View File

@@ -19,7 +19,6 @@
package dev.architectury.fluid;
import com.google.common.collect.Iterators;
import com.mojang.serialization.Codec;
import dev.architectury.hooks.fluid.FluidStackHooks;
import dev.architectury.injectables.annotations.ExpectPlatform;
@@ -35,7 +34,8 @@ import net.minecraft.world.level.material.Fluids;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.Objects;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -66,100 +66,6 @@ public final class FluidStack implements DataComponentHolder {
throw new AssertionError();
}
@Override
public DataComponentMap getComponents() {
return new DataComponentMap() {
@Nullable
@Override
public <T> T get(DataComponentType<? extends T> type) {
return getPatch().get(type).orElse(null);
}
@Override
public Set<DataComponentType<?>> keySet() {
return new AbstractSet<>() {
@Override
public Iterator<DataComponentType<?>> iterator() {
return Iterators.transform(getPatch().entrySet().iterator(), Map.Entry::getKey);
}
@Override
public int size() {
return getPatch().entrySet().size();
}
@Override
public boolean contains(Object o) {
if (!(o instanceof DataComponentType<?> type)) return false;
return getPatch().get(type).isPresent();
}
};
}
};
}
public <T> T set(DataComponentType<? super T> dataComponentType, @Nullable T object) {
T previous = (T) get(dataComponentType);
DataComponentPatch.Builder builder = DataComponentPatch.builder();
for (TypedDataComponent<?> component : getComponents()) {
if (component.type() != dataComponentType) {
builder.set(component);
}
}
if (object != null) {
builder.set(dataComponentType, object);
}
setPatch(builder.build());
return previous;
}
@Nullable
public <T, U> T update(DataComponentType<T> dataComponentType, T object, U object2, BiFunction<T, U, T> biFunction) {
return this.set(dataComponentType, biFunction.apply(this.getOrDefault(dataComponentType, object), object2));
}
@Nullable
public <T> T update(DataComponentType<T> dataComponentType, T object, UnaryOperator<T> unaryOperator) {
return this.set(dataComponentType, unaryOperator.apply(this.getOrDefault(dataComponentType, object)));
}
@Nullable
public <T> T remove(DataComponentType<? extends T> dataComponentType) {
return this.set(dataComponentType, null);
}
public void applyComponents(DataComponentPatch dataComponentPatch) {
DataComponentPatch.Builder builder = DataComponentPatch.builder();
for (TypedDataComponent<?> component : getComponents()) {
builder.set(component);
}
for (Map.Entry<DataComponentType<?>, Optional<?>> entry : dataComponentPatch.entrySet()) {
if (entry.getValue().isPresent()) {
//noinspection rawtypes
builder.set((DataComponentType) entry.getKey(), entry.getValue().get());
} else {
builder.remove(entry.getKey());
}
}
setPatch(builder.build());
}
public void applyComponents(DataComponentMap dataComponentMap) {
DataComponentPatch.Builder builder = DataComponentPatch.builder();
for (TypedDataComponent<?> component : getComponents()) {
builder.set(component);
}
for (TypedDataComponent<?> entry : dataComponentMap) {
if (entry.value() != null) {
//noinspection rawtypes
builder.set((DataComponentType) entry.type(), entry.value());
} else {
builder.remove(entry.type());
}
}
setPatch(builder.build());
}
@ApiStatus.Internal
public interface FluidStackAdapter<T> {
T create(Supplier<Fluid> fluid, long amount, @Nullable DataComponentPatch patch);
@@ -174,7 +80,19 @@ public final class FluidStack implements DataComponentHolder {
DataComponentPatch getPatch(T value);
void setPatch(T value, DataComponentPatch patch);
PatchedDataComponentMap getComponents(T value);
void applyComponents(T value, DataComponentPatch patch);
void applyComponents(T value, DataComponentMap patch);
@Nullable <D> D set(T value, DataComponentType<? super D> type, @Nullable D component);
@Nullable <D> D remove(T value, DataComponentType<? extends D> type);
@Nullable <D> D update(T value, DataComponentType<D> type, D component, UnaryOperator<D> updater);
@Nullable <D, U> D update(T value, DataComponentType<D> type, D component, U updateContext, BiFunction<D, U, D> updater);
T copy(T value);
@@ -260,8 +178,37 @@ public final class FluidStack implements DataComponentHolder {
return ADAPTER.getPatch(value);
}
public void setPatch(DataComponentPatch patch) {
ADAPTER.setPatch(value, patch);
@Override
public PatchedDataComponentMap getComponents() {
return ADAPTER.getComponents(value);
}
public void applyComponents(DataComponentPatch patch) {
ADAPTER.applyComponents(value, patch);
}
public void applyComponents(DataComponentMap patch) {
ADAPTER.applyComponents(value, patch);
}
@Nullable
public <T> T set(DataComponentType<? super T> type, @Nullable T component) {
return ADAPTER.set(value, type, component);
}
@Nullable
public <T> T remove(DataComponentType<? extends T> type) {
return ADAPTER.remove(value, type);
}
@Nullable
public <T> T update(DataComponentType<T> type, T component, UnaryOperator<T> updater) {
return ADAPTER.update(value, type, component, updater);
}
@Nullable
public <T, U> T update(DataComponentType<T> type, T component, U updateContext, BiFunction<T, U, T> updater) {
return ADAPTER.update(value, type, component, updateContext, updater);
}
public Component getName() {

View File

@@ -0,0 +1,215 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package dev.architectury.impl;
import com.google.common.base.Suppliers;
import dev.architectury.networking.NetworkManager;
import dev.architectury.networking.transformers.PacketSink;
import dev.architectury.networking.transformers.PacketTransformer;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.ApiStatus;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
@ApiStatus.Internal
public class NetworkAggregator {
public static final Supplier<Adaptor> ADAPTOR = Suppliers.memoize(() -> {
try {
Method adaptor = NetworkManager.class.getDeclaredMethod("getAdaptor");
adaptor.setAccessible(true);
return (Adaptor) adaptor.invoke(null);
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
});
public static final Map<ResourceLocation, CustomPacketPayload.Type<BufCustomPacketPayload>> C2S_TYPE = new HashMap<>();
public static final Map<ResourceLocation, CustomPacketPayload.Type<BufCustomPacketPayload>> S2C_TYPE = new HashMap<>();
public static final Map<ResourceLocation, NetworkManager.NetworkReceiver<?>> C2S_RECEIVER = new HashMap<>();
public static final Map<ResourceLocation, NetworkManager.NetworkReceiver<?>> S2C_RECEIVER = new HashMap<>();
public static final Map<ResourceLocation, StreamCodec<ByteBuf, ?>> C2S_CODECS = new HashMap<>();
public static final Map<ResourceLocation, StreamCodec<ByteBuf, ?>> S2C_CODECS = new HashMap<>();
public static final Map<ResourceLocation, PacketTransformer> C2S_TRANSFORMERS = new HashMap<>();
public static final Map<ResourceLocation, PacketTransformer> S2C_TRANSFORMERS = new HashMap<>();
public static void registerReceiver(NetworkManager.Side side, ResourceLocation id, List<PacketTransformer> packetTransformers, NetworkManager.NetworkReceiver<RegistryFriendlyByteBuf> receiver) {
CustomPacketPayload.Type<BufCustomPacketPayload> type = new CustomPacketPayload.Type<>(id);
if (side == NetworkManager.Side.C2S) {
C2S_TYPE.put(id, type);
registerC2SReceiver(type, BufCustomPacketPayload.streamCodec(type), packetTransformers, (value, context) -> {
RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(Unpooled.wrappedBuffer(value.payload()), context.registryAccess());
receiver.receive(buf, context);
buf.release();
});
} else if (side == NetworkManager.Side.S2C) {
S2C_TYPE.put(id, type);
registerS2CReceiver(type, BufCustomPacketPayload.streamCodec(type), packetTransformers, (value, context) -> {
RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(Unpooled.wrappedBuffer(value.payload()), context.registryAccess());
receiver.receive(buf, context);
buf.release();
});
}
}
public static <T extends CustomPacketPayload> void registerReceiver(NetworkManager.Side side, CustomPacketPayload.Type<T> type, StreamCodec<? super RegistryFriendlyByteBuf, T> codec, List<PacketTransformer> packetTransformers, NetworkManager.NetworkReceiver<T> receiver) {
Objects.requireNonNull(type, "Cannot register receiver with a null type!");
packetTransformers = Objects.requireNonNullElse(packetTransformers, List.of());
Objects.requireNonNull(receiver, "Cannot register a null receiver!");
if (side == NetworkManager.Side.C2S) {
registerC2SReceiver(type, codec, packetTransformers, receiver);
} else if (side == NetworkManager.Side.S2C) {
registerS2CReceiver(type, codec, packetTransformers, receiver);
}
}
private static <T extends CustomPacketPayload> void registerC2SReceiver(CustomPacketPayload.Type<T> type, StreamCodec<? super RegistryFriendlyByteBuf, T> codec, List<PacketTransformer> packetTransformers, NetworkManager.NetworkReceiver<T> receiver) {
PacketTransformer transformer = PacketTransformer.concat(packetTransformers);
C2S_RECEIVER.put(type.id(), receiver);
C2S_CODECS.put(type.id(), (StreamCodec<ByteBuf, ?>) codec);
C2S_TRANSFORMERS.put(type.id(), transformer);
ADAPTOR.get().registerC2S((CustomPacketPayload.Type<BufCustomPacketPayload>) type, BufCustomPacketPayload.streamCodec((CustomPacketPayload.Type<BufCustomPacketPayload>) type), (payload, context) -> {
RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(Unpooled.wrappedBuffer(payload.payload()), context.registryAccess());
transformer.inbound(NetworkManager.Side.C2S, type.id(), buf, context, (side, id1, buf1) -> {
NetworkManager.NetworkReceiver<T> networkReceiver = (NetworkManager.NetworkReceiver<T>) (side == NetworkManager.Side.C2S ? C2S_RECEIVER.get(id1) : S2C_RECEIVER.get(id1));
if (networkReceiver == null) {
throw new IllegalArgumentException("Network Receiver not found! " + id1);
}
T actualPayload = codec.decode(buf1);
networkReceiver.receive(actualPayload, context);
});
buf.release();
});
}
private static <T extends CustomPacketPayload> void registerS2CReceiver(CustomPacketPayload.Type<T> type, StreamCodec<? super RegistryFriendlyByteBuf, T> codec, List<PacketTransformer> packetTransformers, NetworkManager.NetworkReceiver<T> receiver) {
PacketTransformer transformer = PacketTransformer.concat(packetTransformers);
S2C_RECEIVER.put(type.id(), receiver);
S2C_CODECS.put(type.id(), (StreamCodec<ByteBuf, ?>) codec);
S2C_TRANSFORMERS.put(type.id(), transformer);
ADAPTOR.get().registerS2C((CustomPacketPayload.Type<BufCustomPacketPayload>) type, BufCustomPacketPayload.streamCodec((CustomPacketPayload.Type<BufCustomPacketPayload>) type), (payload, context) -> {
RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(Unpooled.wrappedBuffer(payload.payload()), context.registryAccess());
transformer.inbound(NetworkManager.Side.S2C, type.id(), buf, context, (side, id1, buf1) -> {
NetworkManager.NetworkReceiver<T> networkReceiver = (NetworkManager.NetworkReceiver<T>) (side == NetworkManager.Side.C2S ? C2S_RECEIVER.get(id1) : S2C_RECEIVER.get(id1));
if (networkReceiver == null) {
throw new IllegalArgumentException("Network Receiver not found! " + id1);
}
T actualPayload = codec.decode(buf1);
networkReceiver.receive(actualPayload, context);
});
buf.release();
});
}
public static void collectPackets(PacketSink sink, NetworkManager.Side side, ResourceLocation id, RegistryFriendlyByteBuf buf) {
if (side == NetworkManager.Side.C2S) {
collectPackets(sink, side, new BufCustomPacketPayload(C2S_TYPE.get(id), ByteBufUtil.getBytes(buf)), buf.registryAccess());
} else {
collectPackets(sink, side, new BufCustomPacketPayload(S2C_TYPE.get(id), ByteBufUtil.getBytes(buf)), buf.registryAccess());
}
}
public static <T extends CustomPacketPayload> void collectPackets(PacketSink sink, NetworkManager.Side side, T payload, RegistryAccess access) {
CustomPacketPayload.Type<T> type = (CustomPacketPayload.Type<T>) payload.type();
PacketTransformer transformer = side == NetworkManager.Side.C2S ? C2S_TRANSFORMERS.get(type.id()) : S2C_TRANSFORMERS.get(type.id());
StreamCodec<ByteBuf, T> codec = (StreamCodec<ByteBuf, T>) (side == NetworkManager.Side.C2S ? C2S_CODECS.get(type.id()) : S2C_CODECS.get(type.id()));
RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(Unpooled.buffer(), access);
codec.encode(buf, payload);
if (transformer != null) {
transformer.outbound(side, type.id(), buf, (side1, id1, buf1) -> {
if (side == NetworkManager.Side.C2S) {
CustomPacketPayload.Type<BufCustomPacketPayload> type1 = C2S_TYPE.getOrDefault(id1, (CustomPacketPayload.Type<BufCustomPacketPayload>) type);
sink.accept(toPacket(side1, new BufCustomPacketPayload(type1, ByteBufUtil.getBytes(buf1))));
} else if (side == NetworkManager.Side.S2C) {
CustomPacketPayload.Type<BufCustomPacketPayload> type1 = S2C_TYPE.getOrDefault(id1, (CustomPacketPayload.Type<BufCustomPacketPayload>) type);
sink.accept(toPacket(side1, new BufCustomPacketPayload(type1, ByteBufUtil.getBytes(buf1))));
}
});
} else {
sink.accept(toPacket(side, new BufCustomPacketPayload((CustomPacketPayload.Type<BufCustomPacketPayload>) type, ByteBufUtil.getBytes(buf))));
}
buf.release();
}
public static <T extends CustomPacketPayload> Packet<?> toPacket(NetworkManager.Side side, T payload) {
if (side == NetworkManager.Side.C2S) {
return ADAPTOR.get().toC2SPacket(payload);
} else if (side == NetworkManager.Side.S2C) {
return ADAPTOR.get().toS2CPacket(payload);
}
throw new IllegalArgumentException("Invalid side: " + side);
}
public static void registerS2CType(ResourceLocation id, List<PacketTransformer> packetTransformers) {
CustomPacketPayload.Type<BufCustomPacketPayload> type = new CustomPacketPayload.Type<>(id);
S2C_TYPE.put(id, type);
registerS2CType(type, BufCustomPacketPayload.streamCodec(type), packetTransformers);
}
public static <T extends CustomPacketPayload> void registerS2CType(CustomPacketPayload.Type<T> type, StreamCodec<? super RegistryFriendlyByteBuf, T> codec, List<PacketTransformer> packetTransformers) {
Objects.requireNonNull(type, "Cannot register a null type!");
packetTransformers = Objects.requireNonNullElse(packetTransformers, List.of());
S2C_CODECS.put(type.id(), (StreamCodec<ByteBuf, ?>) codec);
S2C_TRANSFORMERS.put(type.id(), PacketTransformer.concat(packetTransformers));
ADAPTOR.get().registerS2CType((CustomPacketPayload.Type<BufCustomPacketPayload>) type, BufCustomPacketPayload.streamCodec((CustomPacketPayload.Type<BufCustomPacketPayload>) type));
}
public interface Adaptor {
<T extends CustomPacketPayload> void registerC2S(CustomPacketPayload.Type<T> type, StreamCodec<? super RegistryFriendlyByteBuf, T> codec, NetworkManager.NetworkReceiver<T> receiver);
@Environment(EnvType.CLIENT)
<T extends CustomPacketPayload> void registerS2C(CustomPacketPayload.Type<T> type, StreamCodec<? super RegistryFriendlyByteBuf, T> codec, NetworkManager.NetworkReceiver<T> receiver);
<T extends CustomPacketPayload> Packet<?> toC2SPacket(T payload);
@Environment(EnvType.CLIENT)
<T extends CustomPacketPayload> Packet<?> toS2CPacket(T payload);
<T extends CustomPacketPayload> void registerS2CType(CustomPacketPayload.Type<T> type, StreamCodec<? super RegistryFriendlyByteBuf, T> codec);
}
public record BufCustomPacketPayload(Type<BufCustomPacketPayload> _type,
byte[] payload) implements CustomPacketPayload {
@Override
public Type<? extends CustomPacketPayload> type() {
return this._type();
}
public static StreamCodec<ByteBuf, BufCustomPacketPayload> streamCodec(Type<BufCustomPacketPayload> type) {
return ByteBufCodecs.BYTE_ARRAY.map(bytes -> new BufCustomPacketPayload(type, bytes), BufCustomPacketPayload::payload);
}
}
}

View File

@@ -27,12 +27,16 @@ import io.netty.buffer.Unpooled;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.protocol.Packet;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
@@ -60,7 +64,7 @@ public final class NetworkChannel {
var s = UUID.nameUUIDFromBytes(type.getName().getBytes(StandardCharsets.UTF_8)).toString().replace("-", "");
var info = new MessageInfo<T>(new ResourceLocation(id + "/" + s), encoder, decoder, messageConsumer);
encoders.put(type, info);
NetworkManager.NetworkReceiver receiver = (buf, context) -> {
NetworkManager.NetworkReceiver<RegistryFriendlyByteBuf> receiver = (buf, context) -> {
info.messageConsumer.accept(info.decoder.apply(buf), () -> context);
};
NetworkManager.registerReceiver(NetworkManager.c2s(), info.packetId, receiver);
@@ -78,19 +82,21 @@ public final class NetworkChannel {
return h;
}
public <T> Packet<?> toPacket(NetworkManager.Side side, T message) {
public <T> Packet<?> toPacket(NetworkManager.Side side, T message, RegistryAccess access) {
var messageInfo = (MessageInfo<T>) Objects.requireNonNull(encoders.get(message.getClass()), "Unknown message type! " + message);
var buf = new FriendlyByteBuf(Unpooled.buffer());
var buf = new RegistryFriendlyByteBuf(Unpooled.buffer(), access);
messageInfo.encoder.accept(message, buf);
return NetworkManager.toPacket(side, messageInfo.packetId, buf);
}
public <T> void sendToPlayer(ServerPlayer player, T message) {
Objects.requireNonNull(player, "Unable to send packet to a 'null' player!").connection.send(toPacket(NetworkManager.s2c(), message));
Objects.requireNonNull(player, "Unable to send packet to a 'null' player!").connection.send(toPacket(NetworkManager.s2c(), message, player.registryAccess()));
}
public <T> void sendToPlayers(Iterable<ServerPlayer> players, T message) {
var packet = toPacket(NetworkManager.s2c(), message);
Iterator<ServerPlayer> iterator = players.iterator();
if (!iterator.hasNext()) return;
var packet = toPacket(NetworkManager.s2c(), message, iterator.next().registryAccess());
for (var player : players) {
Objects.requireNonNull(player, "Unable to send packet to a 'null' player!").connection.send(packet);
}
@@ -98,8 +104,9 @@ public final class NetworkChannel {
@Environment(EnvType.CLIENT)
public <T> void sendToServer(T message) {
if (Minecraft.getInstance().getConnection() != null) {
Minecraft.getInstance().getConnection().send(toPacket(NetworkManager.c2s(), message));
ClientPacketListener connection = Minecraft.getInstance().getConnection();
if (connection != null) {
connection.send(toPacket(NetworkManager.c2s(), message, connection.registryAccess()));
} else {
throw new IllegalStateException("Unable to send packet to the server while not in game!");
}

View File

@@ -19,16 +19,22 @@
package dev.architectury.networking;
import dev.architectury.impl.NetworkAggregator;
import dev.architectury.injectables.annotations.ExpectPlatform;
import dev.architectury.networking.transformers.PacketCollector;
import dev.architectury.networking.transformers.PacketSink;
import dev.architectury.networking.transformers.PacketTransformer;
import dev.architectury.networking.transformers.SinglePacketCollector;
import dev.architectury.utils.Env;
import dev.architectury.utils.GameInstance;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
@@ -37,53 +43,112 @@ import net.minecraft.world.entity.player.Player;
import org.jetbrains.annotations.ApiStatus;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public final class NetworkManager {
public static void registerReceiver(Side side, ResourceLocation id, NetworkReceiver receiver) {
/**
* For S2C types, {@link #registerReceiver} should be called on the client side,
* while {@link #registerS2CPayloadType} should be called on the server side.
*/
public static void registerS2CPayloadType(ResourceLocation id) {
NetworkAggregator.registerS2CType(id, List.of());
}
/**
* For S2C types, {@link #registerReceiver} should be called on the client side,
* while {@link #registerS2CPayloadType} should be called on the server side.
*/
public static <T extends CustomPacketPayload> void registerS2CPayloadType(CustomPacketPayload.Type<T> type, StreamCodec<? super RegistryFriendlyByteBuf, T> codec) {
NetworkAggregator.registerS2CType(type, codec, List.of());
}
/**
* For S2C types, {@link #registerReceiver} should be called on the client side,
* while {@link #registerS2CPayloadType} should be called on the server side.
*/
public static void registerS2CPayloadType(ResourceLocation id, List<PacketTransformer> packetTransformers) {
NetworkAggregator.registerS2CType(id, packetTransformers);
}
/**
* For S2C types, {@link #registerReceiver} should be called on the client side,
* while {@link #registerS2CPayloadType} should be called on the server side.
*/
public static <T extends CustomPacketPayload> void registerS2CPayloadType(CustomPacketPayload.Type<T> type, StreamCodec<? super RegistryFriendlyByteBuf, T> codec, List<PacketTransformer> packetTransformers) {
NetworkAggregator.registerS2CType(type, codec, packetTransformers);
}
public static void registerReceiver(Side side, ResourceLocation id, NetworkReceiver<RegistryFriendlyByteBuf> receiver) {
registerReceiver(side, id, Collections.emptyList(), receiver);
}
@ExpectPlatform
@ApiStatus.Experimental
public static void registerReceiver(Side side, ResourceLocation id, List<PacketTransformer> packetTransformers, NetworkReceiver receiver) {
throw new AssertionError();
public static void registerReceiver(Side side, ResourceLocation id, List<PacketTransformer> packetTransformers, NetworkReceiver<RegistryFriendlyByteBuf> receiver) {
NetworkAggregator.registerReceiver(side, id, packetTransformers, receiver);
}
public static <T extends CustomPacketPayload> void registerReceiver(Side side, CustomPacketPayload.Type<T> id, StreamCodec<? super RegistryFriendlyByteBuf, T> codec, NetworkReceiver<T> receiver) {
registerReceiver(side, id, codec, Collections.emptyList(), receiver);
}
@ApiStatus.Experimental
public static <T extends CustomPacketPayload> void registerReceiver(Side side, CustomPacketPayload.Type<T> id, StreamCodec<? super RegistryFriendlyByteBuf, T> codec, List<PacketTransformer> packetTransformers, NetworkReceiver<T> receiver) {
NetworkAggregator.registerReceiver(side, id, codec, packetTransformers, receiver);
}
@Deprecated
@ApiStatus.ScheduledForRemoval
public static Packet<?> toPacket(Side side, ResourceLocation id, FriendlyByteBuf buf) {
public static Packet<?> toPacket(Side side, ResourceLocation id, RegistryFriendlyByteBuf buf) {
SinglePacketCollector sink = new SinglePacketCollector(null);
collectPackets(sink, side, id, buf);
return sink.getPacket();
}
@Deprecated
@ApiStatus.ScheduledForRemoval
public static List<Packet<?>> toPackets(Side side, ResourceLocation id, FriendlyByteBuf buf) {
public static List<Packet<?>> toPackets(Side side, ResourceLocation id, RegistryFriendlyByteBuf buf) {
PacketCollector sink = new PacketCollector(null);
collectPackets(sink, side, id, buf);
return sink.collect();
}
@ExpectPlatform
public static void collectPackets(PacketSink sink, Side side, ResourceLocation id, FriendlyByteBuf buf) {
throw new AssertionError();
public static void collectPackets(PacketSink sink, Side side, ResourceLocation id, RegistryFriendlyByteBuf buf) {
NetworkAggregator.collectPackets(sink, side, id, buf);
}
public static void sendToPlayer(ServerPlayer player, ResourceLocation id, FriendlyByteBuf buf) {
public static <T extends CustomPacketPayload> void collectPackets(PacketSink sink, Side side, T payload, RegistryAccess access) {
NetworkAggregator.collectPackets(sink, side, payload, access);
}
public static void sendToPlayer(ServerPlayer player, ResourceLocation id, RegistryFriendlyByteBuf buf) {
collectPackets(PacketSink.ofPlayer(player), serverToClient(), id, buf);
}
public static void sendToPlayers(Iterable<ServerPlayer> players, ResourceLocation id, FriendlyByteBuf buf) {
public static void sendToPlayers(Iterable<ServerPlayer> players, ResourceLocation id, RegistryFriendlyByteBuf buf) {
collectPackets(PacketSink.ofPlayers(players), serverToClient(), id, buf);
}
@Environment(EnvType.CLIENT)
public static void sendToServer(ResourceLocation id, FriendlyByteBuf buf) {
public static void sendToServer(ResourceLocation id, RegistryFriendlyByteBuf buf) {
collectPackets(PacketSink.client(), clientToServer(), id, buf);
}
public static <T extends CustomPacketPayload> void sendToPlayer(ServerPlayer player, T payload) {
collectPackets(PacketSink.ofPlayer(player), serverToClient(), payload, player.registryAccess());
}
public static <T extends CustomPacketPayload> void sendToPlayers(Iterable<ServerPlayer> players, T payload) {
Iterator<ServerPlayer> iterator = players.iterator();
if (!iterator.hasNext()) return;
collectPackets(PacketSink.ofPlayers(players), serverToClient(), payload, iterator.next().registryAccess());
}
@Environment(EnvType.CLIENT)
public static <T extends CustomPacketPayload> void sendToServer(T payload) {
ClientPacketListener connection = GameInstance.getClient().getConnection();
if (connection == null) return;
collectPackets(PacketSink.client(), clientToServer(), payload, connection.registryAccess());
}
@Environment(EnvType.CLIENT)
@ExpectPlatform
public static boolean canServerReceive(ResourceLocation id) {
@@ -112,9 +177,14 @@ public final class NetworkManager {
throw new AssertionError();
}
@ExpectPlatform
private static NetworkAggregator.Adaptor getAdaptor() {
throw new AssertionError();
}
@FunctionalInterface
public interface NetworkReceiver {
void receive(FriendlyByteBuf buf, PacketContext context);
public interface NetworkReceiver<T> {
void receive(T value, PacketContext context);
}
public interface PacketContext {
@@ -124,6 +194,8 @@ public final class NetworkManager {
Env getEnvironment();
RegistryAccess registryAccess();
default EnvType getEnv() {
return getEnvironment().toPlatform();
}

View File

@@ -26,6 +26,7 @@ import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.resources.ResourceLocation;
@@ -41,7 +42,7 @@ public class SpawnEntityPacket {
if (entity.level().isClientSide()) {
throw new IllegalStateException("SpawnPacketUtil.create called on the logical client!");
}
var buffer = new FriendlyByteBuf(Unpooled.buffer());
var buffer = new RegistryFriendlyByteBuf(Unpooled.buffer(), entity.registryAccess());
buffer.writeVarInt(BuiltInRegistries.ENTITY_TYPE.getId(entity.getType()));
buffer.writeUUID(entity.getUUID());
buffer.writeVarInt(entity.getId());
@@ -62,6 +63,10 @@ public class SpawnEntityPacket {
return (Packet<ClientGamePacketListener>) NetworkManager.toPacket(NetworkManager.s2c(), PACKET_ID, buffer);
}
public static void register() {
NetworkManager.registerS2CPayloadType(PACKET_ID);
}
@Environment(EnvType.CLIENT)
public static class Client {

View File

@@ -33,7 +33,7 @@ public abstract class BaseC2SMessage extends Message {
@Environment(EnvType.CLIENT)
public final void sendToServer() {
if (Minecraft.getInstance().getConnection() != null) {
Minecraft.getInstance().getConnection().send(toPacket());
Minecraft.getInstance().getConnection().send(toPacket(Minecraft.getInstance().level.registryAccess()));
} else {
throw new IllegalStateException("Unable to send packet to the server while not in game!");
}

View File

@@ -44,7 +44,7 @@ public abstract class BaseS2CMessage extends Message {
* @param player the player
*/
public final void sendTo(ServerPlayer player) {
sendTo(player, toPacket());
sendTo(player, toPacket(player.registryAccess()));
}
/**
@@ -53,7 +53,8 @@ public abstract class BaseS2CMessage extends Message {
* @param players the players
*/
public final void sendTo(Iterable<ServerPlayer> players) {
Packet<?> packet = toPacket();
if (!players.iterator().hasNext()) return;
Packet<?> packet = toPacket(players.iterator().next().registryAccess());
for (ServerPlayer player : players) {
sendTo(player, packet);
@@ -84,7 +85,7 @@ public abstract class BaseS2CMessage extends Message {
* @param chunk the listened chunk
*/
public final void sendToChunkListeners(LevelChunk chunk) {
Packet<?> packet = toPacket();
Packet<?> packet = toPacket(chunk.getLevel().registryAccess());
((ServerChunkCache) chunk.getLevel().getChunkSource()).chunkMap.getPlayers(chunk.getPos(), false).forEach(e -> sendTo(e, packet));
}
}

View File

@@ -21,7 +21,8 @@ package dev.architectury.networking.simple;
import dev.architectury.networking.NetworkManager;
import io.netty.buffer.Unpooled;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.protocol.Packet;
/**
@@ -48,7 +49,7 @@ public abstract class Message {
*
* @param buf the byte buffer
*/
public abstract void write(FriendlyByteBuf buf);
public abstract void write(RegistryFriendlyByteBuf buf);
/**
* Handles this message when it is received.
@@ -62,8 +63,8 @@ public abstract class Message {
*
* @return the converted {@link Packet}
*/
public final Packet<?> toPacket() {
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
public final Packet<?> toPacket(RegistryAccess access) {
RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(Unpooled.buffer(), access);
write(buf);
return NetworkManager.toPacket(getType().getSide(), getType().getId(), buf);
}

View File

@@ -20,10 +20,10 @@
package dev.architectury.networking.simple;
import dev.architectury.networking.NetworkManager;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
/**
* Decodes a {@link Message} from a {@link FriendlyByteBuf}.
* Decodes a {@link Message} from a {@link RegistryFriendlyByteBuf}.
*
* @param <T> the message type handled by this decoder
* @author LatvianModder
@@ -36,17 +36,17 @@ public interface MessageDecoder<T extends Message> {
* @param buf the byte buffer
* @return the decoded instance
*/
T decode(FriendlyByteBuf buf);
T decode(RegistryFriendlyByteBuf buf);
/**
* Creates a network receiver from this decoder.
*
* <p>The returned receiver will first {@linkplain #decode(FriendlyByteBuf) decode a message}
* <p>The returned receiver will first {@linkplain #decode(RegistryFriendlyByteBuf) decode a message}
* and then call {@link Message#handle(NetworkManager.PacketContext)} on the decoded message.
*
* @return the created receiver
*/
default NetworkManager.NetworkReceiver createReceiver() {
default NetworkManager.NetworkReceiver<RegistryFriendlyByteBuf> createReceiver() {
return (buf, context) -> {
Message packet = decode(buf);
context.queue(() -> packet.handle(context));

View File

@@ -23,6 +23,7 @@ import dev.architectury.networking.NetworkManager;
import dev.architectury.networking.transformers.PacketTransformer;
import dev.architectury.platform.Platform;
import dev.architectury.utils.Env;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.ApiStatus;
@@ -77,7 +78,7 @@ public class SimpleNetworkManager {
MessageType messageType = new MessageType(this, new ResourceLocation(namespace, id), NetworkManager.s2c());
if (Platform.getEnvironment() == Env.CLIENT) {
NetworkManager.NetworkReceiver receiver = decoder.createReceiver();
NetworkManager.NetworkReceiver<RegistryFriendlyByteBuf> receiver = decoder.createReceiver();
NetworkManager.registerReceiver(NetworkManager.s2c(), messageType.getId(), transformers, receiver);
}
@@ -107,7 +108,7 @@ public class SimpleNetworkManager {
@ApiStatus.Experimental
public MessageType registerC2S(String id, MessageDecoder<BaseC2SMessage> decoder, List<PacketTransformer> transformers) {
MessageType messageType = new MessageType(this, new ResourceLocation(namespace, id), NetworkManager.c2s());
NetworkManager.NetworkReceiver receiver = decoder.createReceiver();
NetworkManager.NetworkReceiver<RegistryFriendlyByteBuf> receiver = decoder.createReceiver();
NetworkManager.registerReceiver(NetworkManager.c2s(), messageType.getId(), transformers, receiver);
return messageType;
}

View File

@@ -0,0 +1,21 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@Deprecated(forRemoval = true)
package dev.architectury.networking.simple;

View File

@@ -20,7 +20,7 @@
package dev.architectury.networking.transformers;
import dev.architectury.networking.NetworkManager;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
@@ -31,24 +31,24 @@ import java.util.List;
@ApiStatus.Experimental
public interface PacketTransformer {
void inbound(NetworkManager.Side side, ResourceLocation id, FriendlyByteBuf buf, NetworkManager.PacketContext context, TransformationSink sink);
void inbound(NetworkManager.Side side, ResourceLocation id, RegistryFriendlyByteBuf buf, NetworkManager.PacketContext context, TransformationSink sink);
void outbound(NetworkManager.Side side, ResourceLocation id, FriendlyByteBuf buf, TransformationSink sink);
void outbound(NetworkManager.Side side, ResourceLocation id, RegistryFriendlyByteBuf buf, TransformationSink sink);
@FunctionalInterface
interface TransformationSink {
void accept(NetworkManager.Side side, ResourceLocation id, FriendlyByteBuf buf);
void accept(NetworkManager.Side side, ResourceLocation id, RegistryFriendlyByteBuf buf);
}
static PacketTransformer none() {
return new PacketTransformer() {
@Override
public void inbound(NetworkManager.Side side, ResourceLocation id, FriendlyByteBuf buf, NetworkManager.PacketContext context, TransformationSink sink) {
public void inbound(NetworkManager.Side side, ResourceLocation id, RegistryFriendlyByteBuf buf, NetworkManager.PacketContext context, TransformationSink sink) {
sink.accept(side, id, buf);
}
@Override
public void outbound(NetworkManager.Side side, ResourceLocation id, FriendlyByteBuf buf, TransformationSink sink) {
public void outbound(NetworkManager.Side side, ResourceLocation id, RegistryFriendlyByteBuf buf, TransformationSink sink) {
sink.accept(side, id, buf);
}
};
@@ -62,16 +62,16 @@ public interface PacketTransformer {
}
return new PacketTransformer() {
@Override
public void inbound(NetworkManager.Side side, ResourceLocation id, FriendlyByteBuf buf, NetworkManager.PacketContext context, TransformationSink sink) {
public void inbound(NetworkManager.Side side, ResourceLocation id, RegistryFriendlyByteBuf buf, NetworkManager.PacketContext context, TransformationSink sink) {
traverse(side, id, buf, context, sink, true, 0);
}
@Override
public void outbound(NetworkManager.Side side, ResourceLocation id, FriendlyByteBuf buf, TransformationSink sink) {
public void outbound(NetworkManager.Side side, ResourceLocation id, RegistryFriendlyByteBuf buf, TransformationSink sink) {
traverse(side, id, buf, null, sink, false, 0);
}
private void traverse(NetworkManager.Side side, ResourceLocation id, FriendlyByteBuf buf, @Nullable NetworkManager.PacketContext context, TransformationSink outerSink, boolean inbound, int index) {
private void traverse(NetworkManager.Side side, ResourceLocation id, RegistryFriendlyByteBuf buf, @Nullable NetworkManager.PacketContext context, TransformationSink outerSink, boolean inbound, int index) {
if (transformers instanceof List) {
if (((List<? extends PacketTransformer>) transformers).size() > index) {
PacketTransformer transformer = ((List<? extends PacketTransformer>) transformers).get(index);

View File

@@ -28,7 +28,7 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -81,7 +81,7 @@ public class SplitPacketTransformer implements PacketTransformer {
private static class PartData {
private final ResourceLocation id;
private final int partsExpected;
private final List<FriendlyByteBuf> parts;
private final List<RegistryFriendlyByteBuf> parts;
public PartData(ResourceLocation id, int partsExpected) {
this.id = id;
@@ -109,7 +109,7 @@ public class SplitPacketTransformer implements PacketTransformer {
}
@Override
public void inbound(NetworkManager.Side side, ResourceLocation id, FriendlyByteBuf buf, NetworkManager.PacketContext context, TransformationSink sink) {
public void inbound(NetworkManager.Side side, ResourceLocation id, RegistryFriendlyByteBuf buf, NetworkManager.PacketContext context, TransformationSink sink) {
PartKey key = side == NetworkManager.Side.S2C ? new PartKey(side, null) : new PartKey(side, context.getPlayer().getUUID());
PartData data;
switch (buf.readByte()) {
@@ -128,7 +128,7 @@ public class SplitPacketTransformer implements PacketTransformer {
} else if (!data.id.equals(id)) {
LOGGER.warn("Received invalid PART packet for SplitPacketTransformer with packet id " + id + " for side " + side + ", id in cache is " + data.id);
buf.release();
for (FriendlyByteBuf part : data.parts) {
for (RegistryFriendlyByteBuf part : data.parts) {
if (part != buf) {
part.release();
}
@@ -146,7 +146,7 @@ public class SplitPacketTransformer implements PacketTransformer {
} else if (!data.id.equals(id)) {
LOGGER.warn("Received invalid END packet for SplitPacketTransformer with packet id " + id + " for side " + side + ", id in cache is " + data.id);
buf.release();
for (FriendlyByteBuf part : data.parts) {
for (RegistryFriendlyByteBuf part : data.parts) {
if (part != buf) {
part.release();
}
@@ -158,13 +158,13 @@ public class SplitPacketTransformer implements PacketTransformer {
}
if (data.parts.size() != data.partsExpected) {
LOGGER.warn("Received invalid END packet for SplitPacketTransformer with packet id " + id + " for side " + side + " with size " + data.parts + ", parts expected is " + data.partsExpected);
for (FriendlyByteBuf part : data.parts) {
for (RegistryFriendlyByteBuf part : data.parts) {
if (part != buf) {
part.release();
}
}
} else {
FriendlyByteBuf byteBuf = new FriendlyByteBuf(Unpooled.wrappedBuffer(data.parts.toArray(new ByteBuf[0])));
RegistryFriendlyByteBuf byteBuf = new RegistryFriendlyByteBuf(Unpooled.wrappedBuffer(data.parts.toArray(new ByteBuf[0])), buf.registryAccess());
sink.accept(side, data.id, byteBuf);
byteBuf.release();
}
@@ -179,18 +179,18 @@ public class SplitPacketTransformer implements PacketTransformer {
}
@Override
public void outbound(NetworkManager.Side side, ResourceLocation id, FriendlyByteBuf buf, TransformationSink sink) {
public void outbound(NetworkManager.Side side, ResourceLocation id, RegistryFriendlyByteBuf buf, TransformationSink sink) {
int maxSize = (side == NetworkManager.Side.C2S ? 32767 : 1048576) - 1 - 20 - id.toString().getBytes(StandardCharsets.UTF_8).length;
if (buf.readableBytes() <= maxSize) {
ByteBuf stateBuf = Unpooled.buffer(1);
stateBuf.writeByte(ONLY);
FriendlyByteBuf packetBuffer = new FriendlyByteBuf(Unpooled.wrappedBuffer(stateBuf, buf));
RegistryFriendlyByteBuf packetBuffer = new RegistryFriendlyByteBuf(Unpooled.wrappedBuffer(stateBuf, buf), buf.registryAccess());
sink.accept(side, id, packetBuffer);
} else {
int partSize = maxSize - 4;
int parts = (int) Math.ceil(buf.readableBytes() / (float) partSize);
for (int i = 0; i < parts; i++) {
FriendlyByteBuf packetBuffer = new FriendlyByteBuf(Unpooled.buffer());
RegistryFriendlyByteBuf packetBuffer = new RegistryFriendlyByteBuf(Unpooled.buffer(), buf.registryAccess());
if (i == 0) {
packetBuffer.writeByte(START);
packetBuffer.writeInt(parts);