buildcraft.core.lib.network.base.PacketHandler.java Source code

Java tutorial

Introduction

Here is the source code for buildcraft.core.lib.network.base.PacketHandler.java

Source

/** Copyright (c) 2011-2015, SpaceToad and the BuildCraft Team http://www.mod-buildcraft.com
 *
 * 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.core.lib.network.base;

import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Queues;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import net.minecraft.world.World;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.relauncher.Side;

import buildcraft.api.core.BCLog;
import buildcraft.core.TickHandlerCore;

/* Implementation note: while this does implement Sharable this isn't technically sharable because it has a packet map.
 * However its fine provided that you only pass a single instance of this to forge, as this handles the double sides by
 * itself. */
@Sharable
public final class PacketHandler extends SimpleChannelInboundHandler<Packet> {
    /** A massive negative number. Close to {@link Integer#MIN_VALUE} to reduce the likelyhood of this being a valid dim
     * ID in another mod. */
    public static final int INVALID_DIM_ID = Integer.MIN_VALUE + 10;

    private static volatile int livePacketCount = 0;
    private static int lastSomethingPackets = 0;
    private static long lastDispMs = System.currentTimeMillis();
    private final Map<Side, Map<Integer, Queue<Packet>>> packetMap;

    public PacketHandler() {
        Map<Side, Map<Integer, Queue<Packet>>> map = Maps.newHashMap();
        for (Side side : Side.values()) {
            Map<Integer, Queue<Packet>> mp = new ConcurrentHashMap<>();
            map.put(side, mp);
        }
        packetMap = ImmutableMap.copyOf(map);
        TickHandlerCore.addPacketHandler(this);
    }

    public static int packetQueueSize() {
        long now = System.currentTimeMillis();
        if (now - lastDispMs > 800) {
            lastDispMs = now;
            lastSomethingPackets = livePacketCount;
            livePacketCount = 0;
        }
        return lastSomethingPackets;
    }

    public void tick(World world) {
        Packet packet = null;
        Side side = world.isRemote ? Side.CLIENT : Side.SERVER;
        int dimId = world.provider.getDimension();
        Queue<Packet> queue = getQueue(side, dimId);
        // BCLog.logger.info("Ticking world " + dimId + " at " + side + " with " + queue.size() + " packets");
        while ((packet = queue.poll()) != null) {
            // Pass the packets player back to it (It was not accessible to subtypes)
            packet.applyData(world, packet.player);
        }
    }

    public void unload(World world) {
        Side side = world.isRemote ? Side.CLIENT : Side.SERVER;
        int dimId = world.provider.getDimension();
        Queue<Packet> queue = getQueue(side, dimId);
        queue.clear();
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Packet packet) {
        Side side = ctx.channel().attr(NetworkRegistry.CHANNEL_SOURCE).get();
        if (packet.dimensionId == INVALID_DIM_ID)
            BCLog.logger.warn("Found a packet with an invalid dimension id! [read]");
        if (!packet.hasDoneByteStuff)
            throw new IllegalArgumentException("Tried to use a packet that hasn't read yet! THIS IS VERY BAD!");
        if (side != null) {
            getQueue(side, packet.dimensionId).add(packet);
            livePacketCount++;
        } else {
            BCLog.logger.error("Found a message without a side! THIS IS VERY BAD, MAJOR ERRORS COULD OCCOUR!");
        }
    }

    private Queue<Packet> getQueue(Side side, int dimId) {
        Map<Integer, Queue<Packet>> map = packetMap.get(side);
        if (!map.containsKey(dimId)) {
            map.put(dimId, Queues.<Packet>newConcurrentLinkedQueue());
        }
        return map.get(dimId);
    }
}