001 package com.croftsoft.apps.mars.net;
002
003 import java.io.*;
004 import java.net.*;
005 import java.util.*;
006
007 import com.croftsoft.core.io.SerializableCoder;
008 import com.croftsoft.core.lang.NullArgumentException;
009 import com.croftsoft.core.lang.lifecycle.Lifecycle;
010 import com.croftsoft.core.math.MathConstants;
011 import com.croftsoft.core.net.http.msg.HttpMessageClient;
012 import com.croftsoft.core.util.NullIterator;
013 import com.croftsoft.core.util.consumer.Consumer;
014
015 import com.croftsoft.apps.mars.model.GameAccessor;
016 import com.croftsoft.apps.mars.model.NullGameAccessor;
017 import com.croftsoft.apps.mars.model.TankAccessor;
018 import com.croftsoft.apps.mars.model.WorldAccessor;
019 import com.croftsoft.apps.mars.net.request.ViewRequest;
020
021 /*********************************************************************
022 * Network synchronizer.
023 *
024 * @version
025 * 2003-06-02
026 * @since
027 * 2003-04-06
028 * @author
029 * <a href="https://www.croftsoft.com/">David Wallace Croft</a>
030 *********************************************************************/
031
032 public final class Synchronizer
033 implements GameAccessor, Lifecycle
034 //////////////////////////////////////////////////////////////////////
035 //////////////////////////////////////////////////////////////////////
036 {
037
038 private static final String DEFAULT_HOST = "localhost";
039
040 private static final int DEFAULT_PORT = 8080;
041
042 private static final String SERVLET_PATH = "servlet";
043
044 private static final String DEFAULT_PATH = "/mars/" + SERVLET_PATH;
045
046 private static final String USER_AGENT = "CroftSoft Mars";
047
048 private static final String CONTENT_TYPE
049 = "application/octet-stream";
050
051 private static final long POLLING_PERIOD_MIN
052 = 100;
053
054 private static final long POLLING_PERIOD_MAX
055 = MathConstants.MILLISECONDS_PER_DAY;
056
057 private static final long POLLING_PERIOD_INIT
058 = POLLING_PERIOD_MIN;
059
060 private static final double POLLING_PERIOD_MULT
061 = 2.0;
062
063 private static final double POLLING_PERIOD_DIVI
064 = Double.POSITIVE_INFINITY;
065
066 private static final long POLLING_PERIOD_INCR
067 = MathConstants.MILLISECONDS_PER_SECOND;
068
069 //
070
071 private final HttpMessageClient httpMessageClient;
072
073 //
074
075 private GameAccessor gameAccessor;
076
077 private int level;
078
079 //////////////////////////////////////////////////////////////////////
080 //////////////////////////////////////////////////////////////////////
081
082 public Synchronizer (
083 String playerName,
084 URL codeBaseURL )
085 throws IOException, MalformedURLException
086 //////////////////////////////////////////////////////////////////////
087 {
088 NullArgumentException.check ( playerName );
089
090 URL servletURL = null;
091
092 if ( codeBaseURL != null )
093 {
094 servletURL = new URL ( codeBaseURL, SERVLET_PATH );
095 }
096 else
097 {
098 servletURL
099 = new URL ( "http", DEFAULT_HOST, DEFAULT_PORT, DEFAULT_PATH );
100 }
101
102 httpMessageClient = new HttpMessageClient (
103 servletURL,
104 USER_AGENT,
105 SerializableCoder.INSTANCE,
106 SerializableCoder.INSTANCE,
107 CONTENT_TYPE,
108 SerializableCoder.INSTANCE.encode (
109 new ViewRequest ( playerName ) ),
110 new Consumer ( )
111 {
112 public void consume ( Object o )
113 {
114 Synchronizer.this.consume ( o );
115 }
116 },
117 POLLING_PERIOD_MIN,
118 POLLING_PERIOD_MAX,
119 POLLING_PERIOD_INIT,
120 POLLING_PERIOD_MULT,
121 POLLING_PERIOD_DIVI,
122 POLLING_PERIOD_INCR );
123
124 gameAccessor = NullGameAccessor.INSTANCE;
125 }
126
127 //////////////////////////////////////////////////////////////////////
128 //////////////////////////////////////////////////////////////////////
129
130 public void replace ( Object o )
131 //////////////////////////////////////////////////////////////////////
132 {
133 httpMessageClient.replace ( o );
134 }
135
136 //////////////////////////////////////////////////////////////////////
137 // interface GameAccessor methods
138 //////////////////////////////////////////////////////////////////////
139
140 public int getLevel ( )
141 //////////////////////////////////////////////////////////////////////
142 {
143 return level;
144 }
145
146 public Iterator getPath ( )
147 //////////////////////////////////////////////////////////////////////
148 {
149 return NullIterator.INSTANCE;
150 }
151
152 public TankAccessor getPlayerTankAccessor ( )
153 //////////////////////////////////////////////////////////////////////
154 {
155 return gameAccessor.getPlayerTankAccessor ( );
156 }
157
158 public WorldAccessor getWorldAccessor ( )
159 //////////////////////////////////////////////////////////////////////
160 {
161 return gameAccessor.getWorldAccessor ( );
162 }
163
164 //////////////////////////////////////////////////////////////////////
165 // interface Lifecycle methods
166 //////////////////////////////////////////////////////////////////////
167
168 public void init ( )
169 //////////////////////////////////////////////////////////////////////
170 {
171 httpMessageClient.init ( );
172 }
173
174 public void start ( )
175 //////////////////////////////////////////////////////////////////////
176 {
177 httpMessageClient.start ( );
178 }
179
180 public void stop ( )
181 //////////////////////////////////////////////////////////////////////
182 {
183 httpMessageClient.stop ( );
184 }
185
186 public void destroy ( )
187 //////////////////////////////////////////////////////////////////////
188 {
189 httpMessageClient.destroy ( );
190 }
191
192 //////////////////////////////////////////////////////////////////////
193 // private methods
194 //////////////////////////////////////////////////////////////////////
195
196 private void consume ( Object o )
197 //////////////////////////////////////////////////////////////////////
198 {
199 gameAccessor = ( GameAccessor ) o;
200
201 level++;
202 }
203
204 //////////////////////////////////////////////////////////////////////
205 //////////////////////////////////////////////////////////////////////
206 }