Forráskód Böngészése

PlayerHooks and NetworkChannel

shedaniel 4 éve
szülő
commit
7f552f19db

+ 43 - 0
common/src/main/java/me/shedaniel/architectury/hooks/PlayerHooks.java

@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020 shedaniel
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package me.shedaniel.architectury.hooks;
+
+import me.shedaniel.architectury.ArchitecturyPopulator;
+import me.shedaniel.architectury.Populatable;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.world.entity.player.Player;
+
+@Environment(EnvType.CLIENT)
+public final class PlayerHooks {
+    private PlayerHooks() {}
+    
+    @Populatable
+    private static final Impl IMPL = null;
+    
+    public static boolean isFake(Player player) {
+        return IMPL.isFake(player);
+    }
+    
+    public interface Impl {
+        boolean isFake(Player player);
+    }
+    
+    static {
+        ArchitecturyPopulator.populate(PlayerHooks.class);
+    }
+}

+ 130 - 0
common/src/main/java/me/shedaniel/architectury/networking/NetworkChannel.java

@@ -0,0 +1,130 @@
+/*
+ * Copyright 2020 shedaniel
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package me.shedaniel.architectury.networking;
+
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
+import io.netty.buffer.Unpooled;
+import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
+import it.unimi.dsi.fastutil.ints.IntSet;
+import me.shedaniel.architectury.networking.NetworkManager.PacketContext;
+import me.shedaniel.architectury.platform.Platform;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.client.Minecraft;
+import net.minecraft.network.FriendlyByteBuf;
+import net.minecraft.network.protocol.Packet;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.server.level.ServerPlayer;
+import org.apache.commons.lang3.tuple.Pair;
+
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/**
+ * Forge {@code SimpleChannel} like network wrapper of {@link NetworkManager}.
+ */
+public final class NetworkChannel {
+    private final ResourceLocation id;
+    private final IntSet takenIds = new IntOpenHashSet();
+    private final Table<NetworkManager.Side, Class<?>, Pair<ResourceLocation, BiConsumer<?, FriendlyByteBuf>>> encoders = HashBasedTable.create();
+    
+    private NetworkChannel(ResourceLocation id) {
+        this.id = id;
+    }
+    
+    public static NetworkChannel create(ResourceLocation id) {
+        return new NetworkChannel(id);
+    }
+    
+    public <T> void register(NetworkManager.Side side, Class<T> type, BiConsumer<T, FriendlyByteBuf> encoder, Function<FriendlyByteBuf, T> decoder, BiConsumer<T, Supplier<PacketContext>> messageConsumer) {
+        register(Optional.ofNullable(side), type, encoder, decoder, messageConsumer);
+    }
+    
+    public <T> void register(Optional<NetworkManager.Side> side, Class<T> type, BiConsumer<T, FriendlyByteBuf> encoder, Function<FriendlyByteBuf, T> decoder, BiConsumer<T, Supplier<PacketContext>> messageConsumer) {
+        for (int i = 0; ; i++) {
+            if (!takenIds.contains(i)) {
+                register(side, i, type, encoder, decoder, messageConsumer);
+                break;
+            }
+        }
+    }
+    
+    public <T> void register(NetworkManager.Side side, int id, Class<T> type, BiConsumer<T, FriendlyByteBuf> encoder, Function<FriendlyByteBuf, T> decoder, BiConsumer<T, Supplier<PacketContext>> messageConsumer) {
+        register(Optional.ofNullable(side), id, type, encoder, decoder, messageConsumer);
+    }
+    
+    public <T> void register(Optional<NetworkManager.Side> side, int id, Class<T> type, BiConsumer<T, FriendlyByteBuf> encoder, Function<FriendlyByteBuf, T> decoder, BiConsumer<T, Supplier<PacketContext>> messageConsumer) {
+        takenIds.add(id);
+        ResourceLocation messageId = new ResourceLocation(this.id.getNamespace(), this.id.getPath() + "_" + id);
+        if (!side.isPresent() || side.get() == NetworkManager.s2c()) {
+            if (Platform.getEnv() == EnvType.CLIENT) {
+                NetworkManager.registerReceiver(NetworkManager.s2c(), messageId, (buf, context) -> {
+                    messageConsumer.accept(decoder.apply(buf), () -> context);
+                });
+            }
+            encoders.put(NetworkManager.s2c(), type, Pair.of(messageId, encoder));
+        }
+        if (!side.isPresent() || side.get() == NetworkManager.c2s()) {
+            NetworkManager.registerReceiver(NetworkManager.c2s(), messageId, (buf, context) -> {
+                messageConsumer.accept(decoder.apply(buf), () -> context);
+            });
+            encoders.put(NetworkManager.c2s(), type, Pair.of(messageId, encoder));
+        }
+    }
+    
+    private <T> Pair<ResourceLocation, FriendlyByteBuf> encode(NetworkManager.Side side, T message) {
+        Pair<ResourceLocation, BiConsumer<?, FriendlyByteBuf>> pair = Objects.requireNonNull(encoders.get(side, message.getClass()));
+        FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
+        ((BiConsumer<T, FriendlyByteBuf>) pair.getRight()).accept(message, buf);
+        return Pair.of(pair.getLeft(), buf);
+    }
+    
+    public <T> Packet<?> toPacket(NetworkManager.Side side, T message) {
+        Pair<ResourceLocation, FriendlyByteBuf> encoded = encode(side, message);
+        return NetworkManager.toPacket(side, encoded.getLeft(), encoded.getRight());
+    }
+    
+    public <T> void sendToPlayer(ServerPlayer player, T message) {
+        Pair<ResourceLocation, FriendlyByteBuf> encoded = encode(NetworkManager.s2c(), message);
+        NetworkManager.sendToPlayer(player, encoded.getLeft(), encoded.getRight());
+    }
+    
+    public <T> void sendToPlayers(Iterable<ServerPlayer> players, T message) {
+        Packet<?> packet = toPacket(NetworkManager.s2c(), message);
+        for (ServerPlayer player : players) {
+            player.connection.send(packet);
+        }
+    }
+    
+    @Environment(EnvType.CLIENT)
+    public <T> void sendToServer(T message) {
+        Minecraft.getInstance().getConnection().send(toPacket(NetworkManager.c2s(), message));
+    }
+    
+    @Environment(EnvType.CLIENT)
+    public <T> boolean canServerReceive(Class<T> type) {
+        return NetworkManager.canServerReceive(encoders.get(NetworkManager.c2s(), type).getLeft());
+    }
+    
+    public <T> boolean canPlayerReceive(ServerPlayer player, Class<T> type) {
+        return NetworkManager.canPlayerReceive(player, encoders.get(NetworkManager.s2c(), type).getLeft());
+    }
+}

+ 27 - 0
fabric/src/main/java/me/shedaniel/architectury/hooks/fabric/PlayerHooksImpl.java

@@ -0,0 +1,27 @@
+/*
+ * Copyright 2020 shedaniel
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package me.shedaniel.architectury.hooks.fabric;
+
+import me.shedaniel.architectury.hooks.PlayerHooks;
+import net.minecraft.world.entity.player.Player;
+
+public class PlayerHooksImpl implements PlayerHooks.Impl {
+    @Override
+    public boolean isFake(Player player) {
+        return false;
+    }
+}

+ 28 - 0
forge/src/main/java/me/shedaniel/architectury/hooks/forge/PlayerHooksImpl.java

@@ -0,0 +1,28 @@
+/*
+ * Copyright 2020 shedaniel
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package me.shedaniel.architectury.hooks.forge;
+
+import me.shedaniel.architectury.hooks.PlayerHooks;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraftforge.common.util.FakePlayer;
+
+public class PlayerHooksImpl implements PlayerHooks.Impl {
+    @Override
+    public boolean isFake(PlayerEntity playerEntity) {
+        return playerEntity instanceof FakePlayer;
+    }
+}