forked from FabricMC/fabric
final module name refactor prior to release, hopefully
This commit is contained in:
parent
5a5f8c5c68
commit
f16189181b
263 changed files with 212 additions and 206 deletions
fabric-networking-v0
build.gradle
src/main
java/net/fabricmc/fabric
api
event/network
network
ClientSidePacketRegistry.javaPacketConsumer.javaPacketContext.javaPacketRegistry.javaServerSidePacketRegistry.java
server
impl
network
ClientSidePacketRegistryImpl.javaCustomPayloadC2SPacketAccessor.javaPacketRegistryImpl.javaPacketTypes.javaServerSidePacketRegistryImpl.java
server
mixin/network
resources
6
fabric-networking-v0/build.gradle
Normal file
6
fabric-networking-v0/build.gradle
Normal file
|
@ -0,0 +1,6 @@
|
|||
archivesBaseName = "fabric-networking-v0"
|
||||
version = getSubprojectVersion(project, "0.1.0")
|
||||
|
||||
dependencies {
|
||||
compile project(path: ':fabric-api-base', configuration: 'dev')
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.api.event.network;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Event for listening to packet type registrations and unregistrations
|
||||
* (also known as "minecraft:register" and "minecraft:unregister")
|
||||
* in the client -> server direction.
|
||||
*/
|
||||
public interface C2SPacketTypeCallback {
|
||||
static final Event<C2SPacketTypeCallback> REGISTERED = EventFactory.createArrayBacked(
|
||||
C2SPacketTypeCallback.class,
|
||||
(callbacks) -> (client, types) -> {
|
||||
for (C2SPacketTypeCallback callback : callbacks) {
|
||||
callback.accept(client, types);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
static final Event<C2SPacketTypeCallback> UNREGISTERED = EventFactory.createArrayBacked(
|
||||
C2SPacketTypeCallback.class,
|
||||
(callbacks) -> (client, types) -> {
|
||||
for (C2SPacketTypeCallback callback : callbacks) {
|
||||
callback.accept(client, types);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Accept a collection of types.
|
||||
*
|
||||
* @param client The player who is the source of the packet.
|
||||
* @param types The provided collection of types.
|
||||
*/
|
||||
void accept(PlayerEntity client, Collection<Identifier> types);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.api.event.network;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Event for listening to packet type registrations and unregistrations
|
||||
* (also known as "minecraft:register" and "minecraft:unregister")
|
||||
* in the server -> client direction.
|
||||
*/
|
||||
public interface S2CPacketTypeCallback {
|
||||
static final Event<S2CPacketTypeCallback> REGISTERED = EventFactory.createArrayBacked(
|
||||
S2CPacketTypeCallback.class,
|
||||
(callbacks) -> (types) -> {
|
||||
for (S2CPacketTypeCallback callback : callbacks) {
|
||||
callback.accept(types);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
static final Event<S2CPacketTypeCallback> UNREGISTERED = EventFactory.createArrayBacked(
|
||||
S2CPacketTypeCallback.class,
|
||||
(callbacks) -> (types) -> {
|
||||
for (S2CPacketTypeCallback callback : callbacks) {
|
||||
callback.accept(types);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Accept a collection of types.
|
||||
*
|
||||
* @param types The provided collection of types.
|
||||
*/
|
||||
void accept(Collection<Identifier> types);
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.api.network;
|
||||
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
import net.fabricmc.fabric.impl.network.ClientSidePacketRegistryImpl;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
|
||||
/**
|
||||
* The client-side packet registry.
|
||||
* <p>
|
||||
* It is used for:
|
||||
* <p>
|
||||
* - registering client-side packet receivers (server -> client packets)
|
||||
* - sending packets to the server (client -> server packets).
|
||||
*/
|
||||
public interface ClientSidePacketRegistry extends PacketRegistry {
|
||||
static final ClientSidePacketRegistry INSTANCE = new ClientSidePacketRegistryImpl();
|
||||
|
||||
/**
|
||||
* Check if the server declared the ability to receive a given packet ID
|
||||
* using the vanilla "register/unregister" protocol.
|
||||
*
|
||||
* @param id The packet identifier.
|
||||
* @return True if the server side declared a given packet identifier.
|
||||
*/
|
||||
boolean canServerReceive(Identifier id);
|
||||
|
||||
/**
|
||||
* Send a packet to the server.
|
||||
*
|
||||
* @param packet The packet to be sent.
|
||||
* @param completionListener Completion listener. Can be used to check for
|
||||
* the success or failure of sending a given packet, among others.
|
||||
*/
|
||||
void sendToServer(Packet<?> packet, GenericFutureListener<? extends Future<? super Void>> completionListener);
|
||||
|
||||
/**
|
||||
* Send an identifier/buffer-based packet to the server.
|
||||
*
|
||||
* @param id The packet identifier.
|
||||
* @param buf The packet byte buffer.
|
||||
* @param completionListener Completion listener. Can be used to check for
|
||||
* the success or failure of sending a given packet, among others.
|
||||
*/
|
||||
default void sendToServer(Identifier id, PacketByteBuf buf, GenericFutureListener<? extends Future<? super Void>> completionListener) {
|
||||
sendToServer(toPacket(id, buf), completionListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet to the server.
|
||||
*
|
||||
* @param packet The packet to be sent.
|
||||
*/
|
||||
default void sendToServer(Packet<?> packet) {
|
||||
sendToServer(packet, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an identifier/buffer-based packet to the server.
|
||||
*
|
||||
* @param id The packet identifier.
|
||||
* @param buf The packet byte buffer.
|
||||
*/
|
||||
default void sendToServer(Identifier id, PacketByteBuf buf) {
|
||||
sendToServer(id, buf, null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.api.network;
|
||||
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
|
||||
/**
|
||||
* Interface for receiving CustomPayload-based packets.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface PacketConsumer {
|
||||
/**
|
||||
* Receive a CustomPayload-based packet.
|
||||
* <p>
|
||||
* Please keep in mind that this CAN be called OUTSIDE of the main thread!
|
||||
* Most game operations are not thread-safe, so you should look into using
|
||||
* the thread task queue ({@link PacketContext#getTaskQueue()}) to split
|
||||
* the "reading" (which should, but does not have to, happen off-thread)
|
||||
* and "applying" (which, unless you know what you're doing, should happen
|
||||
* on the main thread).
|
||||
*
|
||||
* @param context The context (receiving player, side, etc.)
|
||||
* @param buffer The byte buffer containing the received packet data.
|
||||
*/
|
||||
void accept(PacketContext context, PacketByteBuf buffer);
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.api.network;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.ThreadExecutor;
|
||||
|
||||
/**
|
||||
* Interface defining a context used during packet processing. Allows access
|
||||
* to additional information, such as the source/target of the player, or
|
||||
* the correct task queue to enqueue synchronization-requiring code on.
|
||||
*/
|
||||
public interface PacketContext {
|
||||
/**
|
||||
* Get the environment associated with the packet.
|
||||
*
|
||||
* @return EnvType.CLIENT if processing packet on the client side,
|
||||
* EnvType.SERVER otherwise.
|
||||
*/
|
||||
EnvType getPacketEnvironment();
|
||||
|
||||
/**
|
||||
* Get the player associated with the packet.
|
||||
* <p>
|
||||
* On the client side, this always returns the client-side player instance.
|
||||
* On the server side, it returns the player belonging to the client this
|
||||
* packet was sent by.
|
||||
*
|
||||
* @return The player associated with the packet.
|
||||
*/
|
||||
PlayerEntity getPlayer();
|
||||
|
||||
/**
|
||||
* Get the task queue for a given side.
|
||||
* <p>
|
||||
* As Minecraft networking I/O is asynchronous, but a lot of its logic is
|
||||
* not thread-safe, it is recommended to do the following:
|
||||
* <p>
|
||||
* - read and parse the PacketByteBuf,
|
||||
* - run the packet response logic through the main thread task queue via
|
||||
* ThreadTaskQueue.execute(). The method will check if it's not already
|
||||
* on the main thread in order to avoid unnecessary delays, so don't
|
||||
* worry about that!
|
||||
*
|
||||
* @return The thread task queue.
|
||||
*/
|
||||
ThreadExecutor getTaskQueue();
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.api.network;
|
||||
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
|
||||
public interface PacketRegistry {
|
||||
/**
|
||||
* Turn a (identifier, byte buffer) pair into a "custom payload" packet
|
||||
* suitable for sending in the PacketRegistry's sending direction.
|
||||
*
|
||||
* @param id The identifier.
|
||||
* @param buf The byte buffer.
|
||||
* @return
|
||||
*/
|
||||
Packet<?> toPacket(Identifier id, PacketByteBuf buf);
|
||||
|
||||
/**
|
||||
* Register a packet.
|
||||
*
|
||||
* @param id The packet Identifier.
|
||||
* @param consumer The method used for handling the packet.
|
||||
*/
|
||||
void register(Identifier id, PacketConsumer consumer);
|
||||
|
||||
/**
|
||||
* Unregister a packet.
|
||||
*
|
||||
* @param id The packet Identifier.
|
||||
*/
|
||||
void unregister(Identifier id);
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.api.network;
|
||||
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
import net.fabricmc.fabric.api.server.PlayerStream;
|
||||
import net.fabricmc.fabric.impl.network.ServerSidePacketRegistryImpl;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
|
||||
/**
|
||||
* The server-side packet registry.
|
||||
* <p>
|
||||
* It is used for:
|
||||
* <p>
|
||||
* - registering server-side packet receivers (client -> server packets)
|
||||
* - sending packets to clients (server -> client packets).
|
||||
* <p>
|
||||
* For iterating over clients in a server, see {@link PlayerStream}.
|
||||
*/
|
||||
public interface ServerSidePacketRegistry extends PacketRegistry {
|
||||
static final ServerSidePacketRegistry INSTANCE = new ServerSidePacketRegistryImpl();
|
||||
|
||||
/**
|
||||
* Check if a given client declared the ability to receive a given packet ID
|
||||
* using the vanilla "register/unregister" protocol.
|
||||
*
|
||||
* @param id The packet identifier.
|
||||
* @return True if the client side declared a given packet identifier.
|
||||
*/
|
||||
boolean canPlayerReceive(PlayerEntity player, Identifier id);
|
||||
|
||||
/**
|
||||
* Send a packet to a given client.
|
||||
*
|
||||
* @param player The given client.
|
||||
* @param packet The packet to be sent.
|
||||
* @param completionListener Completion listener. Can be used to check for
|
||||
* the success or failure of sending a given packet, among others.
|
||||
*/
|
||||
void sendToPlayer(PlayerEntity player, Packet<?> packet, GenericFutureListener<? extends Future<? super Void>> completionListener);
|
||||
|
||||
/**
|
||||
* Send an identifier/buffer-based packet to a given client.
|
||||
*
|
||||
* @param player The given client.
|
||||
* @param id The packet identifier.
|
||||
* @param buf The packet byte buffer.
|
||||
* @param completionListener Completion listener. Can be used to check for
|
||||
* the success or failure of sending a given packet, among others.
|
||||
*/
|
||||
default void sendToPlayer(PlayerEntity player, Identifier id, PacketByteBuf buf, GenericFutureListener<? extends Future<? super Void>> completionListener) {
|
||||
sendToPlayer(player, toPacket(id, buf), completionListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet to a given client.
|
||||
*
|
||||
* @param player The given client.
|
||||
* @param packet The packet to be sent.
|
||||
*/
|
||||
default void sendToPlayer(PlayerEntity player, Packet<?> packet) {
|
||||
sendToPlayer(player, packet, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an identifier/buffer-based packet to a given client.
|
||||
*
|
||||
* @param player The given client.
|
||||
* @param id The packet identifier.
|
||||
* @param buf The packet byte buffer.
|
||||
*/
|
||||
default void sendToPlayer(PlayerEntity player, Identifier id, PacketByteBuf buf) {
|
||||
sendToPlayer(player, id, buf, null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.api.server;
|
||||
|
||||
import net.fabricmc.fabric.impl.server.EntityTrackerStorageAccessor;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerChunkManager;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.server.world.ThreadedAnvilChunkStorage;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.ChunkManager;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Helper streams for looking up players on a server.
|
||||
* <p>
|
||||
* In general, most of these methods will only function with a {@link ServerWorld} instance.
|
||||
*/
|
||||
public final class PlayerStream {
|
||||
private PlayerStream() {
|
||||
|
||||
}
|
||||
|
||||
public static Stream<ServerPlayerEntity> all(MinecraftServer server) {
|
||||
if (server.getPlayerManager() != null) {
|
||||
return server.getPlayerManager().getPlayerList().stream();
|
||||
} else {
|
||||
return Stream.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public static Stream<PlayerEntity> world(World world) {
|
||||
if (world instanceof ServerWorld) {
|
||||
// noinspection unchecked
|
||||
return ((Stream<PlayerEntity>) (Stream) ((ServerWorld) world).getPlayers().stream());
|
||||
} else {
|
||||
throw new RuntimeException("Only supported on ServerWorld!");
|
||||
}
|
||||
}
|
||||
|
||||
public static Stream<PlayerEntity> watching(World world, ChunkPos pos) {
|
||||
ChunkManager manager = world.getChunkManager();
|
||||
if (!(manager instanceof ServerChunkManager)) {
|
||||
throw new RuntimeException("Only supported on ServerWorld!");
|
||||
} else {
|
||||
//noinspection unchecked
|
||||
return ((Stream<PlayerEntity>) (Stream) ((ServerChunkManager) manager).threadedAnvilChunkStorage.getPlayersWatchingChunk(pos, false));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Warning: If the provided entity is a PlayerEntity themselves, it is not
|
||||
* guaranteed by the contract that said PlayerEntity is included in the
|
||||
* resulting stream.
|
||||
*/
|
||||
@SuppressWarnings("JavaDoc")
|
||||
public static Stream<PlayerEntity> watching(Entity entity) {
|
||||
ChunkManager manager = entity.getEntityWorld().getChunkManager();
|
||||
|
||||
if (manager instanceof ServerChunkManager) {
|
||||
ThreadedAnvilChunkStorage storage = ((ServerChunkManager) manager).threadedAnvilChunkStorage;
|
||||
if (storage instanceof EntityTrackerStorageAccessor) {
|
||||
//noinspection unchecked
|
||||
return ((Stream<PlayerEntity>) (Stream) ((EntityTrackerStorageAccessor) storage).fabric_getTrackingPlayers(entity));
|
||||
}
|
||||
}
|
||||
|
||||
// fallback
|
||||
return watching(entity.getEntityWorld(), new ChunkPos((int) (entity.x / 16.0D), (int) (entity.z / 16.0D)));
|
||||
}
|
||||
|
||||
public static Stream<PlayerEntity> watching(BlockEntity entity) {
|
||||
return watching(entity.getWorld(), entity.getPos());
|
||||
}
|
||||
|
||||
public static Stream<PlayerEntity> watching(World world, BlockPos pos) {
|
||||
return watching(world, new ChunkPos(pos));
|
||||
}
|
||||
|
||||
public static Stream<PlayerEntity> around(World world, Vec3d vector, double radius) {
|
||||
double radiusSq = radius * radius;
|
||||
return world(world).filter((p) -> p.squaredDistanceTo(vector) <= radiusSq);
|
||||
}
|
||||
|
||||
public static Stream<PlayerEntity> around(World world, BlockPos pos, double radius) {
|
||||
double radiusSq = radius * radius;
|
||||
return world(world).filter((p) -> p.squaredDistanceTo(pos.getX(), pos.getY(), pos.getZ()) <= radiusSq);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.impl.network;
|
||||
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
import net.fabricmc.fabric.api.event.network.S2CPacketTypeCallback;
|
||||
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
|
||||
import net.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
import net.minecraft.client.network.packet.CustomPayloadS2CPacket;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.server.network.packet.CustomPayloadC2SPacket;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class ClientSidePacketRegistryImpl extends PacketRegistryImpl implements ClientSidePacketRegistry {
|
||||
private final Collection<Identifier> serverPayloadIds = new HashSet<>();
|
||||
|
||||
public static void invalidateRegisteredIdList() {
|
||||
((ClientSidePacketRegistryImpl) ClientSidePacketRegistry.INSTANCE).serverPayloadIds.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canServerReceive(Identifier id) {
|
||||
return serverPayloadIds.contains(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToServer(Packet<?> packet, GenericFutureListener<? extends Future<? super Void>> completionListener) {
|
||||
ClientPlayNetworkHandler handler = MinecraftClient.getInstance().getNetworkHandler();
|
||||
if (handler != null) {
|
||||
if (completionListener == null) {
|
||||
// stay closer to the vanilla codepath
|
||||
handler.sendPacket(packet);
|
||||
} else {
|
||||
handler.getClientConnection().send(packet, completionListener);
|
||||
}
|
||||
} else {
|
||||
LOGGER.warn("Sending packet " + packet + " to server failed, not connected!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet<?> toPacket(Identifier id, PacketByteBuf buf) {
|
||||
return new CustomPayloadC2SPacket(id, buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRegister(Identifier id) {
|
||||
ClientPlayNetworkHandler handler = MinecraftClient.getInstance().getNetworkHandler();
|
||||
if (handler != null) {
|
||||
createRegisterTypePacket(PacketTypes.REGISTER, Collections.singleton(id)).ifPresent(handler::sendPacket);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onUnregister(Identifier id) {
|
||||
ClientPlayNetworkHandler handler = MinecraftClient.getInstance().getNetworkHandler();
|
||||
if (handler != null) {
|
||||
createRegisterTypePacket(PacketTypes.UNREGISTER, Collections.singleton(id)).ifPresent(handler::sendPacket);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Identifier> getIdCollectionFor(PacketContext context) {
|
||||
return serverPayloadIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReceivedRegisterPacket(PacketContext context, Collection<Identifier> ids) {
|
||||
S2CPacketTypeCallback.REGISTERED.invoker().accept(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReceivedUnregisterPacket(PacketContext context, Collection<Identifier> ids) {
|
||||
S2CPacketTypeCallback.UNREGISTERED.invoker().accept(ids);
|
||||
}
|
||||
|
||||
public final boolean accept(CustomPayloadS2CPacket packet, PacketContext context) {
|
||||
return accept(packet.getChannel(), context, packet.getData());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.impl.network;
|
||||
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
|
||||
/**
|
||||
* Helper interface containing getters for CustomPayloadC2SPacket
|
||||
* which were omitted from the compiled game.
|
||||
*/
|
||||
public interface CustomPayloadC2SPacketAccessor {
|
||||
Identifier getChannel();
|
||||
|
||||
PacketByteBuf getData();
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.impl.network;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.fabricmc.fabric.api.network.PacketConsumer;
|
||||
import net.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.fabricmc.fabric.api.network.PacketRegistry;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.InvalidIdentifierException;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
public abstract class PacketRegistryImpl implements PacketRegistry {
|
||||
protected static final Logger LOGGER = LogManager.getLogger();
|
||||
protected final Map<Identifier, PacketConsumer> consumerMap;
|
||||
|
||||
PacketRegistryImpl() {
|
||||
consumerMap = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
public static Optional<Packet<?>> createInitialRegisterPacket(PacketRegistry registry) {
|
||||
PacketRegistryImpl impl = (PacketRegistryImpl) registry;
|
||||
return impl.createRegisterTypePacket(PacketTypes.REGISTER, impl.consumerMap.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(Identifier id, PacketConsumer consumer) {
|
||||
boolean isNew = true;
|
||||
if (consumerMap.containsKey(id)) {
|
||||
LOGGER.warn("Registered duplicate packet " + id + "!");
|
||||
LOGGER.trace(new Throwable());
|
||||
isNew = false;
|
||||
}
|
||||
|
||||
consumerMap.put(id, consumer);
|
||||
if (isNew) {
|
||||
onRegister(id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister(Identifier id) {
|
||||
if (consumerMap.remove(id) != null) {
|
||||
onUnregister(id);
|
||||
} else {
|
||||
LOGGER.warn("Tried to unregister non-registered packet " + id + "!");
|
||||
LOGGER.trace(new Throwable());
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void onRegister(Identifier id);
|
||||
|
||||
protected abstract void onUnregister(Identifier id);
|
||||
|
||||
protected abstract Collection<Identifier> getIdCollectionFor(PacketContext context);
|
||||
|
||||
protected abstract void onReceivedRegisterPacket(PacketContext context, Collection<Identifier> ids);
|
||||
|
||||
protected abstract void onReceivedUnregisterPacket(PacketContext context, Collection<Identifier> ids);
|
||||
|
||||
protected Optional<Packet<?>> createRegisterTypePacket(Identifier id, Collection<Identifier> ids) {
|
||||
if (ids.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
|
||||
boolean first = true;
|
||||
for (Identifier a : ids) {
|
||||
if (!first) {
|
||||
buf.writeByte(0);
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
buf.writeBytes(a.toString().getBytes(StandardCharsets.US_ASCII));
|
||||
}
|
||||
return Optional.of(toPacket(id, buf));
|
||||
}
|
||||
|
||||
private boolean acceptRegisterType(Identifier id, PacketContext context, PacketByteBuf buf) {
|
||||
Collection<Identifier> ids = new HashSet<>();
|
||||
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
char c;
|
||||
|
||||
int oldIndex = buf.readerIndex();
|
||||
while (buf.readerIndex() < buf.writerIndex()) {
|
||||
c = (char) buf.readByte();
|
||||
if (c == 0) {
|
||||
String s = sb.toString();
|
||||
if (!s.isEmpty()) {
|
||||
try {
|
||||
ids.add(new Identifier(s));
|
||||
} catch (InvalidIdentifierException e) {
|
||||
LOGGER.warn("Received invalid identifier in " + id + ": " + s + " (" + e.getLocalizedMessage() + ")");
|
||||
LOGGER.trace(e);
|
||||
}
|
||||
}
|
||||
sb = new StringBuilder();
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
buf.readerIndex(oldIndex);
|
||||
|
||||
String s = sb.toString();
|
||||
if (!s.isEmpty()) {
|
||||
ids.add(new Identifier(s));
|
||||
}
|
||||
}
|
||||
|
||||
Collection<Identifier> target = getIdCollectionFor(context);
|
||||
if (id.equals(PacketTypes.UNREGISTER)) {
|
||||
target.removeAll(ids);
|
||||
onReceivedUnregisterPacket(context, ids);
|
||||
} else {
|
||||
target.addAll(ids);
|
||||
onReceivedRegisterPacket(context, ids);
|
||||
}
|
||||
return false; // continue execution for other mods
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for accepting packets used in Fabric mixins.
|
||||
*
|
||||
* @param id The packet Identifier received.
|
||||
* @param context The packet context provided.
|
||||
* @param buf The packet data buffer received.
|
||||
* @return Whether or not the packet was handled by this packet registry.
|
||||
*/
|
||||
public boolean accept(Identifier id, PacketContext context, PacketByteBuf buf) {
|
||||
if (id.equals(PacketTypes.REGISTER) || id.equals(PacketTypes.UNREGISTER)) {
|
||||
return acceptRegisterType(id, context, buf);
|
||||
}
|
||||
|
||||
PacketConsumer consumer = consumerMap.get(id);
|
||||
if (consumer != null) {
|
||||
try {
|
||||
consumer.accept(context, buf);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.warn("Failed to handle packet " + id + "!", t);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.impl.network;
|
||||
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public final class PacketTypes {
|
||||
public static final Identifier BRAND = new Identifier("minecraft:brand");
|
||||
public static final Identifier REGISTER = new Identifier("minecraft:register");
|
||||
public static final Identifier UNREGISTER = new Identifier("minecraft:unregister");
|
||||
|
||||
public static final Identifier OPEN_CONTAINER = new Identifier("fabric", "container/open");
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.impl.network;
|
||||
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
import net.fabricmc.fabric.api.event.network.C2SPacketTypeCallback;
|
||||
import net.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
|
||||
import net.minecraft.client.network.packet.CustomPayloadS2CPacket;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.network.packet.CustomPayloadC2SPacket;
|
||||
import net.minecraft.server.network.packet.LoginQueryResponseC2SPacket;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class ServerSidePacketRegistryImpl extends PacketRegistryImpl implements ServerSidePacketRegistry {
|
||||
private final WeakHashMap<PlayerEntity, Collection<Identifier>> playerPayloadIds = new WeakHashMap<>();
|
||||
private final Set<WeakReference<ServerPlayNetworkHandler>> handlers = new HashSet<>();
|
||||
|
||||
public void onQueryResponse(LoginQueryResponseC2SPacket packet) {
|
||||
}
|
||||
|
||||
public void addNetworkHandler(ServerPlayNetworkHandler handler) {
|
||||
handlers.add(new WeakReference<>(handler));
|
||||
}
|
||||
|
||||
protected void forEachHandler(Consumer<ServerPlayNetworkHandler> consumer) {
|
||||
Iterator<WeakReference<ServerPlayNetworkHandler>> it = handlers.iterator();
|
||||
while (it.hasNext()) {
|
||||
ServerPlayNetworkHandler server = it.next().get();
|
||||
if (server != null) {
|
||||
consumer.accept(server);
|
||||
} else {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayerReceive(PlayerEntity player, Identifier id) {
|
||||
Collection<Identifier> ids = playerPayloadIds.get(player);
|
||||
if (ids != null) {
|
||||
return ids.contains(id);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToPlayer(PlayerEntity player, Packet<?> packet, GenericFutureListener<? extends Future<? super Void>> completionListener) {
|
||||
if (!(player instanceof ServerPlayerEntity)) {
|
||||
throw new RuntimeException("Can only send to ServerPlayerEntities!");
|
||||
} else {
|
||||
((ServerPlayerEntity) player).networkHandler.sendPacket(packet, completionListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet<?> toPacket(Identifier id, PacketByteBuf buf) {
|
||||
return new CustomPayloadS2CPacket(id, buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRegister(Identifier id) {
|
||||
createRegisterTypePacket(PacketTypes.REGISTER, Collections.singleton(id))
|
||||
.ifPresent((packet) -> forEachHandler((n) -> n.sendPacket(packet)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onUnregister(Identifier id) {
|
||||
createRegisterTypePacket(PacketTypes.UNREGISTER, Collections.singleton(id))
|
||||
.ifPresent((packet) -> forEachHandler((n) -> n.sendPacket(packet)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Identifier> getIdCollectionFor(PacketContext context) {
|
||||
return playerPayloadIds.computeIfAbsent(context.getPlayer(), (p) -> new HashSet<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReceivedRegisterPacket(PacketContext context, Collection<Identifier> ids) {
|
||||
C2SPacketTypeCallback.REGISTERED.invoker().accept(context.getPlayer(), ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReceivedUnregisterPacket(PacketContext context, Collection<Identifier> ids) {
|
||||
C2SPacketTypeCallback.UNREGISTERED.invoker().accept(context.getPlayer(), ids);
|
||||
}
|
||||
|
||||
public final boolean accept(CustomPayloadC2SPacket packet, PacketContext context) {
|
||||
CustomPayloadC2SPacketAccessor accessor = ((CustomPayloadC2SPacketAccessor) packet);
|
||||
return accept(accessor.getChannel(), context, accessor.getData());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.impl.server;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface EntityTrackerStorageAccessor {
|
||||
Stream<ServerPlayerEntity> fabric_getTrackingPlayers(Entity entity);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.impl.server;
|
||||
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface EntityTrackerStreamAccessor {
|
||||
Stream<ServerPlayerEntity> fabric_getTrackingPlayers();
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.mixin.network;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
|
||||
import net.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.fabricmc.fabric.impl.network.ClientSidePacketRegistryImpl;
|
||||
import net.fabricmc.fabric.impl.network.PacketRegistryImpl;
|
||||
import net.fabricmc.fabric.impl.network.PacketTypes;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
import net.minecraft.client.network.packet.CustomPayloadS2CPacket;
|
||||
import net.minecraft.client.network.packet.GameJoinS2CPacket;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.util.ThreadExecutor;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Mixin(ClientPlayNetworkHandler.class)
|
||||
public abstract class MixinClientPlayNetworkHandler implements PacketContext {
|
||||
@Shadow
|
||||
private MinecraftClient client;
|
||||
|
||||
@Shadow
|
||||
public abstract void sendPacket(Packet<?> var1);
|
||||
|
||||
@Inject(at = @At("RETURN"), method = "onGameJoin")
|
||||
public void onGameJoin(GameJoinS2CPacket packet, CallbackInfo info) {
|
||||
Optional<Packet<?>> optionalPacket = PacketRegistryImpl.createInitialRegisterPacket(ClientSidePacketRegistry.INSTANCE);
|
||||
//noinspection OptionalIsPresent
|
||||
if (optionalPacket.isPresent()) {
|
||||
sendPacket(optionalPacket.get());
|
||||
}
|
||||
}
|
||||
|
||||
// Optional hook: it only removes a warning message.
|
||||
@Inject(method = "onCustomPayload", at = @At(value = "CONSTANT", args = "stringValue=Unknown custom packed identifier: {}"), cancellable = true, require = 0)
|
||||
public void onCustomPayloadNotFound(CustomPayloadS2CPacket packet, CallbackInfo info) {
|
||||
if (packet.getChannel().equals(PacketTypes.REGISTER) || packet.getChannel().equals(PacketTypes.UNREGISTER)) {
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "onCustomPayload", at = @At("HEAD"), cancellable = true)
|
||||
public void onCustomPayload(CustomPayloadS2CPacket packet, CallbackInfo info) {
|
||||
if (((ClientSidePacketRegistryImpl) ClientSidePacketRegistry.INSTANCE).accept(packet, this)) {
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnvType getPacketEnvironment() {
|
||||
return EnvType.CLIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerEntity getPlayer() {
|
||||
return client.player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThreadExecutor getTaskQueue() {
|
||||
return client;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.mixin.network;
|
||||
|
||||
import net.fabricmc.fabric.impl.network.CustomPayloadC2SPacketAccessor;
|
||||
import net.minecraft.server.network.packet.CustomPayloadC2SPacket;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
@Mixin(CustomPayloadC2SPacket.class)
|
||||
public class MixinCustomPayloadC2SPacket implements CustomPayloadC2SPacketAccessor {
|
||||
@Shadow
|
||||
private Identifier channel;
|
||||
@Shadow
|
||||
private PacketByteBuf data;
|
||||
|
||||
@Override
|
||||
public Identifier getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketByteBuf getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.mixin.network;
|
||||
|
||||
import net.fabricmc.fabric.impl.server.EntityTrackerStreamAccessor;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Mixin(targets = "net.minecraft.server.world.ThreadedAnvilChunkStorage$EntityTracker")
|
||||
public class MixinEntityTracker implements EntityTrackerStreamAccessor {
|
||||
@Shadow
|
||||
@Final
|
||||
private Set<ServerPlayerEntity> playersTracking;
|
||||
|
||||
@Override
|
||||
public Stream<ServerPlayerEntity> fabric_getTrackingPlayers() {
|
||||
return playersTracking.stream();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.mixin.network;
|
||||
|
||||
import net.fabricmc.fabric.impl.network.ClientSidePacketRegistryImpl;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.Screen;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(MinecraftClient.class)
|
||||
public class MixinMinecraftClient {
|
||||
@Inject(at = @At("RETURN"), method = "disconnect(Lnet/minecraft/client/gui/Screen;)V")
|
||||
public void disconnectAfter(Screen screen_1, CallbackInfo info) {
|
||||
ClientSidePacketRegistryImpl.invalidateRegisteredIdList();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.mixin.network;
|
||||
|
||||
import net.fabricmc.fabric.api.network.PacketRegistry;
|
||||
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
|
||||
import net.fabricmc.fabric.impl.network.PacketRegistryImpl;
|
||||
import net.fabricmc.fabric.impl.network.ServerSidePacketRegistryImpl;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.server.PlayerManager;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Mixin(priority = 500, value = PlayerManager.class)
|
||||
public abstract class MixinPlayerManager {
|
||||
@Inject(method = "onPlayerConnect", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/packet/DifficultyS2CPacket;<init>(Lnet/minecraft/world/Difficulty;Z)V"))
|
||||
public void onPlayerConnect(ClientConnection connection, ServerPlayerEntity player, CallbackInfo info) {
|
||||
Optional<Packet<?>> optionalPacket = PacketRegistryImpl.createInitialRegisterPacket(ServerSidePacketRegistry.INSTANCE);
|
||||
//noinspection OptionalIsPresent
|
||||
if (optionalPacket.isPresent()) {
|
||||
player.networkHandler.sendPacket(optionalPacket.get());
|
||||
((ServerSidePacketRegistryImpl) ServerSidePacketRegistry.INSTANCE).addNetworkHandler(player.networkHandler);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.mixin.network;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
|
||||
import net.fabricmc.fabric.impl.network.ServerSidePacketRegistryImpl;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.network.packet.CustomPayloadC2SPacket;
|
||||
import net.minecraft.util.ThreadExecutor;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ServerPlayNetworkHandler.class)
|
||||
public class MixinServerPlayNetworkHandler implements PacketContext {
|
||||
@Shadow
|
||||
private MinecraftServer server;
|
||||
@Shadow
|
||||
private ServerPlayerEntity player;
|
||||
|
||||
@Inject(method = "onCustomPayload", at = @At("HEAD"), cancellable = true)
|
||||
public void onCustomPayload(CustomPayloadC2SPacket packet, CallbackInfo info) {
|
||||
if (((ServerSidePacketRegistryImpl) ServerSidePacketRegistry.INSTANCE).accept(packet, this)) {
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnvType getPacketEnvironment() {
|
||||
return EnvType.SERVER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerEntity getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThreadExecutor getTaskQueue() {
|
||||
return server;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* 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 net.fabricmc.fabric.mixin.network;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import net.fabricmc.fabric.impl.server.EntityTrackerStorageAccessor;
|
||||
import net.fabricmc.fabric.impl.server.EntityTrackerStreamAccessor;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ThreadedAnvilChunkStorage;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Mixin(ThreadedAnvilChunkStorage.class)
|
||||
public class MixinThreadedAnvilChunkStorage implements EntityTrackerStorageAccessor {
|
||||
@Shadow
|
||||
@Final
|
||||
private Int2ObjectMap<EntityTrackerStreamAccessor> entityTrackers;
|
||||
|
||||
@Override
|
||||
public Stream<ServerPlayerEntity> fabric_getTrackingPlayers(Entity entity) {
|
||||
EntityTrackerStreamAccessor accessor = entityTrackers.get(entity.getEntityId());
|
||||
return accessor != null ? accessor.fabric_getTrackingPlayers() : Stream.empty();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"required": true,
|
||||
"package": "net.fabricmc.fabric.mixin.network",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
"MixinCustomPayloadC2SPacket",
|
||||
"MixinEntityTracker",
|
||||
"MixinPlayerManager",
|
||||
"MixinServerPlayNetworkHandler",
|
||||
"MixinThreadedAnvilChunkStorage"
|
||||
],
|
||||
"client": [
|
||||
"MixinClientPlayNetworkHandler",
|
||||
"MixinMinecraftClient"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
9
fabric-networking-v0/src/main/resources/fabric.mod.json
Normal file
9
fabric-networking-v0/src/main/resources/fabric.mod.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "fabric-networking-v0",
|
||||
"version": "${version}",
|
||||
"license": "Apache-2.0",
|
||||
"mixins": [
|
||||
"fabric-networking-v0.mixins.json"
|
||||
]
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue