56 [NSThread detachNewThreadSelector:usage toTarget:self withObject:nil]; |
56 [NSThread detachNewThreadSelector:usage toTarget:self withObject:nil]; |
57 } |
57 } |
58 |
58 |
59 // wrapper that computes the length of the message and then sends the command string |
59 // wrapper that computes the length of the message and then sends the command string |
60 -(int) sendToEngine: (NSString *)string { |
60 -(int) sendToEngine: (NSString *)string { |
61 unsigned char length = [string length]; |
61 uint8_t length = [string length]; |
62 |
62 |
63 SDLNet_TCP_Send(csd, &length , 1); |
63 SDLNet_TCP_Send(csd, &length , 1); |
64 return SDLNet_TCP_Send(csd, [string UTF8String], length); |
64 return SDLNet_TCP_Send(csd, [string UTF8String], length); |
65 } |
65 } |
66 |
66 |
67 // unpacks team data from the team.plist to a sequence of commands for engine |
67 // unpacks team data from the selected team.plist to a sequence of engine commands |
68 -(void) sendTeamData:(NSString *)fileName withPlayingHogs:(NSInteger) playingHogs ofColor:(NSNumber *)color{ |
68 -(void) provideTeamData:(NSString *)teamName forHogs:(NSInteger) numberOfPlayingHogs withHealth:(NSInteger) initialHealth ofColor:(NSNumber *)teamColor { |
69 NSString *teamFile = [[NSString alloc] initWithFormat:@"%@/%@", TEAMS_DIRECTORY(), fileName]; |
69 /* |
|
70 addteam <32charsMD5hash> <color> <team name> |
|
71 addhh <level> <health> <hedgehog name> |
|
72 <level> is 0 for human, 1-5 for bots (5 is the most stupid) |
|
73 */ |
|
74 |
|
75 NSString *teamFile = [[NSString alloc] initWithFormat:@"%@/%@", TEAMS_DIRECTORY(), teamName]; |
70 NSDictionary *teamData = [[NSDictionary alloc] initWithContentsOfFile:teamFile]; |
76 NSDictionary *teamData = [[NSDictionary alloc] initWithContentsOfFile:teamFile]; |
71 [teamFile release]; |
77 [teamFile release]; |
72 |
78 |
73 NSString *teamHashColorAndName = [[NSString alloc] initWithFormat:@"eaddteam %@ %@ %@", [teamData objectForKey:@"hash"], [color stringValue], [teamData objectForKey:@"teamname"]]; |
79 NSString *teamHashColorAndName = [[NSString alloc] initWithFormat:@"eaddteam %@ %@ %@", |
|
80 [teamData objectForKey:@"hash"], [teamColor stringValue], [teamData objectForKey:@"teamname"]]; |
74 [self sendToEngine: teamHashColorAndName]; |
81 [self sendToEngine: teamHashColorAndName]; |
75 [teamHashColorAndName release]; |
82 [teamHashColorAndName release]; |
76 |
83 |
77 NSString *grave = [[NSString alloc] initWithFormat:@"egrave %@", [teamData objectForKey:@"grave"]]; |
84 NSString *grave = [[NSString alloc] initWithFormat:@"egrave %@", [teamData objectForKey:@"grave"]]; |
78 [self sendToEngine: grave]; |
85 [self sendToEngine: grave]; |
89 NSString *flag = [[NSString alloc] initWithFormat:@"eflag %@", [teamData objectForKey:@"flag"]]; |
96 NSString *flag = [[NSString alloc] initWithFormat:@"eflag %@", [teamData objectForKey:@"flag"]]; |
90 [self sendToEngine: flag]; |
97 [self sendToEngine: flag]; |
91 [flag release]; |
98 [flag release]; |
92 |
99 |
93 NSArray *hogs = [teamData objectForKey:@"hedgehogs"]; |
100 NSArray *hogs = [teamData objectForKey:@"hedgehogs"]; |
94 for (int i = 0; i < playingHogs; i++) { |
101 for (int i = 0; i < numberOfPlayingHogs; i++) { |
95 NSDictionary *hog = [hogs objectAtIndex:i]; |
102 NSDictionary *hog = [hogs objectAtIndex:i]; |
96 |
103 |
97 NSString *hogLevelHealthAndName = [[NSString alloc] initWithFormat:@"eaddhh %@ %@ %@", [hog objectForKey:@"level"], [hog objectForKey:@"health"], [hog objectForKey:@"hogname"]]; |
104 NSString *hogLevelHealthAndName = [[NSString alloc] initWithFormat:@"eaddhh %@ %d %@", |
|
105 [hog objectForKey:@"level"], initialHealth, [hog objectForKey:@"hogname"]]; |
98 [self sendToEngine: hogLevelHealthAndName]; |
106 [self sendToEngine: hogLevelHealthAndName]; |
99 [hogLevelHealthAndName release]; |
107 [hogLevelHealthAndName release]; |
100 |
108 |
101 NSString *hogHat = [[NSString alloc] initWithFormat:@"ehat %@", [hog objectForKey:@"hat"]]; |
109 NSString *hogHat = [[NSString alloc] initWithFormat:@"ehat %@", [hog objectForKey:@"hat"]]; |
102 [self sendToEngine: hogHat]; |
110 [self sendToEngine: hogHat]; |
104 } |
112 } |
105 |
113 |
106 [teamData release]; |
114 [teamData release]; |
107 } |
115 } |
108 |
116 |
109 // unpacks ammodata from the ammo.plist to a sequence of commands for engine |
117 // unpacks ammostore data from the selected ammo.plist to a sequence of engine commands |
110 -(void) sendAmmoData:(NSDictionary *)ammoData forTeams: (NSInteger)numberPlaying { |
118 -(void) provideAmmoData:(NSString *)ammostoreName forPlayingTeams:(NSInteger) numberOfTeams { |
|
119 |
|
120 //NSDictionary *ammoData = [[NSDictionary alloc] initWithContentsOfFile:ammoDataFile]; |
|
121 NSDictionary *ammoData = [[NSDictionary alloc] initWithObjectsAndKeys: |
|
122 @"9391929422199121032235111001201000000211190911",@"ammostore_initialqt", |
|
123 @"0405040541600655546554464776576666666155501000",@"ammostore_probability", |
|
124 @"0000000000000205500000040007004000000000200000",@"ammostore_delay", |
|
125 @"1311110312111111123114111111111111111211101111",@"ammostore_crate", nil]; |
|
126 |
|
127 |
111 NSString *ammloadt = [[NSString alloc] initWithFormat:@"eammloadt %@", [ammoData objectForKey:@"ammostore_initialqt"]]; |
128 NSString *ammloadt = [[NSString alloc] initWithFormat:@"eammloadt %@", [ammoData objectForKey:@"ammostore_initialqt"]]; |
112 [self sendToEngine: ammloadt]; |
129 [self sendToEngine: ammloadt]; |
113 [ammloadt release]; |
130 [ammloadt release]; |
114 |
131 |
115 NSString *ammdelay = [[NSString alloc] initWithFormat:@"eammprob %@", [ammoData objectForKey:@"ammostore_probability"]]; |
132 NSString *ammprob = [[NSString alloc] initWithFormat:@"eammprob %@", [ammoData objectForKey:@"ammostore_probability"]]; |
|
133 [self sendToEngine: ammprob]; |
|
134 [ammprob release]; |
|
135 |
|
136 NSString *ammdelay = [[NSString alloc] initWithFormat:@"eammdelay %@", [ammoData objectForKey:@"ammostore_delay"]]; |
116 [self sendToEngine: ammdelay]; |
137 [self sendToEngine: ammdelay]; |
117 [ammdelay release]; |
138 [ammdelay release]; |
118 |
|
119 NSString *ammprob = [[NSString alloc] initWithFormat:@"eammdelay %@", [ammoData objectForKey:@"ammostore_delay"]]; |
|
120 [self sendToEngine: ammprob]; |
|
121 [ammprob release]; |
|
122 |
139 |
123 NSString *ammreinf = [[NSString alloc] initWithFormat:@"eammreinf %@", [ammoData objectForKey:@"ammostore_crate"]]; |
140 NSString *ammreinf = [[NSString alloc] initWithFormat:@"eammreinf %@", [ammoData objectForKey:@"ammostore_crate"]]; |
124 [self sendToEngine: ammreinf]; |
141 [self sendToEngine: ammreinf]; |
125 [ammreinf release]; |
142 [ammreinf release]; |
126 |
143 |
127 // sent twice so it applies to both teams |
144 // sent twice so it applies to both teams |
128 NSString *ammstore = [[NSString alloc] initWithString:@"eammstore"]; |
145 NSString *ammstore = [[NSString alloc] initWithString:@"eammstore"]; |
129 for (int i = 0; i < numberPlaying; i++) |
146 for (int i = 0; i < numberOfTeams; i++) |
130 [self sendToEngine: ammstore]; |
147 [self sendToEngine: ammstore]; |
131 [ammstore release]; |
148 [ammstore release]; |
|
149 |
|
150 [ammoData release]; |
|
151 } |
|
152 |
|
153 // unpacks scheme data from the selected scheme.plist to a sequence of engine commands |
|
154 -(NSInteger) provideScheme:(NSString *)schemeName { |
|
155 NSString *schemePath = [[NSString alloc] initWithFormat:@"%@/%@.plist",SCHEMES_DIRECTORY(),schemeName]; |
|
156 NSArray *scheme = [[NSArray alloc] initWithContentsOfFile:schemePath]; |
|
157 int result = 0; |
|
158 int i = 0; |
|
159 |
|
160 if ([[scheme objectAtIndex:i++] boolValue]) |
|
161 result |= 0x01; |
|
162 if ([[scheme objectAtIndex:i++] boolValue]) |
|
163 result |= 0x10; |
|
164 if ([[scheme objectAtIndex:i++] boolValue]) |
|
165 result |= 0x04; |
|
166 if ([[scheme objectAtIndex:i++] boolValue]) |
|
167 result |= 0x08; |
|
168 if ([[scheme objectAtIndex:i++] boolValue]) |
|
169 result |= 0x20; |
|
170 if ([[scheme objectAtIndex:i++] boolValue]) |
|
171 result |= 0x40; |
|
172 if ([[scheme objectAtIndex:i++] boolValue]) |
|
173 result |= 0x80; |
|
174 if ([[scheme objectAtIndex:i++] boolValue]) |
|
175 result |= 0x100; |
|
176 if ([[scheme objectAtIndex:i++] boolValue]) |
|
177 result |= 0x200; |
|
178 if ([[scheme objectAtIndex:i++] boolValue]) |
|
179 result |= 0x400; |
|
180 if ([[scheme objectAtIndex:i++] boolValue]) |
|
181 result |= 0x800; |
|
182 if ([[scheme objectAtIndex:i++] boolValue]) |
|
183 result |= 0x2000; |
|
184 if ([[scheme objectAtIndex:i++] boolValue]) |
|
185 result |= 0x4000; |
|
186 if ([[scheme objectAtIndex:i++] boolValue]) |
|
187 result |= 0x8000; |
|
188 if ([[scheme objectAtIndex:i++] boolValue]) |
|
189 result |= 0x10000; |
|
190 if ([[scheme objectAtIndex:i++] boolValue]) |
|
191 result |= 0x20000; |
|
192 if ([[scheme objectAtIndex:i++] boolValue]) |
|
193 result |= 0x80000; |
|
194 |
|
195 NSString *flags = [[NSString alloc] initWithFormat:@"e$gmflags %d",result]; |
|
196 [self sendToEngine:flags]; |
|
197 [flags release]; |
|
198 |
|
199 NSString *dmgMod = [[NSString alloc] initWithFormat:@"e$damagepct %d",[[scheme objectAtIndex:i++] intValue]]; |
|
200 [self sendToEngine:dmgMod]; |
|
201 [dmgMod release]; |
|
202 |
|
203 NSString *turnTime = [[NSString alloc] initWithFormat:@"e$turntime %d",[[scheme objectAtIndex:i++] intValue] * 1000]; |
|
204 [self sendToEngine:turnTime]; |
|
205 [turnTime release]; |
|
206 |
|
207 result = [[scheme objectAtIndex:i++] intValue]; // initial health |
|
208 |
|
209 NSString *sdTime = [[NSString alloc] initWithFormat:@"e$sd_turns %d",[[scheme objectAtIndex:i++] intValue]]; |
|
210 [self sendToEngine:sdTime]; |
|
211 [sdTime release]; |
|
212 |
|
213 NSString *crateDrops = [[NSString alloc] initWithFormat:@"e$casefreq %d",[[scheme objectAtIndex:i++] intValue]]; |
|
214 [self sendToEngine:crateDrops]; |
|
215 [crateDrops release]; |
|
216 |
|
217 NSString *minesTime = [[NSString alloc] initWithFormat:@"e$minestime %d",[[scheme objectAtIndex:i++] intValue] * 1000]; |
|
218 [self sendToEngine:minesTime]; |
|
219 [minesTime release]; |
|
220 |
|
221 NSString *minesNumber = [[NSString alloc] initWithFormat:@"e$landadds %d",[[scheme objectAtIndex:i++] intValue]]; |
|
222 [self sendToEngine:minesNumber]; |
|
223 [minesNumber release]; |
|
224 |
|
225 |
|
226 NSString *dudMines = [[NSString alloc] initWithFormat:@"e$minedudpct %d",[[scheme objectAtIndex:i++] intValue]]; |
|
227 [self sendToEngine:dudMines]; |
|
228 [dudMines release]; |
|
229 |
|
230 NSString *explosives = [[NSString alloc] initWithFormat:@"e$explosives %d",[[scheme objectAtIndex:i++] intValue]]; |
|
231 [self sendToEngine:explosives]; |
|
232 [explosives release]; |
|
233 |
|
234 return result; |
132 } |
235 } |
133 |
236 |
134 // method that handles net setup with engine and keeps connection alive |
237 // method that handles net setup with engine and keeps connection alive |
135 -(void) engineProtocol { |
238 -(void) engineProtocol { |
136 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
239 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
137 IPaddress ip; |
240 IPaddress ip; |
138 int eProto; |
241 int eProto; |
139 BOOL clientQuit, serverQuit; |
242 BOOL clientQuit, serverQuit; |
140 char buffer[BUFFER_SIZE], string[BUFFER_SIZE]; |
243 char buffer[BUFFER_SIZE], string[BUFFER_SIZE]; |
141 Uint8 msgSize; |
244 uint8_t msgSize; |
142 Uint16 gameTicks; |
245 uint16_t gameTicks; |
143 |
246 |
144 serverQuit = NO; |
247 serverQuit = NO; |
145 |
248 |
146 if (SDLNet_Init() < 0) { |
249 if (SDLNet_Init() < 0) { |
147 NSLog(@"SDLNet_Init: %s", SDLNet_GetError()); |
250 NSLog(@"SDLNet_Init: %s", SDLNet_GetError()); |
160 serverQuit = YES; |
263 serverQuit = YES; |
161 } |
264 } |
162 |
265 |
163 NSLog(@"engineProtocol - Waiting for a client on port %d", ipcPort); |
266 NSLog(@"engineProtocol - Waiting for a client on port %d", ipcPort); |
164 while (!serverQuit) { |
267 while (!serverQuit) { |
165 |
|
166 // This check the sd if there is a pending connection. |
268 // This check the sd if there is a pending connection. |
167 // If there is one, accept that, and open a new socket for communicating |
269 // If there is one, accept that, and open a new socket for communicating |
168 csd = SDLNet_TCP_Accept(sd); |
270 csd = SDLNet_TCP_Accept(sd); |
169 if (NULL != csd) { |
271 if (NULL != csd) { |
170 // Now we can communicate with the client using csd socket |
272 // Now we can communicate with the client using csd socket |
171 // sd will remain opened waiting other connections |
273 // sd will remain opened waiting other connections |
172 NSLog(@"engineProtocol - Client found"); |
274 NSLog(@"engineProtocol - Client found"); |
173 |
275 |
174 //first byte of the command alwayas contain the size of the command |
276 //first byte of the command alwayas contain the size of the command |
175 SDLNet_TCP_Recv(csd, &msgSize, sizeof(Uint8)); |
277 SDLNet_TCP_Recv(csd, &msgSize, sizeof(uint8_t)); |
176 |
278 |
177 SDLNet_TCP_Recv(csd, buffer, msgSize); |
279 SDLNet_TCP_Recv(csd, buffer, msgSize); |
178 gameTicks = SDLNet_Read16 (&buffer[msgSize - 2]); |
280 gameTicks = SDLNet_Read16 (&buffer[msgSize - 2]); |
179 //NSLog(@"engineProtocol - %d: received [%s]", gameTicks, buffer); |
281 //NSLog(@"engineProtocol - %d: received [%s]", gameTicks, buffer); |
180 |
282 |
181 if ('C' == buffer[0]) { |
283 if ('C' == buffer[0]) { |
182 NSLog(@"engineProtocol - sending game config"); |
284 NSLog(@"engineProtocol - sending game config"); |
183 |
285 |
184 // send config data data |
|
185 /* |
|
186 seed is arbitrary string |
|
187 addteam <32charsMD5hash> <color> <team name> |
|
188 addhh <level> <health> <hedgehog name> |
|
189 <level> is 0 for human, 1-5 for bots (5 is the most stupid) |
|
190 */ |
|
191 // local game |
286 // local game |
192 [self sendToEngine:@"TL"]; |
287 [self sendToEngine:@"TL"]; |
193 |
288 |
194 // seed info |
289 // seed info |
195 [self sendToEngine:[self.gameConfig objectForKey:@"seed_command"]]; |
290 [self sendToEngine:[self.gameConfig objectForKey:@"seed_command"]]; |
196 |
291 |
197 // various flags |
292 // scheme (returns initial health) |
198 [self sendToEngine:@"e$gmflags 256"]; |
293 NSInteger health = [self provideScheme:@"testing"]; |
199 [self sendToEngine:@"e$damagepct 100"]; |
|
200 [self sendToEngine:@"e$turntime 45000"]; |
|
201 [self sendToEngine:@"e$minestime 3000"]; |
|
202 [self sendToEngine:@"e$landadds 4"]; |
|
203 [self sendToEngine:@"e$sd_turns 15"]; |
|
204 [self sendToEngine:@"e$casefreq 5"]; |
|
205 [self sendToEngine:@"e$explosives 2"]; |
|
206 [self sendToEngine:@"e$minedudpct 0"]; |
|
207 |
294 |
208 // dimension of the map |
295 // dimension of the map |
209 [self sendToEngine:[self.gameConfig objectForKey:@"templatefilter_command"]]; |
296 [self sendToEngine:[self.gameConfig objectForKey:@"templatefilter_command"]]; |
210 [self sendToEngine:[self.gameConfig objectForKey:@"mapgen_command"]]; |
297 [self sendToEngine:[self.gameConfig objectForKey:@"mapgen_command"]]; |
211 [self sendToEngine:[self.gameConfig objectForKey:@"mazesize_command"]]; |
298 [self sendToEngine:[self.gameConfig objectForKey:@"mazesize_command"]]; |
213 // theme info |
300 // theme info |
214 [self sendToEngine:[self.gameConfig objectForKey:@"theme_command"]]; |
301 [self sendToEngine:[self.gameConfig objectForKey:@"theme_command"]]; |
215 |
302 |
216 NSArray *teamsConfig = [self.gameConfig objectForKey:@"teams_list"]; |
303 NSArray *teamsConfig = [self.gameConfig objectForKey:@"teams_list"]; |
217 for (NSDictionary *teamData in teamsConfig) { |
304 for (NSDictionary *teamData in teamsConfig) { |
218 [self sendTeamData:[teamData objectForKey:@"team"] |
305 [self provideTeamData:[teamData objectForKey:@"team"] |
219 withPlayingHogs:[[teamData objectForKey:@"number"] intValue] |
306 forHogs:[[teamData objectForKey:@"number"] intValue] |
220 ofColor:[teamData objectForKey:@"color"]]; |
307 withHealth:health |
|
308 ofColor:[teamData objectForKey:@"color"]]; |
221 } |
309 } |
222 |
310 |
223 NSDictionary *ammoData = [[NSDictionary alloc] initWithObjectsAndKeys: |
311 [self provideAmmoData:nil forPlayingTeams:[teamsConfig count]]; |
224 @"939192942219912103223511100120100000021119091",@"ammostore_initialqt", |
|
225 @"040504054160065554655446477657666666615550100",@"ammostore_probability", |
|
226 @"000000000000020550000004000700400000000020000",@"ammostore_delay", |
|
227 @"131111031211111112311411111111111111121110111",@"ammostore_crate", nil]; |
|
228 [self sendAmmoData:ammoData forTeams:[teamsConfig count]]; |
|
229 [ammoData release]; |
|
230 |
312 |
231 clientQuit = NO; |
313 clientQuit = NO; |
232 } else { |
314 } else { |
233 NSLog(@"engineProtocolThread - wrong message or client closed connection"); |
315 NSLog(@"engineProtocolThread - wrong message or client closed connection"); |
234 clientQuit = YES; |
316 clientQuit = YES; |