package org.nikki.rsproto.factory; import java.net.InetSocketAddress; import java.util.HashMap; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.jboss.netty.bootstrap.ClientBootstrap; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; import org.nikki.rsproto.model.RSClient; import org.nikki.rsproto.net.PacketBuilder; import org.nikki.rsproto.net.RS2PipelineFactory; import org.nikki.rsproto.protocol.RSProtocol; /** * A factory which will create new RS Clients * * @author Nikki * */ public class RSClientFactory { /** * A map of created factories */ private static HashMap, RSClientFactory> factories = new HashMap, RSClientFactory>(); /** * The protocol of this factory */ private RSProtocol protocol; /** * The client bootstrap */ private ClientBootstrap clientBootstrap; /** * A place to store the sockets created from this factory */ private HashMap activeClients = new HashMap(); /** * Create a new factory * @param protocol * The protocol */ private RSClientFactory(RSProtocol protocol) { this.protocol = protocol; clientBootstrap = new ClientBootstrap( new NioClientSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); clientBootstrap.setPipelineFactory(new RS2PipelineFactory(this, protocol)); Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() { public void run() { tick(); } }, 0, 1000, TimeUnit.MILLISECONDS); } /** * Create a new socket from this factory * @return * The new socket */ public RSClient newClient(String host, int port) { final RSClient client = new RSClient(protocol); ChannelFuture future = clientBootstrap.connect(new InetSocketAddress(host, port)); future.awaitUninterruptibly(); if(future.isSuccess()) { Channel channel = future.getChannel(); activeClients.put(channel, client); client.setChannel(channel); return client; } return null; } /** * Keep the clients alive */ public void tick() { synchronized(activeClients) { for(RSClient client : activeClients.values()) { client.write(new PacketBuilder(0).toPacket()); } } } /** * Get a pre-existing factory or a new socket factory * @param protocol * The protocol * @return * The factory * @throws IllegalAccessException * @throws InstantiationException */ public static RSClientFactory factory(Class protocol) throws Exception { if(factories.containsKey(protocol)) { return factories.get(protocol); } RSProtocol instance = protocol.newInstance(); //Load the cache instance.loadCache(); //Load data instance.parseData(); //Load the packets instance.loadPackets(); //Create a new factory RSClientFactory factory = new RSClientFactory(instance); factories.put(protocol, factory); return factory; } /** * Get the client attached to a channel * @param channel * The channel * @return * The client, if any */ public RSClient getClient(Channel channel) { return activeClients.get(channel); } /** * Remote the client attached to the specified channel * @param channel * The channel */ public void removeClient(Channel channel) { activeClients.remove(channel); } }