forked from FabricMC/fabric
Remade networking hooks
This commit is contained in:
parent
cc6ae9d3cf
commit
403d0c5a96
32 changed files with 1013 additions and 105 deletions
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
void accept(PlayerEntity client, Collection<Identifier> types);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
void accept(Collection<Identifier> types);
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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.
|
||||
*
|
||||
* It is used for:
|
||||
*
|
||||
* - 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);
|
||||
}
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* Registry for CustomPayload-based packet handling. You can use this
|
||||
* to register your own CustomPayload packet handlers.
|
||||
*/
|
||||
public class CustomPayloadPacketRegistry {
|
||||
public static final CustomPayloadPacketRegistry CLIENT = new CustomPayloadPacketRegistry();
|
||||
public static final CustomPayloadPacketRegistry SERVER = new CustomPayloadPacketRegistry();
|
||||
|
||||
protected final Map<Identifier, BiConsumer<PacketContext, PacketByteBuf>> consumerMap;
|
||||
|
||||
protected CustomPayloadPacketRegistry() {
|
||||
consumerMap = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a packet.
|
||||
*
|
||||
* @param id The packet Identifier.
|
||||
* @param consumer The method used for handling the packet.
|
||||
*/
|
||||
public void register(Identifier id, BiConsumer<PacketContext, PacketByteBuf> consumer) {
|
||||
if (consumerMap.containsKey(id)) {
|
||||
// TODO: log warning
|
||||
}
|
||||
|
||||
consumerMap.put(id, consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
BiConsumer<PacketContext, PacketByteBuf> consumer = consumerMap.get(id);
|
||||
if (consumer != null) {
|
||||
try {
|
||||
consumer.accept(context, buf);
|
||||
} catch (Throwable t) {
|
||||
// TODO: handle better
|
||||
t.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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.
|
||||
*
|
||||
* 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,48 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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 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.
|
||||
*
|
||||
* It is used for:
|
||||
*
|
||||
* - registering server-side packet receivers (client -> server packets)
|
||||
* - sending packets to clients (server -> client packets).
|
||||
*
|
||||
* 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,99 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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.EntityTrackerStreamAccessor;
|
||||
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.EntityTracker;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.ChunkPos;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Helper streams for looking up players on a server.
|
||||
*
|
||||
* 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) {
|
||||
return server.getPlayerManager().getPlayerList().stream();
|
||||
}
|
||||
|
||||
public static Stream<PlayerEntity> world(World world) {
|
||||
return world.players.stream();
|
||||
}
|
||||
|
||||
public static Stream<PlayerEntity> watching(World world, ChunkPos pos) {
|
||||
if (!(world instanceof ServerWorld)) {
|
||||
throw new RuntimeException("Only supported on ServerWorld!");
|
||||
} else {
|
||||
// noinspection unchecked
|
||||
return ((Stream<PlayerEntity>) (Stream) ((ServerWorld) world).getChunkManager().getPlayersWatchingChunk(pos, false, 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) {
|
||||
World world = entity.getEntityWorld();
|
||||
|
||||
if (world instanceof ServerWorld) {
|
||||
EntityTracker tracker = ((ServerWorld) world).getEntityTracker();
|
||||
if (tracker instanceof EntityTrackerStreamAccessor) {
|
||||
//noinspection unchecked
|
||||
return ((Stream<PlayerEntity>) (Stream) ((EntityTrackerStreamAccessor) tracker).fabric_getTrackingPlayers(entity));
|
||||
}
|
||||
}
|
||||
|
||||
// fallback
|
||||
return watching(world, 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.squaredDistanceToCenter(pos) <= radiusSq);
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.api.tags;
|
||||
package net.fabricmc.fabric.api.tag;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.tag.Tag;
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.api.tags;
|
||||
package net.fabricmc.fabric.api.tag;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.tag.Tag;
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.api.tags;
|
||||
package net.fabricmc.fabric.api.tag;
|
||||
|
||||
import net.minecraft.tag.Tag;
|
||||
import net.minecraft.util.Identifier;
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.api.tags;
|
||||
package net.fabricmc.fabric.api.tag;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.Item;
|
|
@ -17,15 +17,15 @@
|
|||
package net.fabricmc.fabric.impl;
|
||||
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
|
||||
import net.fabricmc.fabric.impl.client.gui.ScreenProviderRegistryImpl;
|
||||
import net.fabricmc.fabric.api.network.CustomPayloadPacketRegistry;
|
||||
import net.fabricmc.fabric.impl.registry.RegistrySyncManager;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
|
||||
public class FabricAPIClientInitializer implements ClientModInitializer {
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
CustomPayloadPacketRegistry.CLIENT.register(RegistrySyncManager.ID, (ctx, buf) -> {
|
||||
ClientSidePacketRegistry.INSTANCE.register(RegistrySyncManager.ID, (ctx, buf) -> {
|
||||
// if not hosting server, apply packet
|
||||
RegistrySyncManager.receivePacket(ctx, buf, !MinecraftClient.getInstance().isInSingleplayer());
|
||||
});
|
||||
|
|
|
@ -19,8 +19,9 @@ package net.fabricmc.fabric.impl.client.gui;
|
|||
import net.fabricmc.fabric.api.client.screen.ContainerScreenFactory;
|
||||
import net.fabricmc.fabric.api.client.screen.ScreenProviderRegistry;
|
||||
import net.fabricmc.fabric.api.container.ContainerFactory;
|
||||
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
|
||||
import net.fabricmc.fabric.impl.container.ContainerProviderImpl;
|
||||
import net.fabricmc.fabric.api.network.CustomPayloadPacketRegistry;
|
||||
import net.fabricmc.fabric.impl.network.PacketTypes;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.ContainerScreen;
|
||||
import net.minecraft.container.Container;
|
||||
|
@ -40,7 +41,6 @@ public class ScreenProviderRegistryImpl implements ScreenProviderRegistry {
|
|||
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
private static final Identifier OPEN_CONTAINER = new Identifier("fabric", "open_container");
|
||||
private static final Map<Identifier, ContainerFactory<ContainerScreen>> FACTORIES = new HashMap<>();
|
||||
|
||||
public void registerFactory(Identifier identifier, ContainerFactory<ContainerScreen> factory) {
|
||||
|
@ -63,7 +63,7 @@ public class ScreenProviderRegistryImpl implements ScreenProviderRegistry {
|
|||
}
|
||||
|
||||
public void init() {
|
||||
CustomPayloadPacketRegistry.CLIENT.register(OPEN_CONTAINER, (packetContext, packetByteBuf) -> {
|
||||
ClientSidePacketRegistry.INSTANCE.register(PacketTypes.OPEN_CONTAINER, (packetContext, packetByteBuf) -> {
|
||||
Identifier identifier = packetByteBuf.readIdentifier();
|
||||
int syncId = packetByteBuf.readUnsignedByte();
|
||||
MinecraftClient.getInstance().execute(() -> {
|
||||
|
|
|
@ -19,6 +19,7 @@ package net.fabricmc.fabric.impl.container;
|
|||
import io.netty.buffer.Unpooled;
|
||||
import net.fabricmc.fabric.api.container.ContainerFactory;
|
||||
import net.fabricmc.fabric.api.container.ContainerProviderRegistry;
|
||||
import net.fabricmc.fabric.impl.network.PacketTypes;
|
||||
import net.minecraft.client.network.packet.CustomPayloadClientPacket;
|
||||
import net.minecraft.container.Container;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
|
@ -41,7 +42,6 @@ public class ContainerProviderImpl implements ContainerProviderRegistry {
|
|||
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
private static final Identifier OPEN_CONTAINER = new Identifier("fabric", "open_container");
|
||||
private static final Map<Identifier, ContainerFactory<Container>> FACTORIES = new HashMap<>();
|
||||
|
||||
@Override
|
||||
|
@ -71,7 +71,7 @@ public class ContainerProviderImpl implements ContainerProviderRegistry {
|
|||
buf.writeByte(syncId);
|
||||
|
||||
writer.accept(buf);
|
||||
player.networkHandler.sendPacket(new CustomPayloadClientPacket(OPEN_CONTAINER, buf));
|
||||
player.networkHandler.sendPacket(new CustomPayloadClientPacket(PacketTypes.OPEN_CONTAINER, buf));
|
||||
|
||||
PacketByteBuf clonedBuf = new PacketByteBuf(buf.duplicate());
|
||||
clonedBuf.readIdentifier();
|
||||
|
@ -91,6 +91,7 @@ public class ContainerProviderImpl implements ContainerProviderRegistry {
|
|||
LOGGER.error("No container factory found for {}!", identifier.toString());
|
||||
return null;
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (C) factory.create(syncId, identifier, player, buf);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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.network.Packet;
|
||||
import net.minecraft.server.network.packet.CustomPayloadServerPacket;
|
||||
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().sendPacket(packet, completionListener);
|
||||
}
|
||||
} else {
|
||||
// TODO: log warning
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet<?> toPacket(Identifier id, PacketByteBuf buf) {
|
||||
return new CustomPayloadServerPacket(id, buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRegister(Identifier id) {
|
||||
ClientPlayNetworkHandler handler = MinecraftClient.getInstance().getNetworkHandler();
|
||||
if (handler != null) {
|
||||
handler.sendPacket(createRegisterTypePacket(PacketTypes.REGISTER, Collections.singleton(id)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onUnregister(Identifier id) {
|
||||
ClientPlayNetworkHandler handler = MinecraftClient.getInstance().getNetworkHandler();
|
||||
if (handler != null) {
|
||||
handler.sendPacket(createRegisterTypePacket(PacketTypes.UNREGISTER, Collections.singleton(id)));
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@ import net.minecraft.util.PacketByteBuf;
|
|||
* Helper interface containing getters for SPacketCustomPayload
|
||||
* which were omitted from the compiled game.
|
||||
*/
|
||||
public interface SPacketCustomPayloadAccessor {
|
||||
public interface CustomPayloadC2SPacketAccessor {
|
||||
Identifier getChannel();
|
||||
PacketByteBuf getData();
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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.fabricmc.fabric.api.network.ServerSidePacketRegistry;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public abstract class PacketRegistryImpl implements PacketRegistry {
|
||||
protected final Map<Identifier, PacketConsumer> consumerMap;
|
||||
|
||||
PacketRegistryImpl() {
|
||||
consumerMap = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
public static 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)) {
|
||||
// TODO: log warning
|
||||
isNew = false;
|
||||
}
|
||||
|
||||
consumerMap.put(id, consumer);
|
||||
if (isNew) {
|
||||
onRegister(id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister(Identifier id) {
|
||||
consumerMap.remove(id);
|
||||
onUnregister(id);
|
||||
}
|
||||
|
||||
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 Packet<?> createRegisterTypePacket(Identifier id, Collection<Identifier> ids) {
|
||||
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
|
||||
for (Identifier a : ids) {
|
||||
buf.writeString(a.toString());
|
||||
}
|
||||
return toPacket(id, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)) {
|
||||
Collection<Identifier> ids = new HashSet<>();
|
||||
while (buf.readerIndex() < buf.writerIndex() /* TODO: check correctness */) {
|
||||
Identifier newId = new Identifier(buf.readString(32767));
|
||||
ids.add(newId);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
PacketConsumer consumer = consumerMap.get(id);
|
||||
if (consumer != null) {
|
||||
try {
|
||||
consumer.accept(context, buf);
|
||||
} catch (Throwable t) {
|
||||
// TODO: handle better
|
||||
t.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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 {
|
||||
static final Identifier BRAND = new Identifier("minecraft:brand");
|
||||
static final Identifier REGISTER = new Identifier("minecraft:register");
|
||||
static final Identifier UNREGISTER = new Identifier("minecraft:unregister");
|
||||
|
||||
public static final Identifier OPEN_CONTAINER = new Identifier("fabric", "container/open");
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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.fabricmc.fabric.api.server.PlayerStream;
|
||||
import net.fabricmc.loader.FabricLoader;
|
||||
import net.minecraft.client.network.packet.CustomPayloadClientPacket;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public class ServerSidePacketRegistryImpl extends PacketRegistryImpl implements ServerSidePacketRegistry {
|
||||
private final WeakHashMap<PlayerEntity, Collection<Identifier>> playerPayloadIds = new WeakHashMap<>();
|
||||
|
||||
@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 CustomPayloadClientPacket(id, buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRegister(Identifier id) {
|
||||
MinecraftServer server = FabricLoader.INSTANCE.getEnvironmentHandler().getServerInstance();
|
||||
if (server != null) {
|
||||
Packet<?> packet = createRegisterTypePacket(PacketTypes.REGISTER, Collections.singleton(id));
|
||||
PlayerStream.all(server).forEach((p) -> sendToPlayer(p, packet));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onUnregister(Identifier id) {
|
||||
MinecraftServer server = FabricLoader.INSTANCE.getEnvironmentHandler().getServerInstance();
|
||||
if (server != null) {
|
||||
Packet<?> packet = createRegisterTypePacket(PacketTypes.UNREGISTER, Collections.singleton(id));
|
||||
PlayerStream.all(server).forEach((p) -> sendToPlayer(p, 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);
|
||||
}
|
||||
}
|
|
@ -21,8 +21,9 @@ import io.netty.buffer.Unpooled;
|
|||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import net.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.minecraft.client.network.packet.CustomPayloadClientPacket;
|
||||
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
import net.minecraft.util.registry.IdRegistry;
|
||||
|
@ -43,12 +44,11 @@ public final class RegistrySyncManager {
|
|||
|
||||
}
|
||||
|
||||
public static CustomPayloadClientPacket createPacket() {
|
||||
public static Packet<?> createPacket() {
|
||||
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
|
||||
buf.writeCompoundTag(toTag(true));
|
||||
|
||||
CustomPayloadClientPacket packet = new CustomPayloadClientPacket(ID, buf);
|
||||
return packet;
|
||||
return ServerSidePacketRegistry.INSTANCE.toPacket(ID, buf);
|
||||
}
|
||||
|
||||
public static void receivePacket(PacketContext context, PacketByteBuf buf, boolean accept) {
|
||||
|
@ -120,4 +120,13 @@ public final class RegistrySyncManager {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void unmap() throws RemapException {
|
||||
for (Identifier registryId : Registry.REGISTRIES.keys()) {
|
||||
ModifiableRegistry registry = Registry.REGISTRIES.get(registryId);
|
||||
if (registry instanceof RemappableRegistry) {
|
||||
((RemappableRegistry) registry).unmap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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 EntityTrackerEntryStreamAccessor {
|
||||
Stream<ServerPlayerEntity> fabric_getTrackingPlayers();
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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 EntityTrackerStreamAccessor {
|
||||
Stream<ServerPlayerEntity> fabric_getTrackingPlayers(Entity entity);
|
||||
}
|
|
@ -17,16 +17,25 @@
|
|||
package net.fabricmc.fabric.mixin.entity;
|
||||
|
||||
import net.fabricmc.fabric.api.entity.EntityTrackingRegistry;
|
||||
import net.fabricmc.fabric.impl.server.EntityTrackerEntryStreamAccessor;
|
||||
import net.fabricmc.fabric.impl.server.EntityTrackerStreamAccessor;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.server.network.EntityTracker;
|
||||
import net.minecraft.server.network.EntityTrackerEntry;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.IntHashMap;
|
||||
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.stream.Stream;
|
||||
|
||||
@Mixin(EntityTracker.class)
|
||||
public abstract class MixinEntityTracker {
|
||||
public abstract class MixinEntityTracker implements EntityTrackerStreamAccessor {
|
||||
@Shadow
|
||||
private IntHashMap<EntityTrackerEntry> trackedEntitiesById;
|
||||
@Shadow
|
||||
public abstract void add(Entity var1, int var2, int var3, boolean var4);
|
||||
|
||||
|
@ -40,4 +49,14 @@ public abstract class MixinEntityTracker {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<ServerPlayerEntity> fabric_getTrackingPlayers(Entity entity) {
|
||||
EntityTrackerEntry entry = trackedEntitiesById.get(entity.getEntityId());
|
||||
if (entry != null) {
|
||||
return ((EntityTrackerEntryStreamAccessor) entry).fabric_getTrackingPlayers();
|
||||
} else {
|
||||
return Stream.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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.entity;
|
||||
|
||||
import net.fabricmc.fabric.impl.server.EntityTrackerEntryStreamAccessor;
|
||||
import net.minecraft.server.network.EntityTrackerEntry;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Mixin(EntityTrackerEntry.class)
|
||||
public class MixinEntityTrackerEntry implements EntityTrackerEntryStreamAccessor {
|
||||
@Shadow
|
||||
private Set<ServerPlayerEntity> trackingPlayers;
|
||||
|
||||
@Override
|
||||
public Stream<ServerPlayerEntity> fabric_getTrackingPlayers() {
|
||||
return trackingPlayers.stream();
|
||||
}
|
||||
}
|
|
@ -16,13 +16,23 @@
|
|||
|
||||
package net.fabricmc.fabric.mixin.networking;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.fabric.api.network.CustomPayloadPacketRegistry;
|
||||
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.minecraft.class_2901;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.Screen;
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
import net.minecraft.client.network.packet.CustomPayloadClientPacket;
|
||||
import net.minecraft.client.network.packet.GameJoinClientPacket;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.ThreadTaskQueue;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
@ -31,13 +41,21 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ClientPlayNetworkHandler.class)
|
||||
public class MixinClientPlayNetworkHandler implements PacketContext {
|
||||
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(GameJoinClientPacket packet, CallbackInfo info) {
|
||||
sendPacket(PacketRegistryImpl.createInitialRegisterPacket(ClientSidePacketRegistry.INSTANCE));
|
||||
}
|
||||
|
||||
@Inject(method = "onCustomPayload", at = @At("HEAD"), cancellable = true)
|
||||
public void onCustomPayload(CustomPayloadClientPacket packet, CallbackInfo info) {
|
||||
if (CustomPayloadPacketRegistry.CLIENT.accept(packet.getChannel(), this, packet.getData())) {
|
||||
if (((ClientSidePacketRegistryImpl) ClientSidePacketRegistry.INSTANCE).accept(packet.getChannel(), this, packet.getData())) {
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package net.fabricmc.fabric.mixin.networking;
|
||||
|
||||
import net.fabricmc.fabric.impl.network.SPacketCustomPayloadAccessor;
|
||||
import net.fabricmc.fabric.impl.network.CustomPayloadC2SPacketAccessor;
|
||||
import net.minecraft.server.network.packet.CustomPayloadServerPacket;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
|
@ -24,7 +24,7 @@ import org.spongepowered.asm.mixin.Mixin;
|
|||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
@Mixin(CustomPayloadServerPacket.class)
|
||||
public class MixinSPacketCustomPayload implements SPacketCustomPayloadAccessor {
|
||||
public class MixinCustomPayloadC2SPacket implements CustomPayloadC2SPacketAccessor {
|
||||
@Shadow
|
||||
private Identifier channel;
|
||||
@Shadow
|
|
@ -17,9 +17,10 @@
|
|||
package net.fabricmc.fabric.mixin.networking;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.fabric.api.network.CustomPayloadPacketRegistry;
|
||||
import net.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.fabricmc.fabric.impl.network.SPacketCustomPayloadAccessor;
|
||||
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
|
||||
import net.fabricmc.fabric.impl.network.CustomPayloadC2SPacketAccessor;
|
||||
import net.fabricmc.fabric.impl.network.ServerSidePacketRegistryImpl;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||
|
@ -41,9 +42,9 @@ public class MixinServerPlayNetworkHandler implements PacketContext {
|
|||
|
||||
@Inject(method = "onCustomPayload", at = @At("HEAD"), cancellable = true)
|
||||
public void onCustomPayload(CustomPayloadServerPacket packet, CallbackInfo info) {
|
||||
SPacketCustomPayloadAccessor accessor = ((SPacketCustomPayloadAccessor) packet);
|
||||
CustomPayloadC2SPacketAccessor accessor = ((CustomPayloadC2SPacketAccessor) packet);
|
||||
|
||||
if (CustomPayloadPacketRegistry.SERVER.accept(accessor.getChannel(), this, accessor.getData())) {
|
||||
if (((ServerSidePacketRegistryImpl) ServerSidePacketRegistry.INSTANCE).accept(accessor.getChannel(), this, accessor.getData())) {
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
package net.fabricmc.fabric.mixin.registry;
|
||||
|
||||
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
|
||||
import net.fabricmc.fabric.impl.network.PacketRegistryImpl;
|
||||
import net.fabricmc.fabric.impl.network.ServerSidePacketRegistryImpl;
|
||||
import net.fabricmc.fabric.impl.registry.RegistrySyncManager;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import net.minecraft.network.Packet;
|
||||
|
@ -36,6 +39,8 @@ public abstract class MixinServerPlayNetworkHandler {
|
|||
@Inject(method = "<init>", at = @At("RETURN"))
|
||||
public void init(MinecraftServer server, ClientConnection connection, ServerPlayerEntity player, CallbackInfo info) {
|
||||
// TODO: If integrated and local, don't send the packet (it's ignored)
|
||||
// TODO: Refactor out into network + move registry hook to event
|
||||
sendPacket(PacketRegistryImpl.createInitialRegisterPacket(ServerSidePacketRegistry.INSTANCE));
|
||||
sendPacket(RegistrySyncManager.createPacket());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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.registry.client;
|
||||
|
||||
import net.fabricmc.fabric.impl.network.ClientSidePacketRegistryImpl;
|
||||
import net.fabricmc.fabric.impl.registry.RegistrySyncManager;
|
||||
import net.fabricmc.fabric.impl.registry.RemapException;
|
||||
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 {
|
||||
@Shadow
|
||||
private static Logger LOGGER;
|
||||
|
||||
// Unmap the registry before loading a new SP/MP setup.
|
||||
@Inject(at = @At("RETURN"), method = "method_18096")
|
||||
public void method_18096(Screen screen_1, CallbackInfo info) {
|
||||
ClientSidePacketRegistryImpl.invalidateRegisteredIdList();
|
||||
|
||||
try {
|
||||
RegistrySyncManager.unmap();
|
||||
} catch (RemapException e) {
|
||||
LOGGER.warn("Failed to unmap Fabric registries!", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@
|
|||
"registry.client.MixinBlockColorMap",
|
||||
"registry.client.MixinItemColorMap",
|
||||
"registry.client.MixinItemModelMap",
|
||||
"registry.client.MixinMinecraftClient",
|
||||
"registry.client.MixinParticleManager",
|
||||
"resources.MixinKeyedResourceReloadListener$Client",
|
||||
"resources.MixinMinecraftGame"
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"commands.MixinServerCommandManager",
|
||||
"container.MixinServerPlayerEntity",
|
||||
"entity.MixinEntityTracker",
|
||||
"entity.MixinEntityTrackerEntry",
|
||||
"events.objectbuilder.MixinBlock",
|
||||
"events.objectbuilder.MixinItem",
|
||||
"events.playerinteraction.MixinServerPlayNetworkHandler",
|
||||
|
@ -20,8 +21,8 @@
|
|||
"item.MixinAbstractFurnaceBlockEntity",
|
||||
"itemgroup.MixinItemGroup",
|
||||
"misc.MixinCrashReport",
|
||||
"networking.MixinCustomPayloadC2SPacket",
|
||||
"networking.MixinServerPlayNetworkHandler",
|
||||
"networking.MixinSPacketCustomPayload",
|
||||
"registry.MixinBootstrap",
|
||||
"registry.MixinIdList",
|
||||
"registry.MixinIdRegistry",
|
||||
|
|
Loading…
Reference in a new issue