Преглед изворни кода

MMO: code reformat to match gs tralala

JIV пре 14 година
родитељ
комит
ec6c5e08c3

+ 52 - 27
MMOCore/.settings/org.eclipse.jdt.core.prefs

@@ -1,4 +1,4 @@
-#Sun Dec 10 22:47:16 BRST 2006
+#Sat Sep 11 14:21:37 CEST 2010
 eclipse.preferences.version=1
 org.eclipse.jdt.core.codeComplete.argumentPrefixes=
 org.eclipse.jdt.core.codeComplete.argumentSuffixes=
@@ -9,38 +9,41 @@ org.eclipse.jdt.core.codeComplete.localSuffixes=
 org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
 org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=0
 org.eclipse.jdt.core.formatter.alignment_for_assignment=0
-org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
-org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=0
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=0
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0
 org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
-org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=0
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
 org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
-org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0
 org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
 org.eclipse.jdt.core.formatter.blank_lines_after_package=1
-org.eclipse.jdt.core.formatter.blank_lines_before_field=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
 org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
 org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
 org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
 org.eclipse.jdt.core.formatter.blank_lines_before_method=1
 org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
 org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
 org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
 org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=next_line
-org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=next_line
 org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
 org.eclipse.jdt.core.formatter.brace_position_for_block=next_line
 org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=next_line
@@ -51,33 +54,47 @@ org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line
 org.eclipse.jdt.core.formatter.brace_position_for_switch=next_line
 org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_line
 org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=false
 org.eclipse.jdt.core.formatter.comment.format_comments=true
 org.eclipse.jdt.core.formatter.comment.format_header=false
 org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=false
+org.eclipse.jdt.core.formatter.comment.format_line_comments=false
 org.eclipse.jdt.core.formatter.comment.format_source_code=true
 org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
 org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
 org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
-org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
 org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
 org.eclipse.jdt.core.formatter.compact_else_if=true
 org.eclipse.jdt.core.formatter.continuation_indentation=2
 org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
 org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
 org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
 org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
 org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
 org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
 org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
-org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_empty_lines=true
 org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
 org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
 org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
 org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
 org.eclipse.jdt.core.formatter.indentation.size=4
 org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
 org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert
 org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
 org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
 org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
@@ -228,6 +245,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=inser
 org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
 org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
 org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
 org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
 org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
@@ -243,14 +261,21 @@ org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_
 org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
 org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
 org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
 org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
-org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=true
 org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
 org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
-org.eclipse.jdt.core.formatter.lineSplit=80
+org.eclipse.jdt.core.formatter.lineSplit=300
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
 org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
 org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
-org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
-org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false
+org.eclipse.jdt.core.formatter.tabulation.char=tab
 org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
 org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true

+ 3 - 3
MMOCore/.settings/org.eclipse.jdt.ui.prefs

@@ -1,7 +1,7 @@
-#Sat May 05 02:12:50 BRT 2007
+#Sat Sep 11 14:21:37 CEST 2010
 eclipse.preferences.version=1
-formatter_profile=_KenM
-formatter_settings_version=10
+formatter_profile=_tralala
+formatter_settings_version=11
 org.eclipse.jdt.ui.exception.name=e
 org.eclipse.jdt.ui.gettersetter.use.is=true
 org.eclipse.jdt.ui.javadoc=false

+ 8 - 8
MMOCore/src/org/mmocore/network/AbstractPacket.java

@@ -25,12 +25,12 @@ import java.nio.ByteBuffer;
  */
 public abstract class AbstractPacket<T extends MMOClient<?>>
 {
-    protected ByteBuffer _buf;
-
-    T _client;
-
-    public final T getClient()
-    {
-        return _client;
-    }
+	protected ByteBuffer _buf;
+	
+	T _client;
+	
+	public final T getClient()
+	{
+		return _client;
+	}
 }

+ 1 - 1
MMOCore/src/org/mmocore/network/IAcceptFilter.java

@@ -25,5 +25,5 @@ import java.nio.channels.SocketChannel;
  */
 public interface IAcceptFilter
 {
-    public boolean accept(SocketChannel sc);
+	public boolean accept(SocketChannel sc);
 }

+ 1 - 1
MMOCore/src/org/mmocore/network/IClientFactory.java

@@ -23,5 +23,5 @@ package org.mmocore.network;
  */
 public interface IClientFactory<T extends MMOClient<?>>
 {
-    public T create(final MMOConnection<T> con);
+	public T create(final MMOConnection<T> con);
 }

+ 1 - 1
MMOCore/src/org/mmocore/network/IMMOExecutor.java

@@ -23,5 +23,5 @@ package org.mmocore.network;
  */
 public interface IMMOExecutor<T extends MMOClient<?>>
 {
-    public void execute(ReceivablePacket<T> packet);
+	public void execute(ReceivablePacket<T> packet);
 }

+ 1 - 1
MMOCore/src/org/mmocore/network/IPacketHandler.java

@@ -25,5 +25,5 @@ import java.nio.ByteBuffer;
  */
 public interface IPacketHandler<T extends MMOClient<?>>
 {
-    public ReceivablePacket<T> handlePacket(ByteBuffer buf, T client);
+	public ReceivablePacket<T> handlePacket(ByteBuffer buf, T client);
 }

+ 19 - 19
MMOCore/src/org/mmocore/network/MMOClient.java

@@ -25,23 +25,23 @@ import java.nio.ByteBuffer;
  */
 public abstract class MMOClient<T extends MMOConnection>
 {
-    private final T _con;
-
-    public MMOClient(final T con)
-    {
-        _con = con;
-    }
-
-    public T getConnection()
-    {
-        return _con;
-    }
-
-    public abstract boolean decrypt(final ByteBuffer buf, final int size);
-
-    public abstract boolean encrypt(final ByteBuffer buf, final int size);
-
-    protected abstract void onDisconnection();
-
-    protected abstract void onForcedDisconnection();
+	private final T _con;
+	
+	public MMOClient(final T con)
+	{
+		_con = con;
+	}
+	
+	public T getConnection()
+	{
+		return _con;
+	}
+	
+	public abstract boolean decrypt(final ByteBuffer buf, final int size);
+	
+	public abstract boolean encrypt(final ByteBuffer buf, final int size);
+	
+	protected abstract void onDisconnection();
+	
+	protected abstract void onForcedDisconnection();
 }

+ 235 - 238
MMOCore/src/org/mmocore/network/MMOConnection.java

