package com.skcraft.playblock;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
import io.netty.buffer.Unpooled;
import java.io.IOException;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import org.apache.logging.log4j.Level;
import com.sk89q.forge.PayloadReceiver;
import com.sk89q.forge.TileEntityPayload;
import com.skcraft.playblock.network.PlayBlockPayload;
import com.skcraft.playblock.projector.TileEntityProjector;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.network.ByteBufUtils;
import cpw.mods.fml.common.network.FMLNetworkEvent;
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
/**
* Handles packets for PlayBlock.
*/
public class PacketHandler {
@SideOnly(Side.CLIENT)
@SubscribeEvent
public void onReceiveClient(FMLNetworkEvent.ClientCustomPacketEvent evt) {
World world = Minecraft.getMinecraft().theWorld;
EntityPlayer entityPlayer = Minecraft.getMinecraft().thePlayer;
try {
ByteBufInputStream in = new ByteBufInputStream(evt.packet.payload());
// Read the container
PlayBlockPayload container = new PlayBlockPayload();
container.read(in);
// Figure out what we are containing
switch (container.getType()) {
case TILE_ENTITY:
handleTilePayload(world, entityPlayer, in);
break;
case TILE_ENTITY_NBT:
handleNetworkedNBT(world, evt.packet.payload());
}
} catch (IOException e) {
PlayBlock.log(Level.WARN, "Failed to read packet data from " + entityPlayer.getDisplayName(), e);
}
}
@SubscribeEvent
public void onReceiveServer(FMLNetworkEvent.ServerCustomPacketEvent evt) {
EntityPlayer entityPlayer = ((NetHandlerPlayServer) evt.handler).playerEntity;
World world;
// Get the world
if (entityPlayer != null) {
world = entityPlayer.worldObj;
} else {
PlayBlock.log(Level.WARN, "Received an update packet from an invalid player!");
return;
}
try {
ByteBufInputStream in = new ByteBufInputStream(evt.packet.payload());
// Read the container
PlayBlockPayload container = new PlayBlockPayload();
container.read(in);
// Figure out what we are containing
switch (container.getType()) {
case TILE_ENTITY:
handleTilePayload(world, entityPlayer, in);
break;
case TILE_ENTITY_NBT:
handleNetworkedNBT(world, evt.packet.payload());
}
} catch (IOException e) {
PlayBlock.log(Level.WARN, "Failed to read packet data from " + entityPlayer.getDisplayName(), e);
}
}
public void handleTilePayload(World world, EntityPlayer player, ByteBufInputStream in) throws IOException {
TileEntityPayload tileContainer = new TileEntityPayload();
tileContainer.read(in);
// Get the tile and have it accept this payload
int x = tileContainer.getX();
int y = tileContainer.getY();
int z = tileContainer.getZ();
// We need to check if the chunk exists, otherwise an update packet
// could be used to overload the server by loading/generating chunks
if (world.blockExists(x, y, z)) {
TileEntity tile = world.getTileEntity(x, y, z);
if (tile instanceof PayloadReceiver) {
((PayloadReceiver) tile).readPayload(player, in);
}
} else {
PlayBlock.log(Level.WARN, "Got update packet for non-existent chunk/block from " + player.getDisplayName());
}
}
public void handleNetworkedNBT(World world, ByteBuf bytes) {
NBTTagCompound tag = ByteBufUtils.readTag(bytes);
int x = tag.getInteger("x");
int y = tag.getInteger("y");
int z = tag.getInteger("z");
if (world.blockExists(x, y, z)) {
TileEntity tile = world.getTileEntity(x, y, z);
if (tile instanceof TileEntityProjector) {
TileEntityProjector projector = (TileEntityProjector) tile;
projector.getBehaviors().readNetworkedNBT(tag);
}
} else {
PlayBlock.log(Level.WARN, "Got update packet for non-existent chunk/block!");
}
}
/**
* Send a payload to the server.
*
* @param payload
* the payload
*/
public static void sendToServer(PlayBlockPayload payload) {
ByteBufOutputStream out = new ByteBufOutputStream(Unpooled.buffer());
try {
payload.write(out);
out.flush();
} catch (IOException e) {
PlayBlock.log(Level.WARN, "Failed to send packet to the server");
return;
}
FMLProxyPacket packet = new FMLProxyPacket(out.buffer(), PlayBlock.CHANNEL_ID);
SharedRuntime.networkWrapper.sendToServer(packet);
}
public static void sendToClient(PlayBlockPayload payload, List<EntityPlayer> players) {
ByteBufOutputStream out = new ByteBufOutputStream(Unpooled.buffer());
try {
payload.write(out);
out.flush();
} catch (IOException e) {
PlayBlock.log(Level.WARN, "Failed to build packet to send to the client");
return;
}
FMLProxyPacket packet = new FMLProxyPacket(out.buffer(), PlayBlock.CHANNEL_ID);
if (players == null) {
SharedRuntime.networkWrapper.sendToAll(packet);
} else {
for (EntityPlayer player : players) {
if (player instanceof EntityPlayerMP) {
SharedRuntime.networkWrapper.sendTo(packet, (EntityPlayerMP) player);
}
}
}
}
}