Add a FML outbound target for all players tracking a point or entity in the world. Closes #3677 (#4631)

This commit is contained in:
Vincent Lee authored and LexManos committed 2018-04-01 01:42:55 -07:00
1 parent f5c0b894bf
commit 1d7c04daeb
5 files changed
+273

No files matched your search

@@ -25,6 +25,7 @@ import io.netty.channel.ChannelHandlerContext;
import java.util.EnumMap;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.NetHandlerPlayServer;
import net.minecraftforge.fml.common.FMLCommonHandler;
@@ -177,6 +178,33 @@ public class FMLEventChannel {
channels.get(Side.SERVER).writeAndFlush(pkt).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
}
/**
* Send to all tracking the point
* The {@code range} field of the {@link NetworkRegistry.TargetPoint} is ignored.
* @param pkt
* @param point
*/
public void sendToAllTracking(FMLProxyPacket pkt, NetworkRegistry.TargetPoint point)
{
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TRACKING_POINT);
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(point);
channels.get(Side.SERVER).writeAndFlush(pkt).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
}
/**
* Send to all tracking the entity
* This is not equivalent to {@link #sendToAllTracking(FMLProxyPacket, NetworkRegistry.TargetPoint)}
* because entities have different tracking distances based on their type.
* @param pkt
* @param entity
*/
public void sendToAllTracking(FMLProxyPacket pkt, Entity entity)
{
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TRACKING_ENTITY);
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(entity);
channels.get(Side.SERVER).writeAndFlush(pkt).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
}
/**
* Send to all in a dimension
* @param pkt
@@ -26,9 +26,17 @@ import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.util.AttributeKey;
import java.util.List;
import java.util.Set;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.NetworkManager;
import net.minecraft.server.management.PlayerChunkMap;
import net.minecraft.server.management.PlayerChunkMapEntry;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.network.NetworkRegistry.TargetPoint;
@@ -231,6 +239,79 @@ public class FMLOutboundHandler extends ChannelOutboundHandlerAdapter {
return builder.build();
}
},
/**
* The packet is sent to all players that are watching the Chunk containing the supplied {@link TargetPoint}.
* The {@code range} field of the {@link TargetPoint} is ignored.
*/
TRACKING_POINT(Sets.immutableEnumSet(Side.SERVER))
{
@Override
public void validateArgs(Object args)
{
if (!(args instanceof TargetPoint))
{
throw new RuntimeException("TRACKING_POINT expects a TargetPoint argument");
}
}
@Nullable
@Override
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
{
TargetPoint tp = (TargetPoint)args;
WorldServer world = DimensionManager.getWorld(tp.dimension);
if (world == null)
{
return ImmutableList.of();
}
PlayerChunkMapEntry entry = world.getPlayerChunkMap().getEntry(MathHelper.floor(tp.x) >> 4, MathHelper.floor(tp.z) >> 4);
if (entry == null)
{
return ImmutableList.of();
}
ImmutableList.Builder<NetworkDispatcher> builder = ImmutableList.builder();
for (EntityPlayerMP player : entry.getWatchingPlayers())
{
NetworkDispatcher dispatcher = player.connection.netManager.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
if (dispatcher != null) builder.add(dispatcher);
}
return builder.build();
}
},
/**
* The packet is sent to all players tracking the supplied {@link Entity}. This is different from {@link #TRACKING_POINT} because Entities
* can have different tracking distances depending on their type.
*/
TRACKING_ENTITY(Sets.immutableEnumSet(Side.SERVER))
{
@Override
public void validateArgs(Object args)
{
if (!(args instanceof Entity))
{
throw new RuntimeException("TRACKING_ENTITY expects an Entity argument");
}
}
@Nullable
@Override
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
{
Entity e = (Entity)args;
Set<? extends EntityPlayer> players = FMLCommonHandler.instance().getMinecraftServerInstance()
.getWorld(e.dimension).getEntityTracker().getTrackingPlayers(e);
ImmutableList.Builder<NetworkDispatcher> builder = ImmutableList.builder();
for (EntityPlayer player : players)
{
NetworkDispatcher dispatcher = ((EntityPlayerMP) player).connection.netManager.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
if (dispatcher != null) builder.add(dispatcher);
}
return builder.build();
}
},
/**
* The packet is sent to the server this client is currently conversing with.
* @author cpw
@@ -24,6 +24,7 @@ import io.netty.channel.ChannelFutureListener;
import java.lang.reflect.Method;
import java.util.EnumMap;
import net.minecraft.entity.Entity;
import net.minecraft.util.IThreadListener;
import io.netty.channel.ChannelHandler;
@@ -263,6 +264,37 @@ public class SimpleNetworkWrapper {
channels.get(Side.SERVER).writeAndFlush(message).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
}
/**
* Sends this message to everyone tracking a point.
* The {@link IMessageHandler} for this message type should be on the CLIENT side.
* The {@code range} field of the {@link TargetPoint} is ignored.
*
* @param message The message to send
* @param point The tracked {@link TargetPoint} around which to send
*/
public void sendToAllTracking(IMessage message, NetworkRegistry.TargetPoint point)
{
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TRACKING_POINT);
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(point);
channels.get(Side.SERVER).writeAndFlush(message).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
}
/**
* Sends this message to everyone tracking an entity.
* The {@link IMessageHandler} for this message type should be on the CLIENT side.
* This is not equivalent to {@link #sendToAllTracking(IMessage, TargetPoint)}
* because entities have different tracking distances based on their type.
*
* @param message The message to send
* @param entity The tracked entity around which to send
*/
public void sendToAllTracking(IMessage message, Entity entity)
{
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TRACKING_ENTITY);
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(entity);
channels.get(Side.SERVER).writeAndFlush(message).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
}
/**
* Send this message to everyone within the supplied dimension.
* The {@link IMessageHandler} for this message type should be on the CLIENT side.