@@ -32,242 +32,239 @@ import java.nio.channels.WritableByteChannel;
  */
 public final class MMOConnection<T extends MMOClient<?>>
 {
-    private final SelectorThread<T> _selectorThread;
-
-    private final Socket _socket;
-
-    private final InetAddress _address;
-
-    private final ReadableByteChannel _readableByteChannel;
-
-    private final WritableByteChannel _writableByteChannel;
-
-    private final int _port;
-
-    private final NioNetStackList<SendablePacket<T>> _sendQueue;
-
-    private final SelectionKey _selectionKey;
-
-    //private SendablePacket<T> _closePacket;
-
-    private ByteBuffer _readBuffer;
-
-    private ByteBuffer _primaryWriteBuffer;
-
-    private ByteBuffer _secondaryWriteBuffer;
-
-    private volatile boolean _pendingClose;
-
-    private T _client;
-
-    public MMOConnection(final SelectorThread<T> selectorThread,
-            final Socket socket, final SelectionKey key)
-    {
-        _selectorThread = selectorThread;
-        _socket = socket;
-        _address = socket.getInetAddress();
-        _readableByteChannel = socket.getChannel();
-        _writableByteChannel = socket.getChannel();
-        _port = socket.getPort();
-        _selectionKey = key;
-
-        _sendQueue = new NioNetStackList<SendablePacket<T>>();
-    }
-
-    final void setClient(final T client)
-    {
-        _client = client;
-    }
-
-    public final T getClient()
-    {
-        return _client;
-    }
-
-    public final void sendPacket(final SendablePacket<T> sp)
-    {
-        sp._client = _client;
-        
-        if (_pendingClose)
-            return;
-        
-        synchronized (getSendQueue())
-        {
-            _sendQueue.addLast(sp);
-        }
-        
-        if (!_sendQueue.isEmpty())
-        {
-            try
-            {
-                _selectionKey.interestOps(_selectionKey.interestOps()
-                        | SelectionKey.OP_WRITE);
-            }
-            catch (CancelledKeyException e)
-            {
-                // ignore
-            }
-        }
-    }
-
-    final SelectionKey getSelectionKey()
-    {
-        return _selectionKey;
-    }
-
-    public final InetAddress getInetAddress()
-    {
-        return _address;
-    }
-
-    public final int getPort()
-    {
-        return _port;
-    }
-
-    final void close() throws IOException
-    {
-        _socket.close();
-    }
-
-    final int read(final ByteBuffer buf) throws IOException
-    {
-        return _readableByteChannel.read(buf);
-    }
-
-    final int write(final ByteBuffer buf) throws IOException
-    {
-        return _writableByteChannel.write(buf);
-    }
-
-    final void createWriteBuffer(final ByteBuffer buf)
-    {
-        if (_primaryWriteBuffer == null)
-        {
-            _primaryWriteBuffer = _selectorThread.getPooledBuffer();
-            _primaryWriteBuffer.put(buf);
-        }
-        else
-        {
-            final ByteBuffer temp = _selectorThread.getPooledBuffer();
-            temp.put(buf);
-
-            final int remaining = temp.remaining();
-            _primaryWriteBuffer.flip();
-            final int limit = _primaryWriteBuffer.limit();
-
-            if (remaining >= _primaryWriteBuffer.remaining())
-            {
-                temp.put(_primaryWriteBuffer);
-                _selectorThread.recycleBuffer(_primaryWriteBuffer);
-                _primaryWriteBuffer = temp;
-            }
-            else
-            {
-                _primaryWriteBuffer.limit(remaining);
-                temp.put(_primaryWriteBuffer);
-                _primaryWriteBuffer.limit(limit);
-                _primaryWriteBuffer.compact();
-                _secondaryWriteBuffer = _primaryWriteBuffer;
-                _primaryWriteBuffer = temp;
-            }
-        }
-    }
-
-    final boolean hasPendingWriteBuffer()
-    {
-        return _primaryWriteBuffer != null;
-    }
-
-    final void movePendingWriteBufferTo(final ByteBuffer dest)
-    {
-        _primaryWriteBuffer.flip();
-        dest.put(_primaryWriteBuffer);
-        _selectorThread.recycleBuffer(_primaryWriteBuffer);
-        _primaryWriteBuffer = _secondaryWriteBuffer;
-        _secondaryWriteBuffer = null;
-    }
-
-    final void setReadBuffer(final ByteBuffer buf)
-    {
-        _readBuffer = buf;
-    }
-
-    final ByteBuffer getReadBuffer()
-    {
-        return _readBuffer;
-    }
-
-    public final boolean isClosed()
-    {
-        return _pendingClose;
-    }
-
-    final NioNetStackList<SendablePacket<T>> getSendQueue()
-    {
-        return _sendQueue;
-    }
-
-    /*final SendablePacket<T> getClosePacket()
-    {
-        return _closePacket;
-    }*/
-
-    @SuppressWarnings("unchecked")
-    public final void close(final SendablePacket<T> sp)
-    {
-        
-        close(new SendablePacket[] {sp});
-    }
-    
-    public final void close(final SendablePacket<T>[] closeList)
-    {
-        if (_pendingClose)
-            return;
-        
-        synchronized (getSendQueue())
-        {
-            if (!_pendingClose)
-            {
-                _pendingClose = true;
-                _sendQueue.clear();
-                for (SendablePacket<T> sp : closeList)
-                    _sendQueue.addLast(sp);
-            }
-        }
-
-        try
-        {
-            _selectionKey.interestOps(_selectionKey.interestOps()
-                    & ~SelectionKey.OP_WRITE);
-        }
-        catch (CancelledKeyException e)
-        {
-            // ignore
-        }
-
-        //_closePacket = sp;
-        _selectorThread.closeConnection(this);
-    }
-
-    final void releaseBuffers()
-    {
-        if (_primaryWriteBuffer != null)
-        {
-            _selectorThread.recycleBuffer(_primaryWriteBuffer);
-            _primaryWriteBuffer = null;
-
-            if (_secondaryWriteBuffer != null)
-            {
-                _selectorThread.recycleBuffer(_secondaryWriteBuffer);
-                _secondaryWriteBuffer = null;
-            }
-        }
-
-        if (_readBuffer != null)
-        {
-            _selectorThread.recycleBuffer(_readBuffer);
-            _readBuffer = null;
-        }
-    }
+	private final SelectorThread<T> _selectorThread;
+	
+	private final Socket _socket;
+	
+	private final InetAddress _address;
+	
+	private final ReadableByteChannel _readableByteChannel;
+	
+	private final WritableByteChannel _writableByteChannel;
+	
+	private final int _port;
+	
+	private final NioNetStackList<SendablePacket<T>> _sendQueue;
+	
+	private final SelectionKey _selectionKey;
+	
+	//private SendablePacket<T> _closePacket;
+	
+	private ByteBuffer _readBuffer;
+	
+	private ByteBuffer _primaryWriteBuffer;
+	
+	private ByteBuffer _secondaryWriteBuffer;
+	
+	private volatile boolean _pendingClose;
+	
+	private T _client;
+	
+	public MMOConnection(final SelectorThread<T> selectorThread, final Socket socket, final SelectionKey key)
+	{
+		_selectorThread = selectorThread;
+		_socket = socket;
+		_address = socket.getInetAddress();
+		_readableByteChannel = socket.getChannel();
+		_writableByteChannel = socket.getChannel();
+		_port = socket.getPort();
+		_selectionKey = key;
+		
+		_sendQueue = new NioNetStackList<SendablePacket<T>>();
+	}
+	
+	final void setClient(final T client)
+	{
+		_client = client;
+	}
+	
+	public final T getClient()
+	{
+		return _client;
+	}
+	
+	public final void sendPacket(final SendablePacket<T> sp)
+	{
+		sp._client = _client;
+		
+		if (_pendingClose)
+			return;
+		
+		synchronized (getSendQueue())
+		{
+			_sendQueue.addLast(sp);
+		}
+		
+		if (!_sendQueue.isEmpty())
+		{
+			try
+			{
+				_selectionKey.interestOps(_selectionKey.interestOps() | SelectionKey.OP_WRITE);
+			}
+			catch (CancelledKeyException e)
+			{
+				// ignore
+			}
+		}
+	}
+	
+	final SelectionKey getSelectionKey()
+	{
+		return _selectionKey;
+	}
+	
+	public final InetAddress getInetAddress()
+	{
+		return _address;
+	}
+	
+	public final int getPort()
+	{
+		return _port;
+	}
+	
+	final void close() throws IOException
+	{
+		_socket.close();
+	}
+	
+	final int read(final ByteBuffer buf) throws IOException
+	{
+		return _readableByteChannel.read(buf);
+	}
+	
+	final int write(final ByteBuffer buf) throws IOException
+	{
+		return _writableByteChannel.write(buf);
+	}
+	
+	final void createWriteBuffer(final ByteBuffer buf)
+	{
+		if (_primaryWriteBuffer == null)
+		{
+			_primaryWriteBuffer = _selectorThread.getPooledBuffer();
+			_primaryWriteBuffer.put(buf);
+		}
+		else
+		{
+			final ByteBuffer temp = _selectorThread.getPooledBuffer();
+			temp.put(buf);
+			
+			final int remaining = temp.remaining();
+			_primaryWriteBuffer.flip();
+			final int limit = _primaryWriteBuffer.limit();
+			
+			if (remaining >= _primaryWriteBuffer.remaining())
+			{
+				temp.put(_primaryWriteBuffer);
+				_selectorThread.recycleBuffer(_primaryWriteBuffer);
+				_primaryWriteBuffer = temp;
+			}
+			else
+			{
+				_primaryWriteBuffer.limit(remaining);
+				temp.put(_primaryWriteBuffer);
+				_primaryWriteBuffer.limit(limit);
+				_primaryWriteBuffer.compact();
+				_secondaryWriteBuffer = _primaryWriteBuffer;
+				_primaryWriteBuffer = temp;
+			}
+		}
+	}
+	
+	final boolean hasPendingWriteBuffer()
+	{
+		return _primaryWriteBuffer != null;
+	}
+	
+	final void movePendingWriteBufferTo(final ByteBuffer dest)
+	{
+		_primaryWriteBuffer.flip();
+		dest.put(_primaryWriteBuffer);
+		_selectorThread.recycleBuffer(_primaryWriteBuffer);
+		_primaryWriteBuffer = _secondaryWriteBuffer;
+		_secondaryWriteBuffer = null;
+	}
+	
+	final void setReadBuffer(final ByteBuffer buf)
+	{
+		_readBuffer = buf;
+	}
+	
+	final ByteBuffer getReadBuffer()
+	{
+		return _readBuffer;
+	}
+	
+	public final boolean isClosed()
+	{
+		return _pendingClose;
+	}
+	
+	final NioNetStackList<SendablePacket<T>> getSendQueue()
+	{
+		return _sendQueue;
+	}
+	
+	/*final SendablePacket<T> getClosePacket()
+	{
+	    return _closePacket;
+	}*/
+
+	@SuppressWarnings("unchecked")
+	public final void close(final SendablePacket<T> sp)
+	{
+		
+		close(new SendablePacket[] { sp });
+	}
+	
+	public final void close(final SendablePacket<T>[] closeList)
+	{
+		if (_pendingClose)
+			return;
+		
+		synchronized (getSendQueue())
+		{
+			if (!_pendingClose)
+			{
+				_pendingClose = true;
+				_sendQueue.clear();
+				for (SendablePacket<T> sp : closeList)
+					_sendQueue.addLast(sp);
+			}
+		}
+		
+		try
+		{
+			_selectionKey.interestOps(_selectionKey.interestOps() & ~SelectionKey.OP_WRITE);
+		}
+		catch (CancelledKeyException e)
+		{
+			// ignore
+		}
+		
+		//_closePacket = sp;
+		_selectorThread.closeConnection(this);
+	}
+	
+	final void releaseBuffers()
+	{
+		if (_primaryWriteBuffer != null)
+		{
+			_selectorThread.recycleBuffer(_primaryWriteBuffer);
+			_primaryWriteBuffer = null;
+			
+			if (_secondaryWriteBuffer != null)
+			{
+				_selectorThread.recycleBuffer(_secondaryWriteBuffer);
+				_secondaryWriteBuffer = null;
+			}
+		}
+		
+		if (_readBuffer != null)
+		{
+			_selectorThread.recycleBuffer(_readBuffer);
+			_readBuffer = null;
+		}
+	}
 }

