source: Daodan/MSVC/Flatline.c@ 582

Last change on this file since 582 was 582, checked in by gumby, 14 years ago

Hangs on death, but netcode is improved.

File size: 31.9 KB
Line 
1#include "Flatline.h"
2#include "Oni_Character.h"
3#include "Flatline_Client.h"
4#include "Flatline_Server.h"
5#include "Flatline_Events.h"
6#include <Windows.h>
7//#include <sys/time.h>
8#include <time.h>
9#include <float.h>
10#define isnan(x) ((x) != (x))
11uint32_t last1 = 0; uint32_t last2 = 0;
12player_info Players[MAX_PLAYERS] = {{0}, {0}, {0}, {0}};
13player_info * PlayerList[MAX_CONNECTIONS] = {0};
14multiplayer_status MultiplayerStatus;
15unsigned int lastPingTime;
16
17const char * Rejection_Messages[][255] = {
18 {"Server is full"},
19 {"-2"},
20 {"-3"},
21 {"-4"},
22 {"-5"},
23};
24
25#define BETTER_SYNC
26
27void DoRareSync( short Player, sockaddr_in * sender )
28{
29 flatline_packet sync = {0};
30
31 if (Player > max_connections || !PlayerList[ Player ] ) return;
32
33
34 // DDrConsole_PrintF( "Sending sync data for player %i, new index %u", Player, PlayerList[ Player ]->rare_sync_index);
35 sender->sin_addr.S_un.S_addr = htonl(sender->sin_addr.S_un.S_addr);
36 sync.id = RARE_SYNC_DATA;
37 sprintf( sync.rare_sync_data.Class, TMrInstance_GetInstanceName( PlayerList[ Player ]->Chr->ONCC ) );
38 //using ->Inventory instead of ->Chr->Inventory to keep the index and Inventory in sync, just in case.
39 memcpy( &(sync.rare_sync_data.Inventory), &(PlayerList[ Player ]->Inventory), sizeof(Inventory) );
40 //WEAPONS ARE DISABLED. Why? Pain in the arse to sync.
41 sync.rare_sync_data.Inventory.Weapons[0] = NULL;
42 sync.rare_sync_data.Inventory.Weapons[1] = NULL;
43 sync.rare_sync_data.Inventory.Weapons[2] = NULL;
44 sync.rare_sync_data.PlayerNum = Player;
45 sync.rare_sync_data.index = PlayerList[ Player ]->rare_sync_index;
46 NetTCPServer_Send( sender, (char*)&sync, sizeof(rare_sync_data) + FLATLINE_HEADER );
47}
48
49bool FLrServer_PacketCallback(char* data, int datalen, int from)
50{
51 int i, j;
52 bool found_player = 0;
53 flatline_packet * packet = (flatline_packet*)data;
54 static int recieved = 0;
55 sockaddr_in sender;
56 sender.sin_family = AF_INET;
57 sender.sin_port = htons(27777);
58 sender.sin_addr = *((struct in_addr*)(int*)&from);
59
60
61 //packet->data[datalen] = '\0';
62
63 //DDrConsole_PrintF("Packet \r%d recieved from %i", ++recieved, from);
64
65
66
67 //if data[0] != CONNECT_SEND, search in playerlist for ip address
68
69
70
71
72 switch(packet->id) {
73 flatline_packet connect_recv;
74 player_info * playah;
75 //rewrite this when we get TCP support.
76 //rewrite this before we get TCP support*
77 //the way of seeing if there is room for players sucks.
78 case CONNECT_SEND:
79 ;
80
81 connect_recv.id = CONNECT_REPLY;
82
83 //if(Players[i].ip == sender.sin_addr.S_un.S_addr) break; //needs to send an error message
84 sender.sin_addr.S_un.S_addr = htonl(sender.sin_addr.S_un.S_addr);
85 playah = FLrServer_AddPlayer(from,packet->connect_send.name, 0, 0);
86 DDrConsole_PrintF("%s connected from %s", packet->connect_send.name, inet_ntoa(sender.sin_addr ) );
87 if(!((int)playah > -5 && (int)playah <= 0)) {
88 flatline_packet new_char = {0};
89 CharacterObject* Char;
90 connect_recv.connect_reply.goodtogo = 1;
91 connect_recv.connect_reply.player_slot = playah->list_slot;
92 DDrConsole_PrintF("Slot: %i", playah->list_slot);
93
94 //sending this several times to make sure it gets through. Really need to make up some form of packet tracking.
95 NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
96 NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
97 NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
98 NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
99 NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
100 Sleep(100);
101
102 new_char.id = NEW_PLAYER;
103 Char = &new_char.new_player.Character;
104 memset(Char, 0, sizeof(CharacterObject));
105 Char->Header.Type = 'CHAR';
106 Char->OSD.Options = chr_dontaim;
107 for(j = 0; j < max_connections; j++) {
108 if(PlayerList[j] != 0) {
109 new_char.new_player.Playernumber = j;
110 sprintf(Char->OSD.Name,"%s",PlayerList[j]->name);
111
112 sprintf(Char->OSD.Class, "%s", TMrInstance_GetInstanceName(PlayerList[j]->Chr->ONCC));
113 DDrConsole_PrintF("Class %s", Char->OSD.Class );
114
115 sprintf(Char->OSD.Class, "konoko_generic");
116 NetTCPServer_Send((sockaddr *) &sender, (char*)&new_char, sizeof(new_player) + FLATLINE_HEADER );
117 }
118
119 }
120 }
121 else {
122 //fix the error messages...
123 DDrConsole_PrintF("Server is full. :(");
124 connect_recv.connect_reply.goodtogo = 0;
125 sender.sin_addr.S_un.S_addr = htonl(sender.sin_addr.S_un.S_addr);
126 memcpy(&connect_recv.connect_reply.message,"Server is full.", sizeof("Server is full."));
127 NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(bool)*2 + FLATLINE_HEADER + sizeof("Server is full."));
128
129 }
130
131
132 break;
133 case CONNECT_REPLY:
134 break; //do nothing...a server shouldn't recieve this type of packet.
135 case MESSAGE:
136 for(i = 0; i < MAX_PLAYERS; i++) {
137 //DDrConsole_PrintF("%i : %i | %s : %s", from, Players[i].ip, inet_ntoa(*(struct in_addr*)&from), inet_ntoa(*(struct in_addr*)&(Players[i].ip)));
138 if(Players[i].ip == sender.sin_addr.S_un.S_addr) {
139 found_player = 1;
140 break;
141 }
142 }
143 if(found_player == 0) return true;
144 else {
145 char message_buffer[512] = {0};
146 flatline_packet message;
147 int message_size;
148 data[datalen] = 0;
149
150 DDrConsole_PrintF("%s: %s", Players[i].name, packet->data);
151 sprintf(message_buffer, "%s: %s", Players[i].name, packet->data);
152
153 message.id = MESSAGE;
154 message_size = sprintf(message.data, "%s", message_buffer);
155 COrMessage_Print(message_buffer, "chat", 0);
156 UDPServer_SendToAll(&message, message_size + 1 + FLATLINE_HEADER);
157 break;
158 }
159 case CHANGE_NAME:
160 ; //wtf, needed or i get an error.
161 DDrConsole_PrintF("Changing Name to: %s", packet->data);
162 for(i = 0; i < MAX_PLAYERS; i++) {
163 if(Players[i].ip == sender.sin_addr.S_un.S_addr) {
164 found_player = 1;
165 break;
166 }
167 }
168 if(found_player == 0) return true;
169 else {
170 bool name_exists = 0;
171 for(j = 0; j < MAX_PLAYERS; j++) {
172 if(!strcmp(packet->data, Players[j].name)) {
173 name_exists = 1;
174 break;
175 }
176 }
177 if(!name_exists) {
178 char message_buffer[1024];
179 sprintf(message_buffer,"%s changed their name to %s", Players[i].name, packet->data);
180 COrMessage_Print(message_buffer, "name_change", 0);
181 memcpy(Players[i].name, packet->data, 256);
182
183 }
184 break;
185 }
186 case PLAYER_INPUT:
187
188 for(i = 0; i < max_connections; i++) {
189 if(PlayerList[i] != 0 && PlayerList[i]->ip == sender.sin_addr.S_un.S_addr) {
190 found_player = 1;
191 break;
192 }
193 }
194
195 if(found_player == 0) return true;
196 else {
197 input_struct * packet_input = &packet->input_struct;
198
199
200 PlayerList[i]->Actions1 = packet_input->Actions1;
201 PlayerList[i]->Actions2 = packet_input->Actions2;
202 PlayerList[i]->MouseDeltaX = packet_input->MouseDeltaX;
203 PlayerList[i]->MouseDeltaY = packet_input->MouseDeltaY;
204 PlayerList[i]->LastInputTime = packet_input->Time;
205
206 break;
207 }
208 case RARE_SYNC_DATA_REQUEST:
209 DoRareSync( packet->sync_request , &sender);
210 break;
211 case PK_PONG:
212 for(i = 0; i < max_connections; i++) {
213 if(PlayerList[i] != 0 && PlayerList[i]->ip == sender.sin_addr.S_un.S_addr) {
214 found_player = 1;
215 break;
216 }
217 }
218
219 if(found_player == 0) return true;
220 if(packet->ping != lastPingTime)
221 {
222 PlayerList[i]->Ping = 999;
223 }
224 else
225 {
226 PlayerList[i]->Ping = GetTickCount() - packet->ping;
227 }
228 break;
229 default:
230 DDrConsole_PrintF("Warning, recieved badly formed packet!");
231 break;
232 }
233 return true;
234}
235
236bool FLrServer_Run()
237{
238 // Get the local hostname
239 char szHostName[255];
240 struct hostent *host_entry;
241 gethostname(szHostName, 255);
242
243 host_entry=gethostbyname(szHostName);
244 DDrConsole_PrintF("Server started at %s...", inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list));
245 return NetUDPServer_Listen(27777, FLrServer_PacketCallback);
246}
247
248short TRrAnimation_GetType(char* anim)
249{
250 return *(short*)(anim + 0x15A);
251}
252
253void ONrCharacter_SetAnimationInternal(Character* Char, ActiveCharacter* AChar,
254 short inFromState, short inNextAnimType, const void *TRAM)
255{
256 ONCC *ONCC = Char->ONCC;
257 void *TRAC = ONCC->TRAC;
258 short index = Char->Number;
259 short animType;
260
261 if (TRAM == 0) return;
262
263 animType = TRrAnimation_GetType(TRAM);
264
265 AChar->Animation = TRAM;
266 AChar->Frame = 0;
267 AChar->AnimationFromState = inFromState;
268 AChar->AnimationType = animType;
269
270 AChar->NextAnimationType= inNextAnimType;
271 AChar->AnimationToState = TRrAnimation_GetTo(TRAM);
272
273 return;
274}
275
276
277RGBA green = {0, 0xFF, 0, 0};
278RGBA red = {0, 0, 0xFF, 0};
279RGBA grey = {0x80,0x80,0x80,0x80};
280
281//FLrClient_Run
282//Looping function that waits for packets from the server.
283int client_slot = 0;
284
285void FLrClient_GetPackets()
286{
287 flatline_packet packet;
288 uint16_t len;
289 //#define SPAM_INPUT
290#ifdef SPAM_INPUT
291 struct timeval lasttime;
292 struct timeval thistime;
293 gettimeofday(&lasttime, 0);
294#endif
295
296
297 while(NetUDPSocket_Recieve(client_sock, (sockaddr_storage *) &client_address, &packet, &len)) {
298 //packet = (flatline_packet*)data;
299 //DDrConsole_PrintF("Data recieved, length %i, type %i", len, ((flatline_packet*)data)->id);
300 switch(packet.id) {
301 case MESSAGE:
302 COrMessage_Print(packet.data, "chat", 0);
303 break;
304 case CONNECT_SEND:
305 ;if(1) {
306 flatline_packet connect_recv;
307 memcpy(&connect_recv.connect_reply.message,"This isn't a server!", sizeof("This isn't a server!"));
308 NetUDPSocket_Send(client_sock, (sockaddr *) &address, (char*)&connect_recv, sizeof(bool) + FLATLINE_HEADER + sizeof("This isn't a server!"));
309 }
310 case CONNECT_REPLY:
311 break; //extra packet or something.
312 case NEW_PLAYER:
313 ;if(1) { //haxhaxhax
314 CharacterObject* Char = &(packet.new_player.Character);
315 uint32_t chr_index = 0;
316 Character* PC;
317 DDrConsole_PrintF("%i | %i", packet.new_player.Playernumber ,client_slot);
318 //Char->OSD.Options = 0;
319 if(packet.new_player.Playernumber == client_slot) {
320 PlayerList[packet.new_player.Playernumber] = &Players[0];
321 PC = (ONgGameState->PlayerCharacter);
322 Players[0].Chr = PC;
323
324 }
325 else {
326 ONrGameState_NewCharacter(Char, NULL, NULL, &chr_index);
327 ONgGameState->CharacterStorage[chr_index].charType = 0;
328 PlayerList[packet.new_player.Playernumber] = &Players[chr_index];
329 Players[chr_index].Chr = &(ONgGameState->CharacterStorage[chr_index]);
330 Players[chr_index].Chr->Flags &= 0xFFBFFFFF;
331 Players[chr_index].spawnnumber = chr_index;
332 DDrConsole_PrintF("Spawning player %s, class %s, slot %i", ((new_player*)(packet.data))->Character.OSD.Name, ((new_player*)(packet.data))->Character.OSD.Class,chr_index) ;
333 }
334 //Players[((new_player*)(packet.data))->Playernumber].spawnnumber = ONrGameState_NewCharacter(&(((new_player*)(packet.data))->Character), NULL, NULL, 0);
335 break;
336 }
337 case PLAYER_DATA:
338 if(1) { //haxhaxhax
339 player_data* pd = &packet.player_data;
340 uint16_t i = pd->PlayerNum;
341
342 pd = (void*)packet.data;
343
344
345 if (i > max_connections) break;
346 if( !PlayerList[i] ) break;
347
348 memcpy( &(PlayerList[i]->player_data), pd, sizeof(player_data) );
349
350 if( !server_started && pd->rare_sync_index > PlayerList[i]->rare_sync_index )
351 {
352 int sent_bytes;
353 flatline_packet sync_request = {0};
354 sync_request.id = RARE_SYNC_DATA_REQUEST;
355 sync_request.sync_request = i;
356 DDrConsole_PrintF( "Requesting sync data for player %i, old index %u", i, PlayerList[i]->rare_sync_index);
357 sent_bytes = NetUDPSocket_Send(client_sock,(sockaddr *) &address, (char*)&sync_request, FLATLINE_HEADER + sizeof(int) );
358 }
359
360 PlayerList[i]->DataApplied = 0;
361
362
363 break;
364 }
365 case RARE_SYNC_DATA:
366 if(1) {
367 sl_arg hax[2];
368 int dontuse;
369 uint16_t i = packet.rare_sync_data.PlayerNum;
370
371 if (i > max_connections) break;
372 if( !PlayerList[i] ) break;
373
374 //WEAPONS ARE DISABLED. Why? Pain in the arse to sync.
375 packet.rare_sync_data.Inventory.Weapons[0] = NULL;
376 packet.rare_sync_data.Inventory.Weapons[1] = NULL;
377 packet.rare_sync_data.Inventory.Weapons[2] = NULL;
378 // TMrInstance_GetDataPtr( 'ONCC', packet.rare_sync_data.Class, PlayerList[ i ]->Chr->ONCC );
379
380 //add the target character
381 hax[0].type = sl_int32;
382 hax[0].value_int32 = PlayerList[ packet.rare_sync_data.PlayerNum ]->spawnnumber;
383
384 //add the new class
385 //fix this later so we cant buffer overflow :O
386 hax[1].type = sl_str32;
387 hax[1].value_str32 = packet.rare_sync_data.Class;
388
389 //we are directly calling a bsl function instead of using the normal method for two reasons
390 //1. it has all the checking built in
391 iSetCharacterClass( 0, 2, hax, &dontuse, &dontuse, hax );
392 //DDrConsole_PrintF( "Recieved sync data for player %i, class %s, old index %u, new index %u", i, packet.rare_sync_data.Class, PlayerList[i]->rare_sync_index, packet.rare_sync_data.index);
393 memcpy( &(PlayerList[ i ]->Chr->Inventory), &(packet.rare_sync_data.Inventory), sizeof(Inventory ));
394
395 PlayerList[i]->rare_sync_index = packet.rare_sync_data.index;
396 }
397 break;
398 case FLATLINE_EVENT:
399 FLcEventHandler( packet.flatline_event.event_index, packet.flatline_event.intArray );
400 break;
401 case PK_PING:
402 packet.id = PK_PONG;
403 NetUDPSocket_Send(client_sock, (sockaddr *) &address, (char*)&packet, FLATLINE_HEADER + 4);
404 break;
405 case PK_ALL_INPUT:
406 if(1)
407 {
408 int Player, i;
409 for(i = 0; packet.all_input[i].PlayerNum != -1; i++)
410 {
411 Player = packet.all_input[i].PlayerNum;
412 if(PlayerList[Player])
413 {
414 PlayerList[Player]->Actions1 = packet.all_input[Player].Actions1;
415 PlayerList[Player]->Actions2 = packet.all_input[Player].Actions2;
416 PlayerList[Player]->MouseDeltaX = packet.all_input[Player].MouseDeltaX;
417 PlayerList[Player]->MouseDeltaY = packet.all_input[Player].MouseDeltaY;
418 PlayerList[Player]->Facing = packet.all_input[Player].Facing;
419 PlayerList[Player]->DesiredFacing = packet.all_input[Player].DesiredFacing;
420 PlayerList[Player]->Position = packet.all_input[Player].Position;
421 }
422 }
423 }
424 break;
425 default:
426 DDrConsole_PrintF("Warning, recieved badly formed packet!");
427 break;
428 }
429 }
430}
431
432
433bool FLrClient_Run(flatline_packet* packet)
434{
435
436 char data[1400];
437 uint16_t len;
438 int j;
439 int sent_bytes;
440 client_connected = 0;
441
442
443 //starts the connection
444 DDrConsole_PrintF("Connecting to server %s on socket %i", inet_ntoa(address.sin_addr), client_sock);
445 sent_bytes = NetUDPSocket_Send(client_sock, (sockaddr*)&address, (char*)packet, 255);
446 if(sent_bytes == SOCKET_ERROR) {
447 NetCatchError();
448 }
449 //loops once per second waiting for a reply.
450 for(j = 0; j < CONNECTION_TIMEOUT; j++) {
451 while(NetUDPSocket_Recieve(client_sock, (sockaddr_storage *) &client_address, data, &len)){
452 packet = (flatline_packet*)data;
453 if(packet->id == CONNECT_REPLY) {
454 if(packet->connect_reply.goodtogo){
455
456 client_connected = 1;
457
458 client_slot = ((connect_reply*)packet->data)->player_slot;
459
460 PlayerList[client_slot] = Players+client_slot;
461 PlayerList[client_slot]->Chr = ONgGameState->PlayerCharacter;
462
463 DDrConsole_PrintColored("Connection successful!",0,green, grey);
464
465 //disable local input.
466 DDrPatch_NOOP(0x004FA929, 5 + 6 + 5);
467
468 //Disable local turning
469 //DDrPatch_NOOP(0x004F7EA8, 2);
470 //DDrPatch_Byte( 0x004F7EB1 , 0xE9);
471 //DDrPatch_MakeJump( 0x004F7EB1, 0x004F8030 );
472
473
474 //DDrPatch_Byte(0x04ED6FB, 0xEB);
475
476 //DDrConsole_PrintF("Slot %i", ((connect_reply*)packet)->player_slot);
477 //DDrPatch_NOOP(0x43B23,0x10);
478 //DDrPatch_NOOP(0x4EC248,(0x5A-0x48));
479 //DDrPatch_NOOP(0x4EC861, 6);
480 break;
481 }
482 else {
483 DDrConsole_PrintF("Connection rejected: %s", ((connect_reply*)packet->data)->message);
484 return false;
485 break;
486 }
487 }
488 }
489 if(client_connected) break;
490 DDrConsole_PrintF("Connection timing out in %i seconds...", CONNECTION_TIMEOUT - j);
491 Sleep(1000);
492 }
493 //the client timed out without recieving an error message.
494 if(!client_connected) {
495 DDrConsole_PrintColored("Connection timed out.",0,red, grey);
496 return false;
497 }
498
499 return true;
500}
501
502//wtf, this needs cleaned up...
503player_info *FLr_FindEmptySlot() {
504 int j;
505 for(j = 0; j < MAX_PLAYERS; j++) {
506 if (Players[j].ip == 0) {
507 return &Players[j];
508 }
509 }
510 return 0;
511}
512
513extern uint16_t max_connections;
514uint16_t FLr_FindEmptyListSlot() {
515 int j;
516 for(j = 0; j < max_connections; j++) {
517 if (PlayerList[j] == 0) {
518 return j;
519 }
520 }
521 return -1;
522}
523typedef struct
524{
525 uint16_t x;
526 uint16_t y;
527
528} IMtPoint2D;
529static flatline_packet cache_input = {0};
530enum
531{
532 FirstPass,
533 SecondPass,
534 NoPass,
535};
536bool ShouldSendUpdate( int i, Character* Player, ActiveCharacter* Active_Player )
537{
538 return
539 MultiplayerStatus.PleaseUpdateAllPlayers ? 1 :
540 strcmp(PlayerList[i]->player_data.Animation,
541 TMrInstance_GetInstanceName(Active_Player->Animation)) ? 1 :
542 PlayerList[i]->player_data.Health != Player->Health ? 1 : 0;
543}
544
545void * ONICALL FLrInput_Update_Keys(void)
546{
547 uint16_t i;
548 flatline_packet all_input = {0};
549 int16_t InputIndex = 0;
550 //ActiveCharacter * Active_Player = ONgGameState->ActiveCharacters;
551
552 if(client_connected)
553 {
554 int sent_bytes;
555 flatline_packet input_packet = {0};
556
557 FLrClient_GetPackets();
558
559 input_packet.id = PLAYER_INPUT;
560 input_packet.input_struct.Time = ONgGameState->GameTime;
561// ((GameState*)(ONgGameState))->Input.Current.Actions1 |= Action_Backward | Action_StepLeft;
562 input_packet.input_struct.Actions1 = ((GameState*)(ONgGameState))->Input.Current.Actions1;
563 input_packet.input_struct.Actions2 = ((GameState*)(ONgGameState))->Input.Current.Actions2;
564 input_packet.input_struct.MouseDeltaX = ((GameState*)(ONgGameState))->Input.MouseDeltaX;
565 input_packet.input_struct.MouseDeltaY = ((GameState*)(ONgGameState))->Input.MouseDeltaY;
566
567 sent_bytes = NetUDPSocket_Send(client_sock,(sockaddr *) &address, (char*)&input_packet, sizeof(input_struct) + FLATLINE_HEADER);
568
569 //return ONgGameState;
570 }
571
572
573 if(!(server_started || client_connected)) return ONgGameState;
574
575 all_input.id = PK_ALL_INPUT;
576
577 if(server_started && ONgGameState->GameTime % 120 == 0)
578 {
579 FLsPingAll();
580 }
581
582 if(server_started && PlayerList[0])
583 {
584 PlayerList[0]->Actions1 = ONgGameState->Input.Current.Actions1;
585 PlayerList[0]->Actions2 = ONgGameState->Input.Current.Actions2;
586 PlayerList[0]->MouseDeltaX = ONgGameState->Input.MouseDeltaX;
587 PlayerList[0]->MouseDeltaY = ONgGameState->Input.MouseDeltaY;
588 }
589
590 for(i = 0; i < max_connections; i++) {
591 ActiveCharacter * Active_Player;
592 Character* Player;
593 GameInput * Active_Input;
594 if(PlayerList[i] == 0) continue;
595 Player = PlayerList[i]->Chr;
596 if(server_started)
597 {
598
599 //Set up input packets
600
601 all_input.all_input[InputIndex].Actions1 = PlayerList[i]->Actions1;
602 all_input.all_input[InputIndex].Actions2 = PlayerList[i]->Actions2;
603 all_input.all_input[InputIndex].MouseDeltaX = PlayerList[i]->MouseDeltaX;
604 all_input.all_input[InputIndex].MouseDeltaY = PlayerList[i]->MouseDeltaY;
605
606 all_input.all_input[InputIndex].Facing = Player->Facing;
607 all_input.all_input[InputIndex].DesiredFacing = Player->DesiredFacing;
608
609 //Infinity...
610 *(int *)&all_input.all_input[InputIndex].Position.X = 0x7f800000;
611
612 all_input.all_input[InputIndex].PlayerNum = i;
613 InputIndex++;
614 }
615
616 if( Player->Health == 0)
617 {
618 int Actions;
619 const short TicksToRespawn = 3 * 60;
620 if(PlayerList[i]->state != STATE_DEAD)
621 {
622 PlayerList[i]->state = STATE_DEAD;
623 PlayerList[i]->DeathTime = ONgGameState->GameTime;
624 if(i == client_slot)
625 {
626 ONrGameState_Timer_Start( "", TicksToRespawn );
627 }
628 }
629
630 if(server_started && i == 0)
631 {
632 Actions = ONgGameState->Input.Current.Actions1;
633 }
634 else
635 {
636 Actions = PlayerList[i]->Actions1;
637 }
638
639 if(PlayerList[i]->flags & PF_SCRIPTEDAI)
640 {
641 FLrPlayerDisconnect( i );
642 }
643 else if(ONgGameState->GameTime - PlayerList[i]->DeathTime < TicksToRespawn )
644 {
645 continue;
646 }
647 else if(Actions & (Action_Punch | Action_Kick))
648 {
649 FLrPlayerRespawn( i );
650 }
651 continue;
652
653
654 }
655
656 Active_Player = ONrGetActiveCharacter( PlayerList[i]->Chr);
657
658 if(Active_Player == 0) continue;
659
660
661
662 //Active_Player->PlayingFilm.Flags = 1;
663 Active_Input = &(Active_Player->Input);
664 if(server_started)
665 {
666 all_input.all_input[InputIndex - 1].Position = Active_Player->PhyContext->Position;
667 }
668 if(server_started &&
669 ShouldSendUpdate( i, PlayerList[i]->Chr, Active_Player) )
670 {
671 player_data * data;
672 flatline_packet data_out = {0};
673
674
675 data_out.id = PLAYER_DATA;
676 data = (void*)&(data_out.data);
677 data->PlayerNum = i;
678 data->Health = PlayerList[i]->Chr->Health;
679 data->MaxHealth = PlayerList[i]->Chr->MaxHealth;
680 //data->Position = PlayerList[i]->Chr->Position;
681 //data->Facing = PlayerList[i]->Chr->Facing;
682 //data->DesiredFacing = PlayerList[i]->Chr->DesiredFacing;
683 //data->Position = Active_Player->PhyContext->Position;
684 memcpy(data->Animation, TMrInstance_GetInstanceName(Active_Player->Animation), 31);
685 data->Frame = Active_Player->Frame;
686
687 data->UD = Active_Player->HeadPitch;
688 data->LR = Active_Player->HeadFacing;
689
690 if(Active_Player->targetThrow)
691 {
692 data->throw_data.throwing = Players[Active_Player->throwing].list_slot;
693 memcpy(data->throw_data.throwName, TMrInstance_GetInstanceName(Active_Player->targetThrow), 31);
694 data->throw_data.throwFrame = ONrGetActiveCharacter(Active_Player->targetThrow)->Frame;
695 }
696
697
698 if( PlayerList[i]->OldClass != PlayerList[i]->Chr->ONCC || memcmp( &(PlayerList[i]->Inventory), &(PlayerList[i]->Chr->Inventory), sizeof(Inventory) ) )
699 {
700 PlayerList[i]->OldClass = PlayerList[i]->Chr->ONCC;
701 memcpy( &(PlayerList[i]->Inventory), &(PlayerList[i]->Chr->Inventory), sizeof(Inventory) );
702 PlayerList[i]->rare_sync_index++;
703
704 }
705
706 data->rare_sync_index = PlayerList[i]->rare_sync_index;
707
708
709 data->Ping = PlayerList[i]->Ping;
710 memcpy( &(PlayerList[i]->player_data), data, sizeof(player_data) );
711
712 UDPServer_SendToAll(&data_out, sizeof(player_data) + FLATLINE_HEADER);
713 }
714
715 if( (server_started && i !=0) || !server_started )
716 {
717 Active_Input->Stop.Actions1 = ~PlayerList[i]->Actions1 & Active_Input->Current.Actions1;
718 Active_Input->Stop.Actions2 = ~PlayerList[i]->Actions2 & Active_Input->Current.Actions2;
719 Active_Input->Start.Actions1 = ~Active_Input->Current.Actions1 & PlayerList[i]->Actions1;
720 Active_Input->Start.Actions2 = ~Active_Input->Current.Actions2 & PlayerList[i]->Actions2;
721
722 Active_Input->Current.Actions1 = PlayerList[i]->Actions1;
723 Active_Input->Current.Actions2 = PlayerList[i]->Actions2;
724 Active_Input->Stopped.Actions1 = ~Active_Input->Current.Actions1;
725 Active_Input->Stopped.Actions2 = ~Active_Input->Current.Actions2;
726 Active_Input->MouseDeltaX = PlayerList[i]->MouseDeltaX;
727 Active_Input->MouseDeltaY = PlayerList[i]->MouseDeltaY;
728
729
730 if( !server_started && PlayerList[i]->player_data.Health != 0) {
731 void* OldAnimation;
732 void* Animation;
733 player_data* pd = &PlayerList[i]->player_data;
734
735 PlayerList[i]->Chr->Facing = PlayerList[i]->Facing;
736 PlayerList[i]->Chr->DesiredFacing = PlayerList[i]->DesiredFacing;
737
738 if(*(int*)&PlayerList[i]->Chr->Position.X != 0x7f800000)
739 {
740 Active_Player->PhyContext->Position = PlayerList[i]->Position;
741 }
742 else
743 {
744 int breakfast = 0;
745 }
746 /*
747 if(isnan(Active_Player->PhyContext->Position.Y) ||
748 isnan(Active_Player->PhyContext->Position.X) ||
749 isnan(Active_Player->PhyContext->Position.Z) )
750 {
751 //DDrConsole_PrintF("Player is NAN! %x %x", Active_Player->PhyContext->Position.Y, PlayerList[i]->Height);
752 DDrConsole_PrintF("Player is NAN! %x %x %x", Active_Player->PhyContext->Position.X, Active_Player->PhyContext->Position.Y, Active_Player->PhyContext->Position.Z);
753 //DDrConsole_PrintF("Velocity %x %x %x", Active_Player->PhyContext->Velocity.X, Active_Player->PhyContext->Velocity.Y, Active_Player->PhyContext->Velocity.Z);
754
755
756 }
757 */
758
759 if( PlayerList[i]->DataApplied == FirstPass )
760 {
761 PlayerList[i]->DataApplied = SecondPass;
762
763 Player->Health = PlayerList[i]->player_data.Health;
764 PlayerList[i]->Chr->MaxHealth = PlayerList[i]->player_data.MaxHealth;
765
766 }
767 else if( PlayerList[i]->DataApplied == SecondPass )
768 {
769 OldAnimation = Active_Player->Animation;
770
771 PlayerList[i]->DataApplied = NoPass;
772
773 PlayerList[i]->player_data.Frame++;
774
775 if (!(Player->Flags & ONcCharacterFlag_BeingThrown) &&
776 (pd->Animation[0] != 0))
777 {
778 // get a pointer to the animation
779
780 TMrInstance_GetDataPtr(
781 'TRAM',
782 pd->Animation,
783 &Animation);
784 if (Animation != OldAnimation)
785 {
786 short num_frames;
787 bool updateAnimation = true;
788
789 // if the character is dead, make sure this animation is appropriate for death
790 /*
791 if (Player->Flags & ONcCharacterFlag_Dead)
792 {
793 short curToState = TRrAnimation_GetTo(Active_Player->Animation);
794 short newToState = TRrAnimation_GetTo(animation);
795
796 // if we are currently heading towards fallen and the new animation would not
797 // then this is a better animation to run when we are dead
798 if ((ONrAnimState_IsFallen(curToState)) &&
799 (!ONrAnimState_IsFallen(newToState)))
800 {
801 updateAnimation = false;
802 }
803 }
804 */
805 if ((updateAnimation) && (Active_Player->Animation == Animation))
806 {
807 int oldFrame = Active_Player->Frame;
808 int newFrame = pd->Frame;
809
810 if (abs(oldFrame - newFrame) < 2)
811 {
812 updateAnimation = false;
813 }
814 }
815
816 if (updateAnimation)
817 {
818 // set the characters animation
819 /* ONrCharacter_SetAnimationInternal(Player,
820 Active_Player,
821 Active_Player->AnimationToState,
822 0,
823 Animation);
824 ONrCharacter_NewAnimationHook(Player, Active_Player);*/
825 //Player->Flags |= 0x00000010;
826 ONrCharacter_SetAnimationExternal(Player, TRrAnimation_GetFrom(Animation), Animation, 0);
827 //ONrCharacter_NewAnimationHook(Player, Active_Player);
828 }
829
830 num_frames = TRrAnimation_GetDuration(Active_Player->Animation);
831
832 if (pd->Frame == num_frames)
833 {
834 Active_Player->Frame = num_frames - 1;
835 //Active_Player->Frame = 0;
836 }
837 else
838 {
839 Active_Player->Frame = pd->Frame;
840 }
841 }
842 } //animation check
843
844 if (PlayerList[i]->player_data.throw_data.throwName[0] != 0)
845 {
846 short throwTarget = PlayerList[pd->throw_data.throwing]->spawnnumber;
847 if ((throwTarget != Active_Player->throwing) &&
848 (pd->throw_data.throwFrame < 10))
849 {
850 void *throw_animation;
851 ActiveCharacter* Target;
852 // get the animation
853
854 TMrInstance_GetDataPtr(
855 'TRAM',
856 pd->throw_data.throwName,
857 &throw_animation);
858 //if (error) return;
859
860 // set the throw target
861 Active_Player->ThrowTargetCharacter = &ONgGameState->CharacterStorage[throwTarget];
862 Target = ONrGetActiveCharacter(Active_Player->ThrowTargetCharacter);
863 if ((Target->Animation != throw_animation) &&
864 (OldAnimation != Animation) &&
865 !(Active_Player->ThrowTargetCharacter->Flags & ONcCharacterFlag_BeingThrown))
866 {
867 // set the throw variables
868 Active_Player->targetThrow = throw_animation;
869 Active_Player->throwing = throwTarget;
870
871 // run the throw
872 ONrCharacter_NewAnimationHook(Player, Active_Player);
873
874 if (Active_Player->ThrowTargetCharacter)
875 {
876 Target->Frame += 2;
877 Target->thrownBy = Player->Number;
878 }
879 }
880 }
881 } //throw check
882 } //second pass
883 } //if not dead
884 } //if( (server_started && i !=0) || !server_started )
885
886 //Check for character switching requests
887 if(server_started && PlayerList[i]->Actions1 & Action_Block && PlayerList[i]->ShapeshiftCooldown < ONgGameState->GameTime)
888 {
889 int error;
890
891
892
893 ONCC *newClass;
894 short numClasses = (short)TMrInstance_GetTagCount('ONCC');
895 /*
896 if(Active_Player->Input.Start.Actions1 & Action_Block)
897 {
898 //This might not be getting hit. Find out why, eh?
899 PlayerList[i]->ShapeshiftCooldown = ONgGameState->GameTime + 15;
900 }
901 else
902 {
903 PlayerList[i]->ShapeshiftCooldown = ONgGameState->GameTime + 5;
904 }
905 */
906 if (PlayerList[i]->Actions1 & Action_Crouch) {
907 Player->ONCCnumber += numClasses - 1;
908 }
909 else {
910 Player->ONCCnumber += 1;
911 }
912
913 if (numClasses > 0) {
914 Player->ONCCnumber = Player->ONCCnumber % numClasses;
915
916 error = TMrInstance_GetDataPtr_ByNumber('ONCC', Player->ONCCnumber, &newClass);
917
918 if ((newClass != NULL) && (!error)) {
919 ONrCharacter_SetCharacterClass(Player, newClass);
920 }
921 }
922
923 }
924
925
926 }
927 if(server_started)
928 {
929 all_input.all_input[InputIndex].PlayerNum = -1;
930 UDPServer_SendToAll(&all_input,
931 FLATLINE_HEADER + sizeof(player_input) * InputIndex + sizeof(int16_t));
932 }
933 MultiplayerStatus.PleaseUpdateAllPlayers = 0;
934 return ONgGameState;
935}
936
937void FLrPlayerDisconnect( int Player )
938{
939 if(server_started)
940 {
941 //FLsPublic_Event(EV_DISCONNECT, &Player );
942 MultiplayerStatus.PleaseUpdateAllPlayers = 1;
943 }
944 //Kill off the character in another function, please
945 //ONrCharacter_SetHitPoints( PlayerList[Player]->Chr, 0);
946
947 memset(PlayerList[Player], 0, sizeof(player_info));
948 PlayerList[Player] = 0;
949
950
951
952 return;
953}
954
955void FLrPlayerRespawn( int Player )
956{
957 PlayerList[Player]->state = STATE_ALIVE;
958 ONrCorpse_Create(PlayerList[Player]->Chr);
959 ONrCharacter_SetHitPoints( PlayerList[Player]->Chr, PlayerList[Player]->Chr->MaxHealth );
960}
961
962
963void* ScoreboardInstance = 0;
964void FLrRun_Scores()
965{
966 if(client_connected || server_started)
967 {
968 if(!ScoreboardInstance){
969 void* TSFFTahoma;
970 TMrInstance_GetDataPtr( 'TSFF', "Tahoma", &TSFFTahoma);
971 TSrContext_New( TSFFTahoma, 7, 1, 1, 0, &ScoreboardInstance);
972 }
973 if(ScoreboardInstance){
974 const int white = 0x00FFFFFF;
975 const int green = 0x0000FF00;
976 const int red = 0x00FF0000;
977 int i;
978 char DrawString[255];
979 const int LineHeight = 15;
980 IMtPoint2D DrawLocation = {20, 20};
981 TSrContext_SetShade(ScoreboardInstance, white);
982 TSrContext_DrawText(ScoreboardInstance, "Oni Flatline build " __DATE__ " " __TIME__, 255, 0, &DrawLocation);
983 DrawLocation.y += LineHeight;
984 TSrContext_DrawText(ScoreboardInstance, "Name", 255, 0, &DrawLocation);
985 DrawLocation.x += 150;
986 TSrContext_DrawText(ScoreboardInstance, "Score", 255, 0, &DrawLocation);
987 DrawLocation.x += 50;
988 TSrContext_DrawText(ScoreboardInstance, "Ping", 255, 0, &DrawLocation);
989 for(i = 0; i <MAX_PLAYERS; i++)
990 {
991 if(PlayerList[i] == 0 || PlayerList[i]->Chr == 0) continue;
992
993 DrawLocation.x = 20;
994 DrawLocation.y += LineHeight;
995
996 if(PlayerList[i]->Chr && PlayerList[i]->Chr->Health == 0)
997 {
998 TSrContext_SetShade(ScoreboardInstance, red);
999 }
1000 else if (i == client_slot)
1001 {
1002 TSrContext_SetShade(ScoreboardInstance, green);
1003 }
1004 TSrContext_DrawText(ScoreboardInstance, PlayerList[i]->Chr->Name, 255, 0, &DrawLocation);
1005 TSrContext_SetShade(ScoreboardInstance, white);
1006 DrawLocation.x += 150;
1007 sprintf(DrawString, "%i", PlayerList[i]->Chr->Damage);
1008 TSrContext_DrawText(ScoreboardInstance, DrawString, 255, 0, &DrawLocation);
1009 DrawLocation.x += 50;
1010 sprintf(DrawString, "%i", PlayerList[i]->player_data.Ping);
1011 TSrContext_DrawText(ScoreboardInstance, DrawString, 255, 0, &DrawLocation);
1012 }
1013 }
1014 }
1015}
1016
1017bool FlatlineInitialize()
1018{
1019
1020 memset( Players, 0, sizeof( player_info ) * MAX_PLAYERS );
1021 memset( PlayerList, 0, 4 * MAX_PLAYERS );
1022 memset( &MultiplayerStatus, 0, sizeof( multiplayer_status ));
1023 return 1;
1024}
Note: See TracBrowser for help on using the repository browser.