source: Daodan/MSVC/Flatline.c@ 583

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

last update before big rewrite

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