+ 80 - 80
MMOCore/src/org/mmocore/network/NioNetStackList.java

@@ -22,83 +22,83 @@ package org.mmocore.network;
  */
 public final class NioNetStackList<E>
 {
-    private final NioNetStackNode _start = new NioNetStackNode();
-
-    private final NioNetStackNodeBuf _buf = new NioNetStackNodeBuf();
-
-    private NioNetStackNode _end = new NioNetStackNode();
-
-    public NioNetStackList()
-    {
-        clear();
-    }
-
-    public final void addLast(final E elem)
-    {
-        final NioNetStackNode newEndNode = _buf.removeFirst();
-        _end._value = elem;
-        _end._next = newEndNode;
-        _end = newEndNode;
-    }
-
-    public final E removeFirst()
-    {
-        final NioNetStackNode old = _start._next;
-        final E value = old._value;
-        _start._next = old._next;
-        _buf.addLast(old);
-        return value;
-    }
-
-    public final boolean isEmpty()
-    {
-        return _start._next == _end;
-    }
-
-    public final void clear()
-    {
-        _start._next = _end;
-    }
-
-    private final class NioNetStackNode
-    {
-        private NioNetStackNode _next;
-
-        private E _value;
-
-        private NioNetStackNode()
-        {
-
-        }
-    }
-
-    private final class NioNetStackNodeBuf
-    {
-        private final NioNetStackNode _start = new NioNetStackNode();
-
-        private NioNetStackNode _end = new NioNetStackNode();
-
-        NioNetStackNodeBuf()
-        {
-            _start._next = _end;
-        }
-
-        final void addLast(final NioNetStackNode node)
-        {
-            node._next = null;
-            node._value = null;
-            _end._next = node;
-            _end = node;
-        }
-
-        final NioNetStackNode removeFirst()
-        {
-            if (_start._next == _end)
-                return new NioNetStackNode();
-
-            final NioNetStackNode old = _start._next;
-            _start._next = old._next;
-            return old;
-        }
-    }
-}
+	private final NioNetStackNode _start = new NioNetStackNode();
+	
+	private final NioNetStackNodeBuf _buf = new NioNetStackNodeBuf();
+	
+	private NioNetStackNode _end = new NioNetStackNode();
+	
+	public NioNetStackList()
+	{
+		clear();
+	}
+	
+	public final void addLast(final E elem)
+	{
+		final NioNetStackNode newEndNode = _buf.removeFirst();
+		_end._value = elem;
+		_end._next = newEndNode;
+		_end = newEndNode;
+	}
+	
+	public final E removeFirst()
+	{
+		final NioNetStackNode old = _start._next;
+		final E value = old._value;
+		_start._next = old._next;
+		_buf.addLast(old);
+		return value;
+	}
+	
+	public final boolean isEmpty()
+	{
+		return _start._next == _end;
+	}
+	
+	public final void clear()
+	{
+		_start._next = _end;
+	}
+	
+	private final class NioNetStackNode
+	{
+		private NioNetStackNode _next;
+		
+		private E _value;
+		
+		private NioNetStackNode()
+		{
+			
+		}
+	}
+	
+	private final class NioNetStackNodeBuf
+	{
+		private final NioNetStackNode _start = new NioNetStackNode();
+		
+		private NioNetStackNode _end = new NioNetStackNode();
+		
+		NioNetStackNodeBuf()
+		{
+			_start._next = _end;
+		}
+		
+		final void addLast(final NioNetStackNode node)
+		{
+			node._next = null;
+			node._value = null;
+			_end._next = node;
+			_end = node;
+		}
+		
+		final NioNetStackNode removeFirst()
+		{
+			if (_start._next == _end)
+				return new NioNetStackNode();
+			
+			final NioNetStackNode old = _start._next;
+			_start._next = old._next;
+			return old;
+		}
+	}
+}

+ 31 - 31
MMOCore/src/org/mmocore/network/NioNetStringBuffer.java

@@ -7,35 +7,35 @@ import java.nio.BufferOverflowException;
  */
 public final class NioNetStringBuffer
 {
-    private final char[] _buf;
-
-    private final int _size;
-
-    private int _len;
-
-    public NioNetStringBuffer(final int size)
-    {
-        _buf = new char[size];
-        _size = size;
-        _len = 0;
-    }
-
-    public final void clear()
-    {
-        _len = 0;
-    }
-
-    public final void append(final char c)
-    {
-        if (_len < _size)
-            _buf[_len++] = c;
-        else
-            throw new BufferOverflowException();
-    }
-
-    @Override
-    public final String toString()
-    {
-        return new String(_buf, 0, _len);
-    }
+	private final char[] _buf;
+	
+	private final int _size;
+	
+	private int _len;
+	
+	public NioNetStringBuffer(final int size)
+	{
+		_buf = new char[size];
+		_size = size;
+		_len = 0;
+	}
+	
+	public final void clear()
+	{
+		_len = 0;
+	}
+	
+	public final void append(final char c)
+	{
+		if (_len < _size)
+			_buf[_len++] = c;
+		else
+			throw new BufferOverflowException();
+	}
+	
+	@Override
+	public final String toString()
+	{
+		return new String(_buf, 0, _len);
+	}
 }

+ 71 - 71
MMOCore/src/org/mmocore/network/ReceivablePacket.java

@@ -25,75 +25,75 @@ import java.nio.ByteBuffer;
  */
 public abstract class ReceivablePacket<T extends MMOClient<?>> extends AbstractPacket<T> implements Runnable
 {
-    NioNetStringBuffer _sbuf;
-
-    protected ReceivablePacket()
-    {
-
-    }
-
-    protected abstract boolean read();
-
-    public abstract void run();
-
-    protected final void readB(final byte[] dst)
-    {
-        _buf.get(dst);
-    }
-
-    protected final void readB(final byte[] dst, final int offset, final int len)
-    {
-        _buf.get(dst, offset, len);
-    }
-
-    protected final int readC()
-    {
-        return _buf.get() & 0xFF;
-    }
-
-    protected final int readH()
-    {
-        return _buf.getShort() & 0xFFFF;
-    }
-
-    protected final int readD()
-    {
-        return _buf.getInt();
-    }
-
-    protected final long readQ()
-    {
-        return _buf.getLong();
-    }
-
-    protected final double readF()
-    {
-        return _buf.getDouble();
-    }
-
-    protected final String readS()
-    {
-        _sbuf.clear();
-
-        char ch;
-        while ((ch = _buf.getChar()) != 0)
-        {
-            _sbuf.append(ch);
-        }
-
-        return _sbuf.toString();
-    }
-    
-    /**
-     * packet forge purpose
-     * @param data
-     * @param client
-     * @param sBuffer
-     */
-    public void setBuffers(ByteBuffer data, T client, NioNetStringBuffer sBuffer)
-    {
-        _buf = data;
-        _client = client;
-        _sbuf = sBuffer;
-    }
+	NioNetStringBuffer _sbuf;
+	
+	protected ReceivablePacket()
+	{
+		
+	}
+	
+	protected abstract boolean read();
+	
+	public abstract void run();
+	
+	protected final void readB(final byte[] dst)
+	{
+		_buf.get(dst);
+	}
+	
+	protected final void readB(final byte[] dst, final int offset, final int len)
+	{
+		_buf.get(dst, offset, len);
+	}
+	
+	protected final int readC()
+	{
+		return _buf.get() & 0xFF;
+	}
+	
+	protected final int readH()
+	{
+		return _buf.getShort() & 0xFFFF;
+	}
+	
+	protected final int readD()
+	{
+		return _buf.getInt();
+	}
+	
+	protected final long readQ()
+	{
+		return _buf.getLong();
+	}
+	
+	protected final double readF()
+	{
+		return _buf.getDouble();
+	}
+	
+	protected final String readS()
+	{
+		_sbuf.clear();
+		
+		char ch;
+		while ((ch = _buf.getChar()) != 0)
+		{
+			_sbuf.append(ch);
+		}
+		
+		return _sbuf.toString();
+	}
+	
+	/**
+	 * packet forge purpose
+	 * @param data
+	 * @param client
+	 * @param sBuffer
+	 */
+	public void setBuffers(ByteBuffer data, T client, NioNetStringBuffer sBuffer)
+	{
+		_buf = data;
+		_client = client;
+		_sbuf = sBuffer;
+	}
 }

