diff --git a/gemp-lotr/gemp-lotr-async/pom.xml b/gemp-lotr/gemp-lotr-async/pom.xml
new file mode 100644
index 000000000..4717560c7
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-async/pom.xml
@@ -0,0 +1,25 @@
+
+
+
+ gemp-lotr
+ com.gempukku.lotro
+ 1.0-SNAPSHOT
+
+ 4.0.0
+ com.gempukku.lotro
+ gemp-lotr-async
+ 1.0-SNAPSHOT
+
+
+ ${project.groupId}
+ gemp-lotr-web-server
+ ${project.version}
+
+
+ io.netty
+ netty
+ 3.6.1.Final
+
+
+
\ No newline at end of file
diff --git a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/HttpRequestHandler.java b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/HttpRequestHandler.java
new file mode 100644
index 000000000..6867f0eba
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/HttpRequestHandler.java
@@ -0,0 +1,104 @@
+package com.gempukku.lotro.async;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.*;
+import org.jboss.netty.handler.codec.http.*;
+import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH;
+import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;
+import static org.jboss.netty.handler.codec.http.HttpHeaders.is100ContinueExpected;
+import static org.jboss.netty.handler.codec.http.HttpHeaders.isKeepAlive;
+import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
+import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1;
+import org.jboss.netty.util.CharsetUtil;
+
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Map;
+
+public class HttpRequestHandler extends SimpleChannelUpstreamHandler {
+
+ private HttpRequest _request;
+ private boolean _readingChunks;
+ private String _uri;
+ private Map _objects;
+
+ public HttpRequestHandler(Map objects) {
+ _objects = objects;
+ }
+
+ @Override
+ public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
+ _request = (HttpRequest) e.getMessage();
+
+ if (is100ContinueExpected(_request)) {
+ send100Continue(e);
+ }
+
+ String uri = _request.getUri();
+
+ if (uri.indexOf("?")>-1)
+ _uri = uri.substring(0, uri.indexOf("?"));
+ else
+ _uri = uri;
+
+ QueryStringDecoder queryStringDecoder = new QueryStringDecoder(_request.getUri());
+ Map> queryStringParams = queryStringDecoder.getParameters();
+
+ HttpMethod httpMethod = _request.getMethod();
+
+ if (_request.isChunked()) {
+ send400Error(e);
+ } else {
+ ChannelBuffer content = _request.getContent();
+ if (content.readable()) {
+ }
+ writeResponse(e);
+ }
+ }
+
+ private void writeResponse(MessageEvent e) {
+ // Decide whether to close the connection or not.
+ boolean keepAlive = isKeepAlive(_request);
+
+ // Build the response object.
+ HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
+ response.setContent(ChannelBuffers.copiedBuffer("Response: " + _uri, CharsetUtil.UTF_8));
+ response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8");
+
+ if (keepAlive) {
+ // Add 'Content-Length' header only for a keep-alive connection.
+ response.setHeader(CONTENT_LENGTH, response.getContent().readableBytes());
+ }
+
+ // Write the response.
+ ChannelFuture future = e.getChannel().write(response);
+
+ // Close the non-keep-alive connection after the write operation is done.
+ if (!keepAlive) {
+ future.addListener(ChannelFutureListener.CLOSE);
+ }
+ }
+
+ private void send400Error(MessageEvent e) {
+ boolean keepAlive = isKeepAlive(_request);
+
+ HttpResponse response = new DefaultHttpResponse(HTTP_1_1, BAD_REQUEST);
+ ChannelFuture future = e.getChannel().write(response);
+ if (!keepAlive) {
+ future.addListener(ChannelFutureListener.CLOSE);
+ }
+ }
+
+ private void send100Continue(MessageEvent e) {
+ HttpResponse response = new DefaultHttpResponse(HTTP_1_1, CONTINUE);
+ e.getChannel().write(response);
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
+ throws Exception {
+ e.getCause().printStackTrace();
+ e.getChannel().close();
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/HttpServerPipelineFactory.java b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/HttpServerPipelineFactory.java
new file mode 100644
index 000000000..e5f23336d
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/HttpServerPipelineFactory.java
@@ -0,0 +1,44 @@
+package com.gempukku.lotro.async;
+
+import com.gempukku.lotro.packs.PacksStorage;
+import com.gempukku.lotro.server.provider.DaoBuilder;
+import com.gempukku.lotro.server.provider.PacksStorageBuilder;
+import com.gempukku.lotro.server.provider.ServerBuilder;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.handler.codec.http.HttpContentCompressor;
+import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
+import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
+
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+
+public class HttpServerPipelineFactory implements ChannelPipelineFactory {
+ public ChannelPipeline getPipeline() throws Exception {
+ // Create a default pipeline implementation.
+ ChannelPipeline pipeline = Channels.pipeline();
+
+ // Uncomment the following line if you want HTTPS
+ //SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
+ //engine.setUseClientMode(false);
+ //pipeline.addLast("ssl", new SslHandler(engine));
+
+ pipeline.addLast("decoder", new HttpRequestDecoder());
+ // Uncomment the following line if you don't want to handle HttpChunks.
+ //pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));
+ pipeline.addLast("encoder", new HttpResponseEncoder());
+ // Remove the following line if you don't want automatic content compression.
+ pipeline.addLast("deflater", new HttpContentCompressor());
+
+ Map objects = new HashMap();
+ objects.put(PacksStorage.class, PacksStorageBuilder.createPacksStorage());
+ DaoBuilder.fillObjectMap(objects);
+ ServerBuilder.fillObjectMap(objects);
+ ServerBuilder.constructObjects(objects);
+
+ pipeline.addLast("handler", new HttpRequestHandler(objects));
+ return pipeline;
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/LotroAsyncServer.java b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/LotroAsyncServer.java
new file mode 100644
index 000000000..091832203
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/LotroAsyncServer.java
@@ -0,0 +1,26 @@
+package com.gempukku.lotro.async;
+
+import org.jboss.netty.bootstrap.ServerBootstrap;
+import org.jboss.netty.channel.ChannelFactory;
+import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
+
+import java.net.InetSocketAddress;
+import java.util.concurrent.Executors;
+
+public class LotroAsyncServer {
+ public static void main(String[] server) {
+ ChannelFactory factory =
+ new NioServerSocketChannelFactory(
+ Executors.newCachedThreadPool(),
+ Executors.newCachedThreadPool());
+
+
+ ServerBootstrap bootstrap = new ServerBootstrap(factory);
+
+ bootstrap.setPipelineFactory(new HttpServerPipelineFactory());
+
+ bootstrap.setOption("child.tcpNoDelay", true);
+ bootstrap.setOption("child.keepAlive", true);
+ bootstrap.bind(new InetSocketAddress(8080));
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameEvent.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameEvent.java
index 870dc3883..1467f36fa 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameEvent.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameEvent.java
@@ -7,6 +7,7 @@ import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.logic.decisions.AwaitingDecision;
import com.gempukku.lotro.logic.timing.GameStats;
+import java.util.Date;
import java.util.List;
public class GameEvent {
@@ -18,9 +19,10 @@ public class GameEvent {
AT, RT,
M, W,
GS,
- CAC, EP, CA, D
+ CAC, EP, CA, D, CH
}
+ private Date _date;
private String _message;
private String _side;
private Type _type;
@@ -43,6 +45,15 @@ public class GameEvent {
_type = type;
}
+ public Date getDate() {
+ return _date;
+ }
+
+ public GameEvent date(Date date) {
+ _date = date;
+ return this;
+ }
+
public Integer getIndex() {
return _index;
}