1 #include <unistd.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 
6 
7 #include "servership.h"
8 #include "thread.h"
9 #include "serverdata.h"
10 #include "servergame.h"
11 #include "netdata.h"
12 #include "netconfig.h"
13 #include "sounddefs.h"
14 #include "serversound.h"
15 
16 
17 extern ServerShip *ServerShips[MAX_PLAYERS];
18 extern ServerObject *ServerObjects[MAX_OBJECTS];
19 
20 
21 void *MainPlayerThread(void *threadid);
22 void SetupShipSendData(int shipnum, int threadnum, ShipDesc *ShipData);
23 void SetupObjSendData(int objnum, struct ObjectDesc *ObjData);
24 void SendPlayerData(size_t threadnum);
25 void SetupStatusSendData(char *GameStatus, int playernum);
26 void TransferData(char *SendData, int *DataSize, int threadnum);
27 
28 
MainPlayerThread(void * threadid)29 void *MainPlayerThread(void *threadid)
30 {
31   int n, rc;
32   size_t threadnum;
33   pthread_t readthread;
34 
35   threadnum=(size_t)threadid;
36 
37   SendPlayerData(threadnum);
38 
39   pthread_exit(NULL);
40 }
41 
42 
43 // Main function which loops and continuously sends data to the player
SendPlayerData(size_t threadnum)44 void SendPlayerData(size_t threadnum)
45 {
46   int i, j;
47   int DataSize=0;
48   char SendData[MAX_PACKET_SIZE];
49   char GameStatus[MAX_OBJECTS+MAX_PLAYERS+1];
50   struct ObjectDesc ObjData;
51   struct ShipDesc ShipData;
52 
53   while(!StopServer) {
54     pthread_mutex_lock(&ServerLock);
55 #ifdef DEBUG
56     printf("Main Player Thread %zd Awake\n", threadnum);
57 #endif
58     if (!ServerShips[threadnum]) {
59       pthread_mutex_unlock(&ServerLock);
60       break;
61     }
62 
63     // Send object data to player
64     for (i=0; i<MAX_OBJECTS; i++) {
65       if (ServerObjects[i]) {
66         *(SendData+DataSize)=OBJ_SEND_TYPE;
67         DataSize++;
68         SetupObjSendData(i, &ObjData);
69         memcpy(SendData+DataSize, &ObjData, sizeof(struct ObjectDesc));
70         DataSize+=sizeof(struct ObjectDesc);
71 
72         if (DataSize > PacketSize) {
73           TransferData(SendData, &DataSize, threadnum);
74         }
75       }
76     }
77 
78     // Send ship data to player
79     for (i=0; i<MAX_PLAYERS; i++) {
80       if (ServerShips[i]) {
81         *(SendData+DataSize)=SHIP_SEND_TYPE;
82         DataSize++;
83         SetupShipSendData(i, threadnum, &ShipData);
84         memcpy(SendData+DataSize, &ShipData, sizeof(struct ShipDesc));
85         DataSize+=sizeof(struct ShipDesc);
86       }
87 
88       if (DataSize > PacketSize) {
89         TransferData(SendData, &DataSize, threadnum);
90       }
91     }
92 
93 
94     // Send sound data to players
95     for (i=0; i<MAX_SOUNDS; i++) {
96       if (Sounds[threadnum][i].type!=-1) {
97         *(SendData+DataSize)=SOUND_SEND_TYPE;
98         DataSize++;
99         memcpy(SendData+DataSize, &Sounds[threadnum][i],
100                sizeof(SoundStruct));
101         DataSize+=sizeof(SoundStruct);
102         Sounds[threadnum][i].type=-1;
103       }
104 
105       if (DataSize > PacketSize) {
106         TransferData(SendData, &DataSize, threadnum);
107       }
108     }
109 
110     // Send general status update to player
111     SetupStatusSendData(GameStatus, threadnum);
112     *(SendData+DataSize)=STATUS_SEND_TYPE;
113     memcpy(SendData+DataSize+1, GameStatus, MAX_OBJECTS+MAX_PLAYERS+1);
114     DataSize+=MAX_OBJECTS+MAX_PLAYERS+1+1;
115     TransferData(SendData, &DataSize, threadnum);
116 
117 #ifdef DEBUG
118     printf("Main Player Thread %d Sleeping\n", threadnum);
119 #endif
120     pthread_mutex_unlock(&ServerLock);
121     usleep(NetSleepTime*1000);
122   }
123 }
124 
125 
SetupShipSendData(int shipnum,int threadnum,ShipDesc * ShipData)126 void SetupShipSendData(int shipnum, int threadnum, ShipDesc *ShipData)
127 {
128   ShipData->Number=shipnum;
129   memcpy(&ShipData->Position, &ServerShips[shipnum]->Position, sizeof(struct Point));
130   ShipData->Score=ServerShips[shipnum]->Score;
131   ShipData->Lives=ServerShips[shipnum]->Lives;
132   ShipData->Size=ServerShips[shipnum]->ObjectSize;
133   ShipData->ShieldOn=ServerShips[shipnum]->Action.shield && ServerShips[shipnum]->Shield;
134   strcpy(ShipData->PlayerName, ServerShips[shipnum]->PlayerName);
135   if (ServerShips[shipnum]->AliveTime==-1) {
136     ShipData->Alive=1;
137   } else {
138     ShipData->Alive=0;
139   }
140 
141   if (ServerShips[shipnum]->WarpTime) {
142     ShipData->Warping=1;
143   } else {
144     ShipData->Warping=0;
145   }
146 
147   if (shipnum==threadnum) {
148     ShipData->Shield=ServerShips[shipnum]->Shield;
149     ShipData->Armor=ServerShips[shipnum]->Armor;
150     ShipData->Warps=ServerShips[shipnum]->Warps;
151     ShipData->Nukes=ServerShips[shipnum]->Nukes;
152     if (ServerShips[shipnum]->ShakeTime) {
153       ShipData->Shaking=1;
154     } else {
155       ShipData->Shaking=0;
156     }
157     memcpy(&ShipData->RotationMatrix, &ServerShips[shipnum]->RotationMatrix, sizeof(float [3][3]));
158   } else {
159     ShipData->Shield=0;
160     ShipData->Armor=0;
161     ShipData->Shaking=0;
162     ShipData->Warps=0;
163     ShipData->Nukes=0;
164     memcpy(&ShipData->RotationMatrix, &ServerShips[shipnum]->InvRotationMatrix, sizeof(float [3][3]));
165   }
166 }
167 
168 
SetupObjSendData(int objnum,ObjectDesc * ObjData)169 void SetupObjSendData(int objnum, ObjectDesc *ObjData)
170 {
171   ObjData->Type=ServerObjects[objnum]->ObjectType;
172   ObjData->Number=objnum;
173   ObjData->Size=ServerObjects[objnum]->ObjectSize;
174   memcpy(&ObjData->Position, &ServerObjects[objnum]->Position, sizeof(struct Point));
175   memcpy(&ObjData->RotationMatrix, &ServerObjects[objnum]->RotationMatrix, sizeof(float [3][3]));
176 }
177 
178 
179 //
180 //  Function to send the status of each object and player,
181 //  whether they're alive or dead
182 //
SetupStatusSendData(char * GameStatus,int playernum)183 void SetupStatusSendData(char *GameStatus, int playernum)
184 {
185   int i, j;
186 
187   for (i=0; i<MAX_OBJECTS; i++) {
188     if (ServerObjects[i]) {
189       GameStatus[i]=1;
190     } else {
191       GameStatus[i]=0;
192     }
193   }
194   for (i=0; i<MAX_PLAYERS; i++) {
195     if (ServerShips[i]) {
196       GameStatus[i+MAX_OBJECTS]=1;
197     } else {
198       GameStatus[i+MAX_OBJECTS]=0;
199     }
200   }
201 
202   if (ServerGameRunning) {
203     GameStatus[MAX_OBJECTS+MAX_PLAYERS]=1;
204   } else {
205     GameStatus[MAX_OBJECTS+MAX_PLAYERS]=0;
206   }
207 }
208 
209 
TransferData(char * SendData,int * DataSize,int threadnum)210 void TransferData(char *SendData, int *DataSize, int threadnum)
211 {
212   int rc;
213 
214   if ((rc=sendto(listenfd, SendData, *DataSize, 0,
215                  (struct sockaddr *)&Connections[threadnum].PlayerIp,
216                  sizeof(struct sockaddr))) < 0) {
217     printf("write error\n");
218     if (MaxPlayers==1) {
219       StopServer=1;
220     }
221     if (ServerShips[threadnum]) {
222       DeletePlayer(threadnum);
223     }
224     pthread_mutex_unlock(&ServerLock);
225     pthread_exit(NULL);
226   }
227   *DataSize=0;
228 }
229