Added Communication Implementation.
[clanbomber-xamarin-client.git] / src / communication / ConnectionTest / ServerSimulator / Program.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Net;
5 using System.Net.Sockets;
6 using System.Text;
7 using System.Threading.Tasks;
8 using ConnectionTest;
9 using Newtonsoft.Json;
10
11
12
13 namespace ServerSimulator
14 {
15
16
17     class ServerSimulation
18     {
19
20         static void Main(string[] args)
21         {
22             ServerSimulation serverSimulation = new ServerSimulation();
23             serverSimulation.Start();
24         }
25
26
27         private void Print(string v)
28         {
29             //Comment for quit operation..
30             Console.WriteLine(v);
31         }
32
33
34
35         //////////////////////////////////////////>
36         /// Simulation stuff below
37         //////////////////////////////////////////>
38
39         GameSimulation m_gameSimulation = new GameSimulation();
40         class GameSimulation : TcpJsonConnection    //Specialize Client to have access to some Params and Types...
41         {
42             public GameSimulation() : base((field) => { }) { }
43
44
45             const int FieldSize = 20;
46             const double MoveLengthPerEvent = 1.0;  // We do not hold the state of players (like the server) in simulation, so we will only move when we get the event to do that..
47
48             //Run Simulation in this class.
49
50
51             public int c_ServerPort {get{ return c_serverPort; } }
52
53             List <double> playerXPos = new List<double>();
54             List <double> playerYPos = new List<double>();
55
56             List<double> bombXPos = new List<double>();
57             List<double> bombYPos = new List<double>();
58
59             public string CreateSendData(int ClientId)
60             {
61                 lock (playerXPos)
62                 {
63                     if (ClientId == playerXPos.Count)
64                     {
65                         playerXPos.Add(FieldSize / 2.0);
66                         playerYPos.Add(FieldSize / 2.0);
67                     }
68                 }
69
70                 ServerPackage pkg = new ServerPackage()
71                 {
72                     Id = ClientId,
73                     State = ServerPackage.ServerState.InGamePhase,
74                     Timeout = 4711,                    
75                 };
76                 lock (playerXPos)
77                 {
78                     for (int i = 0; i < playerXPos.Count; i++)
79                     {
80                         pkg.Players.Add(new ServerPackage.Player()
81                         {
82                             Id = i,
83                             Life = 50,
84                             X = playerXPos[i],
85                             Y = playerYPos[i],
86                         });
87                     }
88
89                     for (int i = 0; i < bombXPos.Count; i++)
90                     {
91                         pkg.Bombs.Add(new ServerPackage.Bomb()
92                         {
93                             Id = ClientId,
94                             Timeout = 4712,
95                             X = bombXPos[i],
96                             Y = bombYPos[i],
97                         });
98                     }
99                 }
100
101
102                 pkg.Bombs.Add(new ServerPackage.Bomb()
103                 {
104                     Id = ClientId,
105                     Timeout = 4712,
106                     X = 1,
107                     Y = FieldSize - 2,
108                 });
109
110                 pkg.Flames.Add(new ServerPackage.Flame()
111                 {
112                     Id = ClientId,
113                     Timeout = 4713,
114                     X = 1,
115                     Y = FieldSize - 3,
116                 });
117                 pkg.Flames.Add(new ServerPackage.Flame()
118                 {
119                     Id = ClientId,
120                     Timeout = 4713,
121                     X = 1,
122                     Y = FieldSize - 4,
123                 });
124
125                 pkg.Flames.Add(new ServerPackage.Flame()
126                 {
127                     Id = ClientId,
128                     Timeout = 4713,
129                     X = 2,
130                     Y = FieldSize - 2,
131                 });
132
133                 pkg.Flames.Add(new ServerPackage.Flame()
134                 {
135                     Id = ClientId,
136                     Timeout = 4713,
137                     X = 3,
138                     Y = FieldSize - 2,
139                 });
140
141
142
143                 for (int i = 0; i < FieldSize; i++)
144                 {
145                     pkg.Field.Add(new List<ServerPackage.FieldTypes>());
146                     pkg.Field[i].AddRange(Enumerable.Repeat(ServerPackage.FieldTypes.EmptyField, FieldSize));
147                 }
148
149                 for(int i = 0; i < FieldSize; i++)
150                 {
151                     pkg.Field[0][i] = ServerPackage.FieldTypes.StaticOrUndestroyableBlock;
152                     pkg.Field[i][0] = ServerPackage.FieldTypes.StaticOrUndestroyableBlock;
153                     pkg.Field[FieldSize-1][i] = ServerPackage.FieldTypes.StaticOrUndestroyableBlock;
154                     pkg.Field[i][FieldSize - 1] = ServerPackage.FieldTypes.StaticOrUndestroyableBlock;
155                 }
156
157                 pkg.Field[1][1] = ServerPackage.FieldTypes.DynamicOrDestroyableBlock;
158                 pkg.Field[1][2] = ServerPackage.FieldTypes.DynamicOrDestroyableBlock;
159
160                 pkg.Field[FieldSize - 2][FieldSize - 2] = ServerPackage.FieldTypes.ItemOrMoreBombs;
161                 pkg.Field[FieldSize - 2][FieldSize - 3] = ServerPackage.FieldTypes.ItemOrMoreBombs;
162
163
164                 return JsonConvert.SerializeObject(pkg, c_JsonStyle);
165             }
166
167             public void HandleClientPackage(string pkgString, int ClientId)
168             {
169                 ClientPackage pkg = JsonConvert.DeserializeObject<ClientPackage>(pkgString);
170
171                 while (ClientId >= playerXPos.Count) ;
172
173                 lock (playerXPos)
174                 {
175                     if (pkg.State == InputState.Down) playerYPos[ClientId] += MoveLengthPerEvent;
176                     if (pkg.State == InputState.Up) playerYPos[ClientId] -= MoveLengthPerEvent;
177                     if (pkg.State == InputState.Right) playerXPos[ClientId] += MoveLengthPerEvent;
178                     if (pkg.State == InputState.Left) playerXPos[ClientId] -= MoveLengthPerEvent;
179
180                     playerXPos[ClientId] = Math.Max(playerXPos[ClientId], 1);
181                     playerYPos[ClientId] = Math.Max(playerYPos[ClientId], 1);
182                     playerXPos[ClientId] = Math.Min(playerXPos[ClientId], FieldSize - 2);
183                     playerYPos[ClientId] = Math.Min(playerYPos[ClientId], FieldSize - 2);
184
185                     if(pkg.Bomb == InputBomb.PlaceBomb)
186                     {
187                         bombXPos.Add(playerXPos[ClientId]);
188                         bombYPos.Add(playerYPos[ClientId]);
189                     }
190                 }
191             }
192
193         }
194
195
196         //////////////////////////////////////////>
197         /// Socket stuff below
198         //////////////////////////////////////////>
199
200         const int c_ClientUpdateInterval = 500 /*ms*/;
201
202
203         bool Running = true;
204
205         List<Task> m_clientHandleTasks = new List<Task>();
206         List<Socket> m_clients = new List<Socket>();
207
208         void Start()
209         {
210             try
211                 {
212
213                 //////////////////////////////////////////////////
214                 //Start Receive Threads----------------------------
215
216                 Task Accept = new Task(new Action(AcceptLoop));
217                 Accept.Start();
218
219                 //////////////////////////////////////////////////
220                 // Periodic Send: --------------------------------
221                 while (Running)
222                 {
223                     lock (m_clients)
224                     {
225                         foreach (Socket sock in m_clients)
226                         {
227                             string sendData = m_gameSimulation.CreateSendData(GetClientId(sock));
228                             Print("Sending " + sendData);
229                             byte[] buffer = Encoding.ASCII.GetBytes(sendData + char.MinValue);
230                             SocketAsyncEventArgs e = new SocketAsyncEventArgs();
231                             e.SetBuffer(buffer, 0, buffer.Length);
232                             e.Completed += TransmissionToClientCompleted;
233                             sock.SendAsync(e);
234                         }
235                     }
236                     System.Threading.Thread.Sleep(c_ClientUpdateInterval);
237                 }
238             }
239             catch(Exception e)
240             {
241                 Running = false;
242                 Console.Error.WriteLine(e.ToString());
243             }
244         }
245
246         private void TransmissionToClientCompleted(object sender, SocketAsyncEventArgs e)
247         {
248             //Print(sender.GetHashCode());
249         }
250
251         void AcceptLoop()
252         {
253             Socket listener;
254
255             IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
256             IPAddress ipAddress = ipHostInfo.AddressList[0];
257             IPEndPoint localEndPoint = new IPEndPoint(ipAddress, m_gameSimulation.c_ServerPort);
258
259             // Create a TCP/IP socket.  
260             listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
261
262             // Bind the socket to the local endpoint and   
263             // listen for incoming connections.  
264             try
265             {
266                 listener.Bind(localEndPoint);
267                 listener.Listen(10);
268                 Print("Started listening for clients...");
269
270                 while (Running)
271                 {
272                     // Program is suspended while waiting for an incoming connection.  
273                     Socket handler = listener.Accept();
274                     Print("Accepted new client!");
275
276                     Task clientHandleTask = new Task(()=>
277                     {
278                         ReceiveLoop(handler);
279                     });
280                     clientHandleTask.Start();
281
282                     m_clientHandleTasks.Add(clientHandleTask);
283
284                     lock (m_clients)
285                     {
286                         m_clients.Add(handler);
287                     }
288
289                 }
290             }
291             catch (Exception e)
292             {
293                 Console.Error.WriteLine(e.ToString());
294             }
295             finally
296             {
297                 try
298                 {
299                     listener.Shutdown(SocketShutdown.Both);
300                     listener.Close();
301                 }
302                 catch (Exception e) { Console.Error.WriteLine("Note: Failed to shutdown socket properly. " + e); }
303
304                 Running = false;
305             }
306         }
307
308
309
310         void ReceiveLoop(Socket handler)
311         {
312             try
313             {
314                 string restFromPreviousReception = "";
315                 while (Running)
316                 {
317                     string[] recvPkgs = null;
318
319                     {
320                         // Incoming data from the client.  
321                         string data = null;
322                         byte[] bytes = new Byte[1024];
323                         while (Running)
324                         {
325                             int bytesRec = handler.Receive(bytes);
326                             data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
327                             if (data.Contains('\0'))
328                             {
329                                 string msgWithRestFromPrecedingMsg = restFromPreviousReception + data;
330                                 recvPkgs = msgWithRestFromPrecedingMsg.Split('\0');
331                                 restFromPreviousReception = "";
332                                 if(recvPkgs[recvPkgs.Length-1] != "")
333                                 {
334                                     restFromPreviousReception = recvPkgs[recvPkgs.Length - 1];
335                                 }
336
337                                 break;
338                             }
339                         }
340                     }
341
342
343                     // Show the data on the console and forward to handler
344                     for (int i = 0; i < recvPkgs.Length; i++)
345                     {
346                         if (recvPkgs[i].Length > 0) // Filter '\0' strings..
347                         {                           
348                             Print("Text received : " + recvPkgs[i]);
349                             m_gameSimulation.HandleClientPackage(recvPkgs[i], GetClientId(handler));
350                         }
351                         
352                     }
353                 }
354
355             }
356             catch (SocketException)
357             {
358                 Print("Connection closed by Client. ");
359             }
360             catch (Exception e)
361             {
362                 Console.Error.WriteLine(e.ToString());
363                 Running = false;
364             }
365             finally
366             {
367                 try
368                 {
369                     handler.Shutdown(SocketShutdown.Both);
370                     handler.Close();
371                 }
372                 catch (Exception e) { Console.Error.WriteLine("Note: Failed to shutdown socket properly. " + e); }
373                 lock (m_clients)
374                 {
375                     m_clients.Remove(handler);
376                 }
377             }
378
379             //Terminating Task..
380         }
381
382
383
384         int GetClientId(Socket clientSock)
385         {
386             int id;
387             lock (m_clients)
388             {
389                 id =  m_clients.IndexOf(clientSock);
390             }
391             return id;
392         }
393
394     }
395
396 }