001package net.minecraft.network;
002
003import cpw.mods.fml.common.network.FMLNetworkHandler;
004import cpw.mods.fml.relauncher.Side;
005import cpw.mods.fml.relauncher.SideOnly;
006import java.net.InetSocketAddress;
007import java.net.SocketAddress;
008import java.util.ArrayList;
009import java.util.Collections;
010import java.util.List;
011import java.util.Queue;
012import java.util.concurrent.ConcurrentLinkedQueue;
013
014import com.google.common.collect.Queues;
015
016import net.minecraft.logging.ILogAgent;
017import net.minecraft.network.packet.NetHandler;
018import net.minecraft.network.packet.Packet;
019
020public class MemoryConnection implements INetworkManager
021{
022    private static final SocketAddress mySocketAddress = new InetSocketAddress("127.0.0.1", 0);
023    private final Queue<Packet> readPacketCache = Queues.newConcurrentLinkedQueue();
024    private final ILogAgent field_98214_c;
025    private MemoryConnection pairedConnection;
026    private NetHandler myNetHandler;
027
028    /** set to true by {server,network}Shutdown */
029    private boolean shuttingDown = false;
030    private String shutdownReason = "";
031    private Object[] field_74439_g;
032    @SideOnly(Side.CLIENT)
033    private boolean gamePaused = false;
034
035    @SideOnly(Side.CLIENT)
036    public MemoryConnection(ILogAgent par1ILogAgent, NetHandler par2NetHandler)
037    {
038        this.myNetHandler = par2NetHandler;
039        this.field_98214_c = par1ILogAgent;
040    }
041
042    /**
043     * Sets the NetHandler for this NetworkManager. Server-only.
044     */
045    public void setNetHandler(NetHandler par1NetHandler)
046    {
047        this.myNetHandler = par1NetHandler;
048    }
049
050    /**
051     * Adds the packet to the correct send queue (chunk data packets go to a separate queue).
052     */
053    public void addToSendQueue(Packet par1Packet)
054    {
055        if (!this.shuttingDown)
056        {
057            this.pairedConnection.processOrCachePacket(par1Packet);
058        }
059    }
060
061    /**
062     * Wakes reader and writer threads
063     */
064    public void wakeThreads() {}
065
066    @SideOnly(Side.CLIENT)
067    public void closeConnections()
068    {
069        this.pairedConnection = null;
070        this.myNetHandler = null;
071    }
072
073    @SideOnly(Side.CLIENT)
074    public boolean isConnectionActive()
075    {
076        return !this.shuttingDown && this.pairedConnection != null;
077    }
078
079    /**
080     * Checks timeouts and processes all pending read packets.
081     */
082    public void processReadPackets()
083    {
084        int i = 2500;
085
086        while (i-- >= 0 && !this.readPacketCache.isEmpty())
087        {
088            Packet packet = readPacketCache.poll();
089            packet.processPacket(this.myNetHandler);
090        }
091
092        if (this.readPacketCache.size() > i)
093        {
094            this.field_98214_c.logWarning("Memory connection overburdened; after processing 2500 packets, we still have " + this.readPacketCache.size() + " to go!");
095        }
096
097        if (this.shuttingDown && this.readPacketCache.isEmpty())
098        {
099            this.myNetHandler.handleErrorMessage(this.shutdownReason, this.field_74439_g);
100            FMLNetworkHandler.onConnectionClosed(this, this.myNetHandler.getPlayer());
101        }
102    }
103
104    /**
105     * Return the InetSocketAddress of the remote endpoint
106     */
107    public SocketAddress getSocketAddress()
108    {
109        return mySocketAddress;
110    }
111
112    /**
113     * Shuts down the server. (Only actually used on the server)
114     */
115    public void serverShutdown()
116    {
117        this.shuttingDown = true;
118    }
119
120    /**
121     * Shuts down the network with the specified reason. Closes all streams and sockets, spawns NetworkMasterThread to
122     * stop reading and writing threads.
123     */
124    public void networkShutdown(String par1Str, Object ... par2ArrayOfObj)
125    {
126        this.shuttingDown = true;
127        this.shutdownReason = par1Str;
128        this.field_74439_g = par2ArrayOfObj;
129    }
130
131    /**
132     * returns 0 for memoryConnections
133     */
134    public int packetSize()
135    {
136        return 0;
137    }
138
139    @SideOnly(Side.CLIENT)
140    public void pairWith(MemoryConnection par1MemoryConnection)
141    {
142        this.pairedConnection = par1MemoryConnection;
143        par1MemoryConnection.pairedConnection = this;
144    }
145
146    @SideOnly(Side.CLIENT)
147    public boolean isGamePaused()
148    {
149        return this.gamePaused;
150    }
151
152    @SideOnly(Side.CLIENT)
153    public void setGamePaused(boolean par1)
154    {
155        this.gamePaused = par1;
156    }
157
158    @SideOnly(Side.CLIENT)
159    public MemoryConnection getPairedConnection()
160    {
161        return this.pairedConnection;
162    }
163
164    /**
165     * acts immiditally if isWritePacket, otherwise adds it to the readCache to be processed next tick
166     */
167    public void processOrCachePacket(Packet par1Packet)
168    {
169        if (par1Packet.canProcessAsync() && this.myNetHandler.canProcessPacketsAsync())
170        {
171            par1Packet.processPacket(this.myNetHandler);
172        }
173        else
174        {
175            this.readPacketCache.add(par1Packet);
176        }
177    }
178}