+ 36 - 36
MMOCore/src/org/mmocore/network/SelectorConfig.java

@@ -23,39 +23,39 @@ package org.mmocore.network;
  */
 public final class SelectorConfig
 {
-    public int READ_BUFFER_SIZE = 64 * 1024;
-
-    public int WRITE_BUFFER_SIZE = 64 * 1024;
-
-    public int HELPER_BUFFER_COUNT = 20;
-
-    public int HELPER_BUFFER_SIZE = 64 * 1024;
-
-    /**
-     * Server will try to send MAX_SEND_PER_PASS packets per socket write call<br>
-     * however it may send less if the write buffer was filled before achieving
-     * this value.
-     */
-    public int MAX_SEND_PER_PASS = 10;
-
-    /**
-     * Server will try to read MAX_READ_PER_PASS packets per socket read call<br>
-     * however it may read less if the read buffer was empty before achieving
-     * this value.
-     */
-    public int MAX_READ_PER_PASS = 10;
-
-    /**
-     * Defines how much time (in milis) should the selector sleep, an higher
-     * value increases throughput but also increases latency(to a max of the
-     * sleep value itself).<BR>
-     * Also an extremely high value(usually > 100) will decrease throughput due
-     * to the server not doing enough sends per second (depends on max sends per
-     * pass).<BR>
-     * <BR>
-     * Recommended values:<BR>
-     * 1 for minimal latency.<BR>
-     * 10-30 for an latency/troughput trade-off based on your needs.<BR>
-     */
-    public int SLEEP_TIME = 10;
-}
+	public int READ_BUFFER_SIZE = 64 * 1024;
+	
+	public int WRITE_BUFFER_SIZE = 64 * 1024;
+	
+	public int HELPER_BUFFER_COUNT = 20;
+	
+	public int HELPER_BUFFER_SIZE = 64 * 1024;
+	
+	/**
+	 * Server will try to send MAX_SEND_PER_PASS packets per socket write call<br>
+	 * however it may send less if the write buffer was filled before achieving
+	 * this value.
+	 */
+	public int MAX_SEND_PER_PASS = 10;
+	
+	/**
+	 * Server will try to read MAX_READ_PER_PASS packets per socket read call<br>
+	 * however it may read less if the read buffer was empty before achieving
+	 * this value.
+	 */
+	public int MAX_READ_PER_PASS = 10;
+	
+	/**
+	 * Defines how much time (in milis) should the selector sleep, an higher
+	 * value increases throughput but also increases latency(to a max of the
+	 * sleep value itself).<BR>
+	 * Also an extremely high value(usually > 100) will decrease throughput due
+	 * to the server not doing enough sends per second (depends on max sends per
+	 * pass).<BR>
+	 * <BR>
+	 * Recommended values:<BR>
+	 * 1 for minimal latency.<BR>
+	 * 10-30 for an latency/troughput trade-off based on your needs.<BR>
+	 */
+	public int SLEEP_TIME = 10;
+}

+ 614 - 614
MMOCore/src/org/mmocore/network/SelectorThread.java

