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