buildcraft/common/buildcraft/BuildCraftMod.java
2017-11-10 19:30:36 +01:00

201 lines
5.8 KiB
Java

/**
* Copyright (c) 2011-2017, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
* <p/>
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft;
import java.util.EnumMap;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.NetworkManager;
import net.minecraft.server.MinecraftServer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import cpw.mods.fml.common.network.FMLEmbeddedChannel;
import cpw.mods.fml.common.network.FMLOutboundHandler;
import cpw.mods.fml.common.network.FMLOutboundHandler.OutboundTarget;
import cpw.mods.fml.relauncher.Side;
import buildcraft.api.core.BCLog;
import buildcraft.core.DefaultProps;
import buildcraft.core.lib.network.Packet;
import buildcraft.core.lib.utils.ThreadSafeUtils;
public class BuildCraftMod {
private static PacketSender sender = new PacketSender();
private static Thread senderThread = new Thread(sender);
public EnumMap<Side, FMLEmbeddedChannel> channels;
abstract static class SendRequest {
final Packet packet;
final BuildCraftMod source;
SendRequest(BuildCraftMod source, Packet packet) {
this.packet = packet;
this.source = source;
}
abstract boolean isValid(EntityPlayer player);
}
class PlayerSendRequest extends SendRequest {
EntityPlayer player;
PlayerSendRequest(BuildCraftMod source, Packet packet, EntityPlayer player) {
super(source, packet);
this.player = player;
}
boolean isValid(EntityPlayer player) {
return this.player.equals(player);
}
}
class EntitySendRequest extends SendRequest {
Entity entity;
EntitySendRequest(BuildCraftMod source, Packet packet, Entity entity) {
super(source, packet);
this.entity = entity;
}
boolean isValid(EntityPlayer player) {
if (player.worldObj.equals(entity.worldObj)) {
if (player.worldObj instanceof WorldServer) {
return ((WorldServer) player.worldObj).getEntityTracker().getTrackingPlayers(entity).contains(player);
} else {
return true;
}
} else {
return false;
}
}
}
class WorldSendRequest extends SendRequest {
final int dimensionId;
WorldSendRequest(BuildCraftMod source, Packet packet, int dimensionId) {
super(source, packet);
this.dimensionId = dimensionId;
}
boolean isValid(EntityPlayer player) {
return player.worldObj.provider.dimensionId == dimensionId;
}
}
class LocationSendRequest extends SendRequest {
final int dimensionId;
final int x, y, z, md;
LocationSendRequest(BuildCraftMod source, Packet packet, int dimensionId, int x, int y, int z, int md) {
super(source, packet);
this.dimensionId = dimensionId;
this.x = x;
this.y = y;
this.z = z;
this.md = md * md;
}
boolean isValid(EntityPlayer player) {
return dimensionId == player.worldObj.provider.dimensionId
&& player.getDistanceSq(x, y, z) <= md;
}
}
static class PacketSender implements Runnable {
private Queue<SendRequest> packets = new ConcurrentLinkedQueue<SendRequest>();
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (Exception e) {
}
while (!packets.isEmpty()) {
try {
SendRequest r = packets.remove();
net.minecraft.network.Packet p = ThreadSafeUtils.generatePacketFrom(r.packet, r.source.channels.get(Side.SERVER));
List<EntityPlayerMP> playerList = MinecraftServer.getServer().getConfigurationManager().playerEntityList;
for (EntityPlayerMP player : playerList.toArray(new EntityPlayerMP[playerList.size()])) {
if (r.isValid(player)) {
NetHandlerPlayServer handler = player.playerNetServerHandler;
if (handler == null) {
continue;
}
NetworkManager manager = handler.netManager;
if (manager == null || !manager.isChannelOpen()) {
continue;
}
manager.scheduleOutboundPacket(p);
}
}
} catch (Exception e) {
BCLog.logger.error("The BuildCraft packet sender thread raised an exception! Please report to GitHub.");
e.printStackTrace();
}
}
}
}
public boolean add(SendRequest r) {
return packets.offer(r);
}
}
static {
senderThread.start();
}
public void sendToPlayers(Packet packet, World world, int x, int y, int z, int maxDistance) {
sender.add(new LocationSendRequest(this, packet, world.provider.dimensionId, x, y, z, maxDistance));
}
public void sendToPlayersNear(Packet packet, TileEntity tileEntity, int maxDistance) {
sender.add(new LocationSendRequest(this, packet, tileEntity.getWorldObj().provider.dimensionId, tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord, maxDistance));
}
public void sendToPlayersNear(Packet packet, TileEntity tileEntity) {
sendToPlayersNear(packet, tileEntity, DefaultProps.NETWORK_UPDATE_RANGE);
}
public void sendToWorld(Packet packet, World world) {
sender.add(new WorldSendRequest(this, packet, world.provider.dimensionId));
}
public void sendToEntity(Packet packet, Entity entity) {
sender.add(new EntitySendRequest(this, packet, entity));
}
public void sendToPlayer(EntityPlayer entityplayer, Packet packet) {
sender.add(new PlayerSendRequest(this, packet, entityplayer));
}
public void sendToServer(Packet packet) {
try {
channels.get(Side.CLIENT).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(OutboundTarget.TOSERVER);
channels.get(Side.CLIENT).writeOutbound(packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}