@@ -37,617 +37,617 @@ import javolution.util.FastList;
  */
 public final class SelectorThread<T extends MMOClient<?>> extends Thread
 {
-    // default BYTE_ORDER
-    private static final ByteOrder BYTE_ORDER = ByteOrder.LITTLE_ENDIAN;
-    // default HEADER_SIZE
-    private static final int HEADER_SIZE = 2;
-    // Selector
-    private final Selector _selector;
-    // Implementations
-    private final IPacketHandler<T> _packetHandler;
-    private final IMMOExecutor<T> _executor;
-    private final IClientFactory<T> _clientFactory;
-    private final IAcceptFilter _acceptFilter;
-    // Configurations
-    private final int HELPER_BUFFER_SIZE;
-    private final int HELPER_BUFFER_COUNT;
-    private final int MAX_SEND_PER_PASS;
-    private final int MAX_READ_PER_PASS;
-    private final long SLEEP_TIME;
-    // Main Buffers
-    private final ByteBuffer DIRECT_WRITE_BUFFER;
-    private final ByteBuffer WRITE_BUFFER;
-    private final ByteBuffer READ_BUFFER;
-    // String Buffer
-    private final NioNetStringBuffer STRING_BUFFER;
-    // ByteBuffers General Purpose Pool
-    private final FastList<ByteBuffer> _bufferPool;
-    // Pending Close
-    private final NioNetStackList<MMOConnection<T>> _pendingClose;
-    
-    private boolean _shutdown;
-    
-    public SelectorThread(final SelectorConfig sc, final IMMOExecutor<T> executor, final IPacketHandler<T> packetHandler, final IClientFactory<T> clientFactory, final IAcceptFilter acceptFilter) throws IOException
-    {
-        super.setName("SelectorThread-" + super.getId());
-
-        HELPER_BUFFER_SIZE = sc.HELPER_BUFFER_SIZE;
-        HELPER_BUFFER_COUNT = sc.HELPER_BUFFER_COUNT;
-        MAX_SEND_PER_PASS = sc.MAX_SEND_PER_PASS;
-        MAX_READ_PER_PASS = sc.MAX_READ_PER_PASS;
-
-        SLEEP_TIME = sc.SLEEP_TIME;
-
-        DIRECT_WRITE_BUFFER = ByteBuffer.allocateDirect(sc.WRITE_BUFFER_SIZE) .order(BYTE_ORDER);
-        WRITE_BUFFER = ByteBuffer.wrap(new byte[sc.WRITE_BUFFER_SIZE]).order(BYTE_ORDER);
-        READ_BUFFER = ByteBuffer.wrap(new byte[sc.READ_BUFFER_SIZE]).order(BYTE_ORDER);
-
-        STRING_BUFFER = new NioNetStringBuffer(64 * 1024);
-
-        _pendingClose = new NioNetStackList<MMOConnection<T>>();
-        _bufferPool = new FastList<ByteBuffer>();
-        
-        for (int i = 0; i < HELPER_BUFFER_COUNT; i++)
-        {
-            _bufferPool.addLast(ByteBuffer.wrap(new byte[HELPER_BUFFER_SIZE]).order(BYTE_ORDER));
-        }
-
-        _acceptFilter = acceptFilter;
-        _packetHandler = packetHandler;
-        _clientFactory = clientFactory;
-        _executor = executor;
-        _selector = Selector.open();
-    }
-    
-    public final void openServerSocket(InetAddress address, int tcpPort) throws IOException
-    {
-        ServerSocketChannel selectable = ServerSocketChannel.open();
-        selectable.configureBlocking(false);
-
-        ServerSocket ss = selectable.socket();
-        
-        if (address == null)
-            ss.bind(new InetSocketAddress(tcpPort));
-        else
-            ss.bind(new InetSocketAddress(address, tcpPort));
-        
-        selectable.register(_selector, SelectionKey.OP_ACCEPT);
-    }
-    
-    final ByteBuffer getPooledBuffer()
-    {
-        if (_bufferPool.isEmpty())
-            return ByteBuffer.wrap(new byte[HELPER_BUFFER_SIZE]).order(BYTE_ORDER);
-        
-        return _bufferPool.removeFirst();
-    }
-    
-    final void recycleBuffer(final ByteBuffer buf)
-    {
-        if (_bufferPool.size() < HELPER_BUFFER_COUNT)
-        {
-            buf.clear();
-            _bufferPool.addLast(buf);
-        }
-    }
-    
-    @SuppressWarnings("unchecked")
-    @Override
-    public final void run()
-    {
-        int selectedKeysCount = 0;
-
-        SelectionKey key;
-        MMOConnection<T> con;
-
-        Iterator<SelectionKey> selectedKeys;
-
-        while (!_shutdown)
-        {
-            try
-            {
-                selectedKeysCount = _selector.selectNow();
-            }
-            catch (IOException e)
-            {
-                e.printStackTrace();
-            }
-
-            if (selectedKeysCount > 0)
-            {
-                selectedKeys = _selector.selectedKeys().iterator();
-
-                while (selectedKeys.hasNext())
-                {
-                    key = selectedKeys.next();
-                    selectedKeys.remove();
-
-                    con = (MMOConnection<T>) key.attachment();
-
-                    switch (key.readyOps())
-                    {
-                        case SelectionKey.OP_CONNECT:
-                            finishConnection(key, con);
-                            break;
-                        case SelectionKey.OP_ACCEPT:
-                            acceptConnection(key, con);
-                            break;
-                        case SelectionKey.OP_READ:
-                            readPacket(key, con);
-                            break;
-                        case SelectionKey.OP_WRITE:
-                            writePacket(key, con);
-                            break;
-                        case SelectionKey.OP_READ | SelectionKey.OP_WRITE:
-                            writePacket(key, con);
-                            if (key.isValid())
-                                readPacket(key, con);
-                            break;
-                    }
-                }
-            }
-
-            synchronized (_pendingClose)
-            {
-                while (!_pendingClose.isEmpty())
-                {
-                    con = _pendingClose.removeFirst();
-                    writeClosePacket(con);
-                    closeConnectionImpl(con.getSelectionKey(), con);
-                }
-            }
-
-            try
-            {
-                Thread.sleep(SLEEP_TIME);
-            }
-            catch (InterruptedException e)
-            {
-                e.printStackTrace();
-            }
-        }
-        closeSelectorThread();
-    }
-    
-    private final void finishConnection(final SelectionKey key, final MMOConnection<T> con)
-    {
-        try
-        {
-            ((SocketChannel) key.channel()).finishConnect();
-        }
-        catch (IOException e)
-        {
-            con.getClient().onForcedDisconnection();
-            closeConnectionImpl(key, con);
-        }
-
-        // key might have been invalidated on finishConnect()
-        if (key.isValid())
-        {
-            key.interestOps(key.interestOps() | SelectionKey.OP_READ);
-            key.interestOps(key.interestOps() & ~SelectionKey.OP_CONNECT);
-        }
-    }
-    
-    private final void acceptConnection(final SelectionKey key, MMOConnection<T> con)
-    {
-        ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
-        SocketChannel sc;
-
-        try
-        {
-            while ((sc = ssc.accept()) != null)
-            {
-                if (_acceptFilter == null || _acceptFilter.accept(sc))
-                {
-                    sc.configureBlocking(false);
-                    SelectionKey clientKey = sc.register(_selector, SelectionKey.OP_READ);
-                    con = new MMOConnection<T>(this, sc.socket(), clientKey);
-                    con.setClient(_clientFactory.create(con));
-                    clientKey.attach(con);
-                }
-                else
-                    sc.socket().close();
-            }
-        }
-        catch (IOException e)
-        {
-            e.printStackTrace();
-        }
-    }
-    
-    private final void readPacket(final SelectionKey key, final MMOConnection<T> con)
-    {
-        if (!con.isClosed())
-        {
-            ByteBuffer buf;
-            if ((buf = con.getReadBuffer()) == null)
-            {
-                buf = READ_BUFFER;
-            }
-
-            // if we try to to do a read with no space in the buffer it will
-            // read 0 bytes
-            // going into infinite loop
-            if (buf.position() == buf.limit())
-                System.exit(0);
-
-            int result = -2;
-
-            try
-            {
-                result = con.read(buf);
-            }
-            catch (IOException e)
-            {
-                // error handling goes bellow
-            }
-
-            if (result > 0)
-            {
-                buf.flip();
-
-                final T client = con.getClient();
-
-                for (int i = 0; i < MAX_READ_PER_PASS; i++)
-                {
-                    if (!tryReadPacket(key, client, buf, con))
-                        return;
-                }
-
-                // only reachable if MAX_READ_PER_PASS has been reached
-                // check if there are some more bytes in buffer
-                // and allocate/compact to prevent content lose.
-                if (buf.remaining() > 0)
-                {
-                    // did we use the READ_BUFFER ?
-                    if (buf == READ_BUFFER)
-                        // move the pending byte to the connections READ_BUFFER
-                        allocateReadBuffer(con);
-                    else
-                        // move the first byte to the beginning :)
-                        buf.compact();
-                }
-            }
-            else
-            {
-                switch (result)
-                {
-                    case 0:
-                    case -1:
-                        closeConnectionImpl(key, con);
-                        break;
-                    case -2:
-                        con.getClient().onForcedDisconnection();
-                        closeConnectionImpl(key, con);
-                        break;
-                }
-            }
-        }
-    }
-    
-    private final boolean tryReadPacket(final SelectionKey key, final T client, final ByteBuffer buf, final MMOConnection<T> con)
-    {
-        switch (buf.remaining())
-        {
-            case 0:
-                // buffer is full
-                // nothing to read
-                return false;
-            case 1:
-                // we don`t have enough data for header so we need to read
-                key.interestOps(key.interestOps() | SelectionKey.OP_READ);
-
-                // did we use the READ_BUFFER ?
-                if (buf == READ_BUFFER)
-                    // move the pending byte to the connections READ_BUFFER
-                    allocateReadBuffer(con);
-                else
-                    // move the first byte to the beginning :)
-                    buf.compact();
-                return false;
-            default:
-                // data size excluding header size :>
-                final int dataPending = (buf.getShort() & 0xFFFF) - HEADER_SIZE;
-
-                // do we got enough bytes for the packet?
-                if (dataPending <= buf.remaining())
-                {
-                    // avoid parsing dummy packets (packets without body)
-                    if (dataPending > 0)
-                    {
-                        final int pos = buf.position();
-                        parseClientPacket(pos, buf, dataPending, client);
-                        buf.position(pos + dataPending);
-                    }
-
-                    // if we are done with this buffer
-                    if (!buf.hasRemaining())
-                    {
-                        if (buf != READ_BUFFER)
-                        {
-                            con.setReadBuffer(null);
-                            recycleBuffer(buf);
-                        }
-                        else
-                        {
-                            READ_BUFFER.clear();
-                        }
-                        return false;
-                    }
-                    return true;
-                }
-                else
-                {
-                    // we don`t have enough bytes for the dataPacket so we need
-                    // to read
-                    key.interestOps(key.interestOps() | SelectionKey.OP_READ);
-                    
-                    // did we use the READ_BUFFER ?
-                    if (buf == READ_BUFFER)
-                    {
-                        // move it`s position
-                        buf.position(buf.position() - HEADER_SIZE);
-                        // move the pending byte to the connections READ_BUFFER
-                        allocateReadBuffer(con);
-                    }
-                    else
-                    {
-                        buf.position(buf.position() - HEADER_SIZE);
-                        buf.compact();
-                    }
-                    return false;
-                }
-        }
-    }
-    
-    private final void allocateReadBuffer(final MMOConnection<T> con)
-    {
-        con.setReadBuffer(getPooledBuffer().put(READ_BUFFER));
-        READ_BUFFER.clear();
-    }
-    
-    private final void parseClientPacket(final int pos, final ByteBuffer buf, final int dataSize, final T client)
-    {
-        final boolean ret = client.decrypt(buf, dataSize);
-
-        if (ret && buf.hasRemaining())
-        {
-            // apply limit
-            final int limit = buf.limit();
-            buf.limit(pos + dataSize);
-            final ReceivablePacket<T> cp = _packetHandler.handlePacket(buf, client);
-
-            if (cp != null)
-            {
-                cp._buf = buf;
-                cp._sbuf = STRING_BUFFER;
-                cp._client = client;
-
-                if (cp.read())
-                    _executor.execute(cp);
-
-                cp._buf = null;
-                cp._sbuf = null;
-            }
-            buf.limit(limit);
-        }
-    }
-    
-    private final void writeClosePacket(final MMOConnection<T> con)
-    {
-        SendablePacket<T> sp;
-        while ((sp = con.getSendQueue().removeFirst()) != null)
-        {
-            WRITE_BUFFER.clear();
-
-            putPacketIntoWriteBuffer(con.getClient(), sp);
-
-            WRITE_BUFFER.flip();
-
-            try
-            {
-                con.write(WRITE_BUFFER);
-            }
-            catch (IOException e)
-            {
-                // error handling goes on the if bellow
-            }
-        }
-    }
-    
-    protected final void writePacket(final SelectionKey key, final MMOConnection<T> con)
-    {
-        if (!prepareWriteBuffer(con))
-        {
-            key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
-            return;
-        }
-
-        DIRECT_WRITE_BUFFER.flip();
-
-        final int size = DIRECT_WRITE_BUFFER.remaining();
-
-        int result = -1;
-
-        try
-        {
-            result = con.write(DIRECT_WRITE_BUFFER);
-        }
-        catch (IOException e)
-        {
-            // error handling goes on the if bellow
-        }
-
-        // check if no error happened
-        if (result >= 0)
-        {
-            // check if we written everything
-            if (result == size)
-            {
-                // complete write
-                synchronized (con.getSendQueue())
-                {
-                    if (con.getSendQueue().isEmpty() && !con.hasPendingWriteBuffer())
-                    {
-                        key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
-                    }
-                }
-            }
-            else
-                // incomplete write
-                con.createWriteBuffer(DIRECT_WRITE_BUFFER);
-        }
-        else
-        {
-            con.getClient().onForcedDisconnection();
-            closeConnectionImpl(key, con);
-        }
-    }
-
-    private final boolean prepareWriteBuffer(final MMOConnection<T> con)
-    {
-        boolean hasPending = false;
-        DIRECT_WRITE_BUFFER.clear();
-
-        // if there is pending content add it
-        if (con.hasPendingWriteBuffer())
-        {
-            con.movePendingWriteBufferTo(DIRECT_WRITE_BUFFER);
-            hasPending = true;
-        }
-
-        if (DIRECT_WRITE_BUFFER.remaining() > 1 && !con.hasPendingWriteBuffer())
-        {
-            final NioNetStackList<SendablePacket<T>> sendQueue = con.getSendQueue();
-            final T client = con.getClient();
-            SendablePacket<T> sp;
-
-            for (int i = 0; i < MAX_SEND_PER_PASS; i++)
-            {
-                synchronized (con.getSendQueue())
-                {
-                    if (sendQueue.isEmpty())
-                        sp = null;
-                    else
-                        sp = sendQueue.removeFirst();
-                }
-
-                if (sp == null)
-                    break;
-
-                hasPending = true;
-
-                // put into WriteBuffer
-                putPacketIntoWriteBuffer(client, sp);
-
-                WRITE_BUFFER.flip();
-
-                if (DIRECT_WRITE_BUFFER.remaining() >= WRITE_BUFFER.limit())
-                    DIRECT_WRITE_BUFFER.put(WRITE_BUFFER);
-                else
-                {
-                    con.createWriteBuffer(WRITE_BUFFER);
-                    break;
-                }
-            }
-        }
-        return hasPending;
-    }
-    
-    private final void putPacketIntoWriteBuffer(final T client,final SendablePacket<T> sp)
-    {
-        WRITE_BUFFER.clear();
-
-        // reserve space for the size
-        final int headerPos = WRITE_BUFFER.position();
-        final int dataPos = headerPos + HEADER_SIZE;
-        WRITE_BUFFER.position(dataPos);
-
-        // set the write buffer
-        sp._buf = WRITE_BUFFER;
-        // write content to buffer
-        sp.write();
-        // delete the write buffer
-        sp._buf = null;
-
-        // size (inclusive header)
-        int dataSize = WRITE_BUFFER.position() - dataPos;
-        WRITE_BUFFER.position(dataPos);
-        client.encrypt(WRITE_BUFFER, dataSize);
-
-        // recalculate size after encryption
-        dataSize = WRITE_BUFFER.position() - dataPos;
-
-        WRITE_BUFFER.position(headerPos);
-        // write header
-        WRITE_BUFFER.putShort((short) (dataSize + HEADER_SIZE));
-        WRITE_BUFFER.position(dataPos + dataSize);
-    }
-    
-    final void closeConnection(final MMOConnection<T> con)
-    {
-        synchronized (_pendingClose)
-        {
-            _pendingClose.addLast(con);
-        }
-    }
-    
-    private final void closeConnectionImpl(final SelectionKey key, final MMOConnection<T> con)
-    {
-        try
-        {
-            // notify connection
-            con.getClient().onDisconnection();
-        }
-        finally
-        {
-            try
-            {
-                // close socket and the SocketChannel
-                con.close();
-            }
-            catch (IOException e)
-            {
-                // ignore, we are closing anyway
-            }
-            finally
-            {
-                con.releaseBuffers();
-                // clear attachment
-                key.attach(null);
-                // cancel key
-                key.cancel();
-            }
-        }
-    }
-    
-    public final void shutdown()
-    {
-        _shutdown = true;
-    }
-    
-    protected void closeSelectorThread()
-    {
-        for (final SelectionKey key : _selector.keys())
-        {
-            try
-            {
-                key.channel().close();
-            }
-            catch (IOException e)
-            {
-                // ignore
-            }
-        }
-
-        try
-        {
-            _selector.close();
-        }
-        catch (IOException e)
-        {
-            // Ignore
-        }
-    }
-}
+	// default BYTE_ORDER
+	private static final ByteOrder BYTE_ORDER = ByteOrder.LITTLE_ENDIAN;
+	// default HEADER_SIZE
+	private static final int HEADER_SIZE = 2;
+	// Selector
+	private final Selector _selector;
+	// Implementations
+	private final IPacketHandler<T> _packetHandler;
+	private final IMMOExecutor<T> _executor;
+	private final IClientFactory<T> _clientFactory;
+	private final IAcceptFilter _acceptFilter;
+	// Configurations
+	private final int HELPER_BUFFER_SIZE;
+	private final int HELPER_BUFFER_COUNT;
+	private final int MAX_SEND_PER_PASS;
+	private final int MAX_READ_PER_PASS;
+	private final long SLEEP_TIME;
+	// Main Buffers
+	private final ByteBuffer DIRECT_WRITE_BUFFER;
+	private final ByteBuffer WRITE_BUFFER;
+	private final ByteBuffer READ_BUFFER;
+	// String Buffer
+	private final NioNetStringBuffer STRING_BUFFER;
+	// ByteBuffers General Purpose Pool
+	private final FastList<ByteBuffer> _bufferPool;
+	// Pending Close
+	private final NioNetStackList<MMOConnection<T>> _pendingClose;
+	
+	private boolean _shutdown;
+	
+	public SelectorThread(final SelectorConfig sc, final IMMOExecutor<T> executor, final IPacketHandler<T> packetHandler, final IClientFactory<T> clientFactory, final IAcceptFilter acceptFilter) throws IOException
+	{
+		super.setName("SelectorThread-" + super.getId());
+		
+		HELPER_BUFFER_SIZE = sc.HELPER_BUFFER_SIZE;
+		HELPER_BUFFER_COUNT = sc.HELPER_BUFFER_COUNT;
+		MAX_SEND_PER_PASS = sc.MAX_SEND_PER_PASS;
+		MAX_READ_PER_PASS = sc.MAX_READ_PER_PASS;
+		
+		SLEEP_TIME = sc.SLEEP_TIME;
+		
+		DIRECT_WRITE_BUFFER = ByteBuffer.allocateDirect(sc.WRITE_BUFFER_SIZE).order(BYTE_ORDER);
+		WRITE_BUFFER = ByteBuffer.wrap(new byte[sc.WRITE_BUFFER_SIZE]).order(BYTE_ORDER);
+		READ_BUFFER = ByteBuffer.wrap(new byte[sc.READ_BUFFER_SIZE]).order(BYTE_ORDER);
+		
+		STRING_BUFFER = new NioNetStringBuffer(64 * 1024);
+		
+		_pendingClose = new NioNetStackList<MMOConnection<T>>();
+		_bufferPool = new FastList<ByteBuffer>();
+		
+		for (int i = 0; i < HELPER_BUFFER_COUNT; i++)
+		{
+			_bufferPool.addLast(ByteBuffer.wrap(new byte[HELPER_BUFFER_SIZE]).order(BYTE_ORDER));
+		}
+		
+		_acceptFilter = acceptFilter;
+		_packetHandler = packetHandler;
+		_clientFactory = clientFactory;
+		_executor = executor;
+		_selector = Selector.open();
+	}
+	
+	public final void openServerSocket(InetAddress address, int tcpPort) throws IOException
+	{
+		ServerSocketChannel selectable = ServerSocketChannel.open();
+		selectable.configureBlocking(false);
+		
+		ServerSocket ss = selectable.socket();
+		
+		if (address == null)
+			ss.bind(new InetSocketAddress(tcpPort));
+		else
+			ss.bind(new InetSocketAddress(address, tcpPort));
+		
+		selectable.register(_selector, SelectionKey.OP_ACCEPT);
+	}
+	
+	final ByteBuffer getPooledBuffer()
+	{
+		if (_bufferPool.isEmpty())
+			return ByteBuffer.wrap(new byte[HELPER_BUFFER_SIZE]).order(BYTE_ORDER);
+		
+		return _bufferPool.removeFirst();
+	}
+	
+	final void recycleBuffer(final ByteBuffer buf)
+	{
+		if (_bufferPool.size() < HELPER_BUFFER_COUNT)
+		{
+			buf.clear();
+			_bufferPool.addLast(buf);
+		}
+	}
+	
+	@SuppressWarnings("unchecked")
+	@Override
+	public final void run()
+	{
+		int selectedKeysCount = 0;
+		
+		SelectionKey key;
+		MMOConnection<T> con;
+		
+		Iterator<SelectionKey> selectedKeys;
+		
+		while (!_shutdown)
+		{
+			try
+			{
+				selectedKeysCount = _selector.selectNow();
+			}
+			catch (IOException e)
+			{
+				e.printStackTrace();
+			}
+			
+			if (selectedKeysCount > 0)
+			{
+				selectedKeys = _selector.selectedKeys().iterator();
+				
+				while (selectedKeys.hasNext())
+				{
+					key = selectedKeys.next();
+					selectedKeys.remove();
+					
+					con = (MMOConnection<T>) key.attachment();
+					
+					switch (key.readyOps())
+					{
+						case SelectionKey.OP_CONNECT:
+							finishConnection(key, con);
+							break;
+						case SelectionKey.OP_ACCEPT:
+							acceptConnection(key, con);
+							break;
+						case SelectionKey.OP_READ:
+							readPacket(key, con);
+							break;
+						case SelectionKey.OP_WRITE:
+							writePacket(key, con);
+							break;
+						case SelectionKey.OP_READ | SelectionKey.OP_WRITE:
+							writePacket(key, con);
+							if (key.isValid())
+								readPacket(key, con);
+							break;
+					}
+				}
+			}
+			
+			synchronized (_pendingClose)
+			{
+				while (!_pendingClose.isEmpty())
+				{
+					con = _pendingClose.removeFirst();
+					writeClosePacket(con);
+					closeConnectionImpl(con.getSelectionKey(), con);
+				}
+			}
+			
+			try
+			{
+				Thread.sleep(SLEEP_TIME);
+			}
+			catch (InterruptedException e)
+			{
+				e.printStackTrace();
+			}
+		}
+		closeSelectorThread();
+	}
+	
+	private final void finishConnection(final SelectionKey key, final MMOConnection<T> con)
+	{
+		try
+		{
+			((SocketChannel) key.channel()).finishConnect();
+		}
+		catch (IOException e)
+		{
+			con.getClient().onForcedDisconnection();
+			closeConnectionImpl(key, con);
+		}
+		
+		// key might have been invalidated on finishConnect()
+		if (key.isValid())
+		{
+			key.interestOps(key.interestOps() | SelectionKey.OP_READ);
+			key.interestOps(key.interestOps() & ~SelectionKey.OP_CONNECT);
+		}
+	}
+	
+	private final void acceptConnection(final SelectionKey key, MMOConnection<T> con)
+	{
+		ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
+		SocketChannel sc;
+		
+		try
+		{
+			while ((sc = ssc.accept()) != null)
+			{
+				if (_acceptFilter == null || _acceptFilter.accept(sc))
+				{
+					sc.configureBlocking(false);
+					SelectionKey clientKey = sc.register(_selector, SelectionKey.OP_READ);
+					con = new MMOConnection<T>(this, sc.socket(), clientKey);
+					con.setClient(_clientFactory.create(con));
+					clientKey.attach(con);
+				}
+				else
+					sc.socket().close();
+			}
+		}
+		catch (IOException e)
+		{
+			e.printStackTrace();
+		}
+	}
+	
+	private final void readPacket(final SelectionKey key, final MMOConnection<T> con)
+	{
+		if (!con.isClosed())
+		{
+			ByteBuffer buf;
+			if ((buf = con.getReadBuffer()) == null)
+			{
+				buf = READ_BUFFER;
+			}
+			
+			// if we try to to do a read with no space in the buffer it will
+			// read 0 bytes
+			// going into infinite loop
+			if (buf.position() == buf.limit())
+				System.exit(0);
+			
+			int result = -2;
+			
+			try
+			{
+				result = con.read(buf);
+			}
+			catch (IOException e)
+			{
+				// error handling goes bellow
+			}
+			
+			if (result > 0)
+			{
+				buf.flip();
+				
+				final T client = con.getClient();
+				
+				for (int i = 0; i < MAX_READ_PER_PASS; i++)
+				{
+					if (!tryReadPacket(key, client, buf, con))
+						return;
+				}
+				
+				// only reachable if MAX_READ_PER_PASS has been reached
+				// check if there are some more bytes in buffer
+				// and allocate/compact to prevent content lose.
+				if (buf.remaining() > 0)
+				{
+					// did we use the READ_BUFFER ?
+					if (buf == READ_BUFFER)
+						// move the pending byte to the connections READ_BUFFER
+						allocateReadBuffer(con);
+					else
+						// move the first byte to the beginning :)
+						buf.compact();
+				}
+			}
+			else
+			{
+				switch (result)
+				{
+					case 0:
+					case -1:
+						closeConnectionImpl(key, con);
+						break;
+					case -2:
+						con.getClient().onForcedDisconnection();
+						closeConnectionImpl(key, con);
+						break;
+				}
+			}
+		}
+	}
+	
+	private final boolean tryReadPacket(final SelectionKey key, final T client, final ByteBuffer buf, final MMOConnection<T> con)
+	{
+		switch (buf.remaining())
+		{
+			case 0:
+				// buffer is full
+				// nothing to read
+				return false;
+			case 1:
+				// we don`t have enough data for header so we need to read
+				key.interestOps(key.interestOps() | SelectionKey.OP_READ);
+				
+				// did we use the READ_BUFFER ?
+				if (buf == READ_BUFFER)
+					// move the pending byte to the connections READ_BUFFER
+					allocateReadBuffer(con);
+				else
+					// move the first byte to the beginning :)
+					buf.compact();
+				return false;
+			default:
+				// data size excluding header size :>
+				final int dataPending = (buf.getShort() & 0xFFFF) - HEADER_SIZE;
+				
+				// do we got enough bytes for the packet?
+				if (dataPending <= buf.remaining())
+				{
+					// avoid parsing dummy packets (packets without body)
+					if (dataPending > 0)
+					{
+						final int pos = buf.position();
+						parseClientPacket(pos, buf, dataPending, client);
+						buf.position(pos + dataPending);
+					}
+					
+					// if we are done with this buffer
+					if (!buf.hasRemaining())
+					{
+						if (buf != READ_BUFFER)
+						{
+							con.setReadBuffer(null);
+							recycleBuffer(buf);
+						}
+						else
+						{
+							READ_BUFFER.clear();
+						}
+						return false;
+					}
+					return true;
+				}
+				else
+				{
+					// we don`t have enough bytes for the dataPacket so we need
+					// to read
+					key.interestOps(key.interestOps() | SelectionKey.OP_READ);
+					
+					// did we use the READ_BUFFER ?
+					if (buf == READ_BUFFER)
+					{
+						// move it`s position
+						buf.position(buf.position() - HEADER_SIZE);
+						// move the pending byte to the connections READ_BUFFER
+						allocateReadBuffer(con);
+					}
+					else
+					{
+						buf.position(buf.position() - HEADER_SIZE);
+						buf.compact();
+					}
+					return false;
+				}
+		}
+	}
+	
+	private final void allocateReadBuffer(final MMOConnection<T> con)
+	{
+		con.setReadBuffer(getPooledBuffer().put(READ_BUFFER));
+		READ_BUFFER.clear();
+	}
+	
+	private final void parseClientPacket(final int pos, final ByteBuffer buf, final int dataSize, final T client)
+	{
+		final boolean ret = client.decrypt(buf, dataSize);
+		
+		if (ret && buf.hasRemaining())
+		{
+			// apply limit
+			final int limit = buf.limit();
+			buf.limit(pos + dataSize);
+			final ReceivablePacket<T> cp = _packetHandler.handlePacket(buf, client);
+			
+			if (cp != null)
+			{
+				cp._buf = buf;
+				cp._sbuf = STRING_BUFFER;
+				cp._client = client;
+				
+				if (cp.read())
+					_executor.execute(cp);
+				
+				cp._buf = null;
+				cp._sbuf = null;
+			}
+			buf.limit(limit);
+		}
+	}
+	
+	private final void writeClosePacket(final MMOConnection<T> con)
+	{
+		SendablePacket<T> sp;
+		while ((sp = con.getSendQueue().removeFirst()) != null)
+		{
+			WRITE_BUFFER.clear();
+			
+			putPacketIntoWriteBuffer(con.getClient(), sp);
+			
+			WRITE_BUFFER.flip();
+			
+			try
+			{
+				con.write(WRITE_BUFFER);
+			}
+			catch (IOException e)
+			{
+				// error handling goes on the if bellow
+			}
+		}
+	}
+	
+	protected final void writePacket(final SelectionKey key, final MMOConnection<T> con)
+	{
+		if (!prepareWriteBuffer(con))
+		{
+			key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
+			return;
+		}
+		
+		DIRECT_WRITE_BUFFER.flip();
+		
+		final int size = DIRECT_WRITE_BUFFER.remaining();
+		
+		int result = -1;
+		
+		try
+		{
+			result = con.write(DIRECT_WRITE_BUFFER);
+		}
+		catch (IOException e)
+		{
+			// error handling goes on the if bellow
+		}
+		
+		// check if no error happened
+		if (result >= 0)
+		{
+			// check if we written everything
+			if (result == size)
+			{
+				// complete write
+				synchronized (con.getSendQueue())
+				{
+					if (con.getSendQueue().isEmpty() && !con.hasPendingWriteBuffer())
+					{
+						key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
+					}
+				}
+			}
+			else
+				// incomplete write
+				con.createWriteBuffer(DIRECT_WRITE_BUFFER);
+		}
+		else
+		{
+			con.getClient().onForcedDisconnection();
+			closeConnectionImpl(key, con);
+		}
+	}
+	
+	private final boolean prepareWriteBuffer(final MMOConnection<T> con)
+	{
+		boolean hasPending = false;
+		DIRECT_WRITE_BUFFER.clear();
+		
+		// if there is pending content add it
+		if (con.hasPendingWriteBuffer())
+		{
+			con.movePendingWriteBufferTo(DIRECT_WRITE_BUFFER);
+			hasPending = true;
+		}
+		
+		if (DIRECT_WRITE_BUFFER.remaining() > 1 && !con.hasPendingWriteBuffer())
+		{
+			final NioNetStackList<SendablePacket<T>> sendQueue = con.getSendQueue();
+			final T client = con.getClient();
+			SendablePacket<T> sp;
+			
+			for (int i = 0; i < MAX_SEND_PER_PASS; i++)
+			{
+				synchronized (con.getSendQueue())
+				{
+					if (sendQueue.isEmpty())
+						sp = null;
+					else
+						sp = sendQueue.removeFirst();
+				}
+				
+				if (sp == null)
+					break;
+				
+				hasPending = true;
+				
+				// put into WriteBuffer
+				putPacketIntoWriteBuffer(client, sp);
+				
+				WRITE_BUFFER.flip();
+				
+				if (DIRECT_WRITE_BUFFER.remaining() >= WRITE_BUFFER.limit())
+					DIRECT_WRITE_BUFFER.put(WRITE_BUFFER);
+				else
+				{
+					con.createWriteBuffer(WRITE_BUFFER);
+					break;
+				}
+			}
+		}
+		return hasPending;
+	}
+	
+	private final void putPacketIntoWriteBuffer(final T client, final SendablePacket<T> sp)
+	{
+		WRITE_BUFFER.clear();
+		
+		// reserve space for the size
+		final int headerPos = WRITE_BUFFER.position();
+		final int dataPos = headerPos + HEADER_SIZE;
+		WRITE_BUFFER.position(dataPos);
+		
+		// set the write buffer
+		sp._buf = WRITE_BUFFER;
+		// write content to buffer
+		sp.write();
+		// delete the write buffer
+		sp._buf = null;
+		
+		// size (inclusive header)
+		int dataSize = WRITE_BUFFER.position() - dataPos;
+		WRITE_BUFFER.position(dataPos);
+		client.encrypt(WRITE_BUFFER, dataSize);
+		
+		// recalculate size after encryption
+		dataSize = WRITE_BUFFER.position() - dataPos;
+		
+		WRITE_BUFFER.position(headerPos);
+		// write header
+		WRITE_BUFFER.putShort((short) (dataSize + HEADER_SIZE));
+		WRITE_BUFFER.position(dataPos + dataSize);
+	}
+	
+	final void closeConnection(final MMOConnection<T> con)
+	{
+		synchronized (_pendingClose)
+		{
+			_pendingClose.addLast(con);
+		}
+	}
+	
+	private final void closeConnectionImpl(final SelectionKey key, final MMOConnection<T> con)
+	{
+		try
+		{
+			// notify connection
+			con.getClient().onDisconnection();
+		}
+		finally
+		{
+			try
+			{
+				// close socket and the SocketChannel
+				con.close();
+			}
+			catch (IOException e)
+			{
+				// ignore, we are closing anyway
+			}
+			finally
+			{
+				con.releaseBuffers();
+				// clear attachment
+				key.attach(null);
+				// cancel key
+				key.cancel();
+			}
+		}
+	}
+	
+	public final void shutdown()
+	{
+		_shutdown = true;
+	}
+	
+	protected void closeSelectorThread()
+	{
+		for (final SelectionKey key : _selector.keys())
+		{
+			try
+			{
+				key.channel().close();
+			}
+			catch (IOException e)
+			{
+				// ignore
+			}
+		}
+		
+		try
+		{
+			_selector.close();
+		}
+		catch (IOException e)
+		{
+			// Ignore
+		}
+	}
+}

+ 62 - 63
MMOCore/src/org/mmocore/network/SendablePacket.java

@@ -21,67 +21,66 @@ package org.mmocore.network;
  * @author KenM
  * 
  */
-public abstract class SendablePacket<T extends MMOClient<?>> extends
-        AbstractPacket<T>
+public abstract class SendablePacket<T extends MMOClient<?>> extends AbstractPacket<T>
 {
-    protected final void putInt(final int value)
-    {
-        _buf.putInt(value);
-    }
-
-    protected final void putDouble(final double value)
-    {
-        _buf.putDouble(value);
-    }
-
-    protected final void putFloat(final float value)
-    {
-        _buf.putFloat(value);
-    }
-
-    protected final void writeC(final int data)
-    {
-        _buf.put((byte) data);
-    }
-
-    protected final void writeF(final double value)
-    {
-        _buf.putDouble(value);
-    }
-
-    protected final void writeH(final int value)
-    {
-        _buf.putShort((short) value);
-    }
-
-    protected final void writeD(final int value)
-    {
-        _buf.putInt(value);
-    }
-
-    protected final void writeQ(final long value)
-    {
-        _buf.putLong(value);
-    }
-
-    protected final void writeB(final byte[] data)
-    {
-        _buf.put(data);
-    }
-
-    protected final void writeS(final String text)
-    {
-        if (text != null)
-        {
-            final int len = text.length();
-            for (int i = 0; i < len; i++)
-            {
-                _buf.putChar(text.charAt(i));
-            }
-        }
-
-        _buf.putChar('\000');
-    }
-
-    protected abstract void write();
-}
+	protected final void putInt(final int value)
+	{
+		_buf.putInt(value);
+	}
+	
+	protected final void putDouble(final double value)
+	{
+		_buf.putDouble(value);
+	}
+	
+	protected final void putFloat(final float value)
+	{
+		_buf.putFloat(value);
+	}
+	
+	protected final void writeC(final int data)
+	{
+		_buf.put((byte) data);
+	}
+	
+	protected final void writeF(final double value)
+	{
+		_buf.putDouble(value);
+	}
+	
+	protected final void writeH(final int value)
+	{
+		_buf.putShort((short) value);
+	}
+	
+	protected final void writeD(final int value)
+	{
+		_buf.putInt(value);
+	}
+	
+	protected final void writeQ(final long value)
+	{
+		_buf.putLong(value);
+	}
+	
+	protected final void writeB(final byte[] data)
+	{
+		_buf.put(data);
+	}
+	
+	protected final void writeS(final String text)
+	{
+		if (text != null)
+		{
+			final int len = text.length();
+			for (int i = 0; i < len; i++)
+			{
+				_buf.putChar(text.charAt(i));
+			}
+		}
+		
+		_buf.putChar('\000');
+	}
+	
+	protected abstract void write();
+}