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         }