1 /*=============================================================================
2 Blobby Volley 2
3 Copyright (C) 2006 Jonathan Sieber (jonathan_sieber@yahoo.de)
4 Copyright (C) 2006 Daniel Knobe (daniel-knobe@web.de)
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 =============================================================================*/
20
21 /* header include */
22
23 /* includes */
24 #include <algorithm>
25 #include <iostream>
26 #include <ctime>
27
28 #include <boost/lexical_cast.hpp>
29 #include <boost/scoped_array.hpp>
30 #include <boost/make_shared.hpp>
31
32 #include "raknet/RakClient.h"
33 #include "raknet/RakServer.h"
34 #include "raknet/PacketEnumerations.h"
35 #include "raknet/GetTime.h"
36
37 #include "NetworkState.h"
38 #include "NetworkMessage.h"
39 #include "TextManager.h"
40 #include "ReplayRecorder.h"
41 #include "DuelMatch.h"
42 #include "IMGUI.h"
43 #include "SoundManager.h"
44 #include "LocalInputSource.h"
45 #include "UserConfig.h"
46 #include "FileExceptions.h"
47 #include "GenericIO.h"
48 #include "FileRead.h"
49 #include "FileWrite.h"
50 #include "MatchEvents.h"
51 #include "SpeedController.h"
52 #include "server/DedicatedServer.h"
53 #include "LobbyState.h"
54 #include "InputManager.h"
55
56
57 /* implementation */
NetworkGameState(boost::shared_ptr<RakClient> client)58 NetworkGameState::NetworkGameState( boost::shared_ptr<RakClient> client):
59 GameState(new DuelMatch(true, DEFAULT_RULES_FILE)),
60 mClient( client ),
61 mWinningPlayer(NO_PLAYER),
62 mNetworkState(WAITING_FOR_OPPONENT),
63 mWaitingForReplay(false),
64 mSelectedChatmessage(0),
65 mChatCursorPosition(0),
66 mChattext("")
67 {
68 boost::shared_ptr<IUserConfigReader> config = IUserConfigReader::createUserConfigReader("config.xml");
69 mOwnSide = (PlayerSide)config->getInteger("network_side");
70 mUseRemoteColor = config->getBool("use_remote_color");
71 mLocalInput.reset(new LocalInputSource(mOwnSide));
72 mLocalInput->setMatch(mMatch.get());
73
74 /// \todo why do we need this here?
75 RenderManager::getSingleton().redraw();
76
77 // game is not started until two players are connected
78 mMatch->pause();
79
80 // load/init players
81
82 if(mOwnSide == LEFT_PLAYER)
83 {
84 PlayerIdentity localplayer = config->loadPlayerIdentity(LEFT_PLAYER, true);
85 PlayerIdentity remoteplayer = config->loadPlayerIdentity(RIGHT_PLAYER, true);
86 mLocalPlayer = &mMatch->getPlayer( LEFT_PLAYER );
87 mRemotePlayer = &mMatch->getPlayer( RIGHT_PLAYER );
88 mMatch->setPlayers( localplayer, remoteplayer );
89 }
90 else
91 {
92 PlayerIdentity localplayer = config->loadPlayerIdentity(RIGHT_PLAYER, true);
93 PlayerIdentity remoteplayer = config->loadPlayerIdentity(LEFT_PLAYER, true);
94 mLocalPlayer = &mMatch->getPlayer( RIGHT_PLAYER );
95 mRemotePlayer = &mMatch->getPlayer( LEFT_PLAYER );
96 mMatch->setPlayers( remoteplayer, localplayer );
97 }
98
99 mRemotePlayer->setName("");
100 }
101
~NetworkGameState()102 NetworkGameState::~NetworkGameState()
103 {
104 mClient->Disconnect(50);
105 }
106
step_impl()107 void NetworkGameState::step_impl()
108 {
109 IMGUI& imgui = IMGUI::getSingleton();
110 RenderManager* rmanager = &RenderManager::getSingleton();
111
112 packet_ptr packet;
113 while (packet = mClient->Receive())
114 {
115 switch(packet->data[0])
116 {
117 case ID_PHYSIC_UPDATE:
118 {
119 RakNet::BitStream stream((char*)packet->data, packet->length, false);
120 int ival;
121 stream.IgnoreBytes(1); //ID_PHYSIC_UPDATE
122 stream.IgnoreBytes(1); //ID_TIMESTAMP
123 stream.Read(ival); //TODO: un-lag based on timestamp delta
124 //printf("Physic packet received. Time: %d\n", ival);
125 DuelMatchState ms;
126 boost::shared_ptr<GenericIn> in = createGenericReader(&stream);
127 in->generic<DuelMatchState> (ms);
128 mMatch->setState(ms);
129 break;
130 }
131 case ID_WIN_NOTIFICATION:
132 {
133 RakNet::BitStream stream((char*)packet->data, packet->length, false);
134 stream.IgnoreBytes(1); //ID_WIN_NOTIFICATION
135 stream.Read((int&)mWinningPlayer);
136
137 // last point must not be added anymore, because
138 // the score is also simulated local so it is already
139 // right. under strange circumstances this need not
140 // be true, but then the score is set to the correy value
141 // by ID_BALL_RESET
142
143 mNetworkState = PLAYER_WON;
144 break;
145 }
146 case ID_OPPONENT_DISCONNECTED:
147 {
148 // In this state, a leaving opponent would not be very surprising
149 if (mNetworkState != PLAYER_WON)
150 mNetworkState = OPPONENT_DISCONNECTED;
151 break;
152 }
153 case ID_BALL_RESET:
154 {
155 PlayerSide servingPlayer;
156 RakNet::BitStream stream((char*)packet->data, packet->length, false);
157 stream.IgnoreBytes(1); //ID_BALL_RESET
158 stream.Read((int&)servingPlayer);
159
160 // read and set new score
161 int nLeftScore;
162 int nRightScore;
163 int time;
164 stream.Read(nLeftScore);
165 stream.Read(nRightScore);
166 stream.Read(time);
167 mMatch->setScore(nLeftScore, nRightScore);
168 mMatch->setServingPlayer(servingPlayer);
169 // sync the clocks... normally, they should not differ
170 mMatch->getClock().setTime(time);
171
172 /// \attention
173 /// we can get a problem here:
174 /// assume the packet informing about the game event which lead to this
175 /// either BALL_GROUND_COLLISION or BALL_PLAYER_COLLISION got stalled
176 /// and arrives at the same time time as this packet. Then we get the following behaviour:
177 /// we set the score to the right value... the event causing the score to happen gets processed
178 /// -> that player scores -> score is off!
179 ///
180 /// i don't have a clean fix for this right now, so we'll have to live with a workaround for now
181 /// we just order the game to reset all triggered events.
182 mMatch->resetTriggeredEvents();
183 /// \todo a good fix would involve ensuring we process all events in the right order
184
185
186 break;
187 }
188 case ID_COLLISION:
189 {
190 int event;
191 float intensity;
192 RakNet::BitStream stream((char*)packet->data, packet->length, false);
193 stream.IgnoreBytes(1); //ID_COLLISION
194 stream.Read(event);
195 stream.Read(intensity);
196
197 mMatch->setLastHitIntensity(intensity);
198 mMatch->trigger( event );
199 break;
200 }
201 case ID_PAUSE:
202 if (mNetworkState == PLAYING)
203 {
204 mNetworkState = PAUSING;
205 mMatch->pause();
206 }
207 break;
208 case ID_UNPAUSE:
209 if (mNetworkState == PAUSING)
210 {
211 SDL_StopTextInput();
212 mNetworkState = PLAYING;
213 mMatch->unpause();
214 }
215 break;
216 case ID_GAME_READY:
217 {
218 char charName[16];
219 RakNet::BitStream stream((char*)packet->data, packet->length, false);
220
221 stream.IgnoreBytes(1); // ignore ID_GAME_READY
222
223 // read gamespeed
224 int speed;
225 stream.Read(speed);
226 SpeedController::getMainInstance()->setGameSpeed(speed);
227
228 // read playername
229 stream.Read(charName, sizeof(charName));
230
231 // ensures that charName is null terminated
232 charName[sizeof(charName)-1] = '\0';
233
234 // read colors
235 int temp;
236 stream.Read(temp);
237 Color ncolor = temp;
238
239 mRemotePlayer->setName(charName);
240
241 setDefaultReplayName(mLocalPlayer->getName(), mRemotePlayer->getName());
242
243 // check whether to use remote player color
244 if(mUseRemoteColor)
245 {
246 mRemotePlayer->setStaticColor(ncolor);
247 RenderManager::getSingleton().redraw();
248 }
249
250 // Workarround for SDL-Renderer
251 // Hides the GUI when networkgame starts
252 rmanager->redraw();
253
254 mNetworkState = PLAYING;
255 // start game
256 mMatch->unpause();
257
258 // game ready whistle
259 SoundManager::getSingleton().playSound("sounds/pfiff.wav", ROUND_START_SOUND_VOLUME);
260 break;
261 }
262 case ID_RULES_CHECKSUM:
263 {
264 RakNet::BitStream stream((char*)packet->data, packet->length, false);
265
266 stream.IgnoreBytes(1); // ignore ID_RULES_CHECKSUM
267
268 int serverChecksum;
269 stream.Read(serverChecksum);
270 int ourChecksum = 0;
271 if (serverChecksum != 0)
272 {
273 try
274 {
275 FileRead rulesFile("server_rules.lua");
276 ourChecksum = rulesFile.calcChecksum(0);
277 rulesFile.close();
278 }
279 catch( FileLoadException& ex )
280 {
281 // file doesn't exist - nothing to do here
282 }
283 }
284
285 RakNet::BitStream stream2;
286 stream2.Write((unsigned char)ID_RULES);
287 stream2.Write(bool(serverChecksum != 0 && serverChecksum != ourChecksum));
288 mClient->Send(&stream2, HIGH_PRIORITY, RELIABLE_ORDERED, 0);
289
290 break;
291 }
292 case ID_RULES:
293 {
294 RakNet::BitStream stream((char*)packet->data, packet->length, false);
295
296 stream.IgnoreBytes(1); // ignore ID_RULES
297
298 int rulesLength;
299 stream.Read(rulesLength);
300 if (rulesLength)
301 {
302 boost::shared_array<char> rulesString( new char[rulesLength + 1] );
303 stream.Read(rulesString.get(), rulesLength);
304 // null terminate
305 rulesString[rulesLength] = 0;
306 FileWrite rulesFile("server_rules.lua");
307 rulesFile.write(rulesString.get(), rulesLength);
308 rulesFile.close();
309 mMatch->setRules("server_rules.lua");
310 }
311 else
312 {
313 // either old server, or we have to use fallback ruleset
314 mMatch->setRules( FALLBACK_RULES_NAME );
315 }
316
317 break;
318 }
319 // status messages we don't care about
320 case ID_REMOTE_DISCONNECTION_NOTIFICATION:
321 case ID_REMOTE_CONNECTION_LOST:
322 case ID_SERVER_STATUS:
323 case ID_CHALLENGE:
324 case ID_REMOTE_NEW_INCOMING_CONNECTION:
325 case ID_REMOTE_EXISTING_CONNECTION:
326 break;
327 case ID_DISCONNECTION_NOTIFICATION:
328 case ID_CONNECTION_LOST:
329 if (mNetworkState != PLAYER_WON)
330 mNetworkState = DISCONNECTED;
331 break;
332 case ID_NO_FREE_INCOMING_CONNECTIONS:
333 mNetworkState = SERVER_FULL;
334 break;
335 case ID_CHAT_MESSAGE:
336 {
337 RakNet::BitStream stream((char*)packet->data, packet->length, false);
338 stream.IgnoreBytes(1); // ID_CHAT_MESSAGE
339 // Insert Message in the log and focus the last element
340 char message[31];
341 stream.Read(message, sizeof(message));
342 message[30] = '\0';
343
344 // Insert Message in the log and focus the last element
345 mChatlog.push_back((std::string) message);
346 mChatOrigin.push_back(false);
347 mSelectedChatmessage = mChatlog.size() - 1;
348 SoundManager::getSingleton().playSound("sounds/chat.wav", ROUND_START_SOUND_VOLUME);
349 break;
350 }
351 case ID_REPLAY:
352 {
353 /// \todo we should take more action if server sends replay
354 /// even if not requested!
355 if(!mWaitingForReplay)
356 break;
357
358 RakNet::BitStream stream = RakNet::BitStream((char*)packet->data, packet->length, false);
359 stream.IgnoreBytes(1); // ID_REPLAY
360
361 // read stream into a dummy replay recorder
362 boost::shared_ptr<GenericIn> reader = createGenericReader( &stream );
363 ReplayRecorder dummyRec;
364 dummyRec.receive( reader );
365 // and save that
366 saveReplay(dummyRec);
367
368 // mWaitingForReplay will be set to false even if replay could not be saved because
369 // the server won't send it again.
370 mWaitingForReplay = false;
371
372 break;
373 }
374
375 // we never do anything that should cause such a packet to be received!
376 case ID_CONNECTION_REQUEST_ACCEPTED:
377 case ID_CONNECTION_ATTEMPT_FAILED:
378 assert( 0 );
379 break;
380
381 case ID_BLOBBY_SERVER_PRESENT:
382 {
383 // this should only be called if we use the stay on server option
384 RakNet::BitStream stream( packet->getStream() );
385 stream.IgnoreBytes(1); //ID_BLOBBY_SERVER_PRESENT
386 ServerInfo info(stream, mClient->PlayerIDToDottedIP(packet->playerId), packet->playerId.port);
387
388 if (packet->length == ServerInfo::BLOBBY_SERVER_PRESENT_PACKET_SIZE )
389 {
390 switchState(new LobbyState(info));
391 }
392 break;
393 }
394 default:
395 printf("Received unknown Packet %d\n", packet->data[0]);
396 std::cout<<packet->data<<"\n";
397 break;
398 }
399 }
400
401 // does this generate any problems if we pause at the exact moment an event is set ( i.e. the ball hit sound
402 // could be played in a loop)?
403 presentGame();
404 presentGameUI();
405
406 if (InputManager::getSingleton()->exit() && mNetworkState != PLAYING)
407 {
408 if(mNetworkState == PAUSING)
409 {
410 // end pause
411 RakNet::BitStream stream;
412 stream.Write((unsigned char)ID_UNPAUSE);
413 mClient->Send(&stream, HIGH_PRIORITY, RELIABLE_ORDERED, 0);
414 }
415 else
416 {
417 switchState(new MainMenuState);
418 }
419 }
420 else if (InputManager::getSingleton()->exit() && mSaveReplay)
421 {
422 mSaveReplay = false;
423 IMGUI::getSingleton().resetSelection();
424 }
425 else if (mErrorMessage != "")
426 {
427 displayErrorMessageBox();
428 }
429 else if (mSaveReplay)
430 {
431 if ( displaySaveReplayPrompt() )
432 {
433
434 // request replay from server
435 RakNet::BitStream stream;
436 stream.Write((unsigned char)ID_REPLAY);
437 mClient->Send(&stream, LOW_PRIORITY, RELIABLE_ORDERED, 0);
438
439 mSaveReplay = false;
440 mWaitingForReplay = true;
441 }
442 }
443 else if (mWaitingForReplay)
444 {
445 imgui.doOverlay(GEN_ID, Vector2(150, 200), Vector2(650, 400));
446 imgui.doText(GEN_ID, Vector2(190, 220), TextManager::RP_WAIT_REPLAY);
447 if (imgui.doButton(GEN_ID, Vector2(440, 330), TextManager::LBL_CANCEL))
448 {
449 mSaveReplay = false;
450 mWaitingForReplay = false;
451 imgui.resetSelection();
452 }
453 imgui.doCursor();
454 }
455 else switch (mNetworkState)
456 {
457 case WAITING_FOR_OPPONENT:
458 {
459 imgui.doOverlay(GEN_ID, Vector2(100.0, 210.0),
460 Vector2(700.0, 310.0));
461 imgui.doText(GEN_ID, Vector2(150.0, 250.0),
462 TextManager::GAME_WAITING);
463 break;
464 }
465 case OPPONENT_DISCONNECTED:
466 {
467 imgui.doCursor();
468 imgui.doOverlay(GEN_ID, Vector2(100.0, 210.0), Vector2(700.0, 390.0));
469 imgui.doText(GEN_ID, Vector2(140.0, 240.0), TextManager::GAME_OPP_LEFT);
470
471 if (imgui.doButton(GEN_ID, Vector2(230.0, 290.0), TextManager::LBL_OK))
472 {
473 switchState(new MainMenuState);
474 }
475
476 if (imgui.doButton(GEN_ID, Vector2(350.0, 290.0), TextManager::RP_SAVE))
477 {
478 mSaveReplay = true;
479 imgui.resetSelection();
480 }
481
482 if (imgui.doButton(GEN_ID, Vector2(250.0, 340.0), TextManager::NET_STAY_ON_SERVER))
483 {
484 // Send a blobby server connection request
485 RakNet::BitStream stream;
486 stream.Write((unsigned char)ID_BLOBBY_SERVER_PRESENT);
487 stream.Write(BLOBBY_VERSION_MAJOR);
488 stream.Write(BLOBBY_VERSION_MINOR);
489 mClient->Send(&stream, LOW_PRIORITY, RELIABLE_ORDERED, 0);
490 }
491 break;
492 }
493 case DISCONNECTED:
494 {
495 imgui.doCursor();
496 imgui.doOverlay(GEN_ID, Vector2(100.0, 210.0),
497 Vector2(700.0, 370.0));
498 imgui.doText(GEN_ID, Vector2(120.0, 250.0),
499 TextManager::NET_DISCONNECT);
500 if (imgui.doButton(GEN_ID, Vector2(230.0, 320.0),
501 TextManager::LBL_OK))
502 {
503 switchState(new MainMenuState);
504 }
505 if (imgui.doButton(GEN_ID, Vector2(350.0, 320.0), TextManager::RP_SAVE))
506 {
507 mSaveReplay = true;
508 imgui.resetSelection();
509 }
510 break;
511 }
512 case SERVER_FULL:
513 {
514 imgui.doCursor();
515 imgui.doOverlay(GEN_ID, Vector2(100.0, 210.0),Vector2(700.0, 370.0));
516 imgui.doText(GEN_ID, Vector2(200.0, 250.0), TextManager::NET_SERVER_FULL);
517 if (imgui.doButton(GEN_ID, Vector2(350.0, 300.0), TextManager::LBL_OK))
518 {
519 switchState(new MainMenuState);
520 }
521 break;
522 }
523 case PLAYING:
524 {
525 mMatch->step();
526
527 mLocalInput->updateInput();
528 PlayerInputAbs input = mLocalInput->getRealInput();
529
530 if (InputManager::getSingleton()->exit())
531 {
532 RakNet::BitStream stream;
533 stream.Write((unsigned char)ID_PAUSE);
534 mClient->Send(&stream, HIGH_PRIORITY, RELIABLE_ORDERED, 0);
535 }
536 RakNet::BitStream stream;
537 stream.Write((unsigned char)ID_INPUT_UPDATE);
538 stream.Write((unsigned char)ID_TIMESTAMP); ///! \todo do we really need this time stamps?
539 stream.Write(RakNet::GetTime());
540 input.writeTo(stream);
541 mClient->Send(&stream, HIGH_PRIORITY, UNRELIABLE_SEQUENCED, 0);
542 break;
543 }
544 case PLAYER_WON:
545 {
546 displayWinningPlayerScreen(mWinningPlayer);
547 if (imgui.doButton(GEN_ID, Vector2(290, 360), TextManager::LBL_OK))
548 {
549 switchState(new MainMenuState());
550 }
551 if (imgui.doButton(GEN_ID, Vector2(380, 360), TextManager::RP_SAVE))
552 {
553 mSaveReplay = true;
554 imgui.resetSelection();
555 }
556 break;
557 }
558 case PAUSING:
559 {
560 imgui.doOverlay(GEN_ID, Vector2(175, 20), Vector2(625, 175));
561 imgui.doText(GEN_ID, Vector2(275, 35), TextManager::GAME_PAUSED);
562 if (imgui.doButton(GEN_ID, Vector2(205, 95), TextManager::LBL_CONTINUE))
563 {
564 RakNet::BitStream stream;
565 stream.Write((unsigned char)ID_UNPAUSE);
566 mClient->Send(&stream, HIGH_PRIORITY, RELIABLE_ORDERED, 0);
567 }
568 // Chat
569 imgui.doChatbox(GEN_ID, Vector2(10, 190), Vector2(790, 450), mChatlog, mSelectedChatmessage, mChatOrigin);
570 if (imgui.doEditbox(GEN_ID, Vector2(30, 460), 30, mChattext, mChatCursorPosition, 0, true))
571 {
572
573 // GUI-Hack, so that we can send messages
574 if ((InputManager::getSingleton()->getLastActionKey() == "Return") && (mChattext != ""))
575 {
576 RakNet::BitStream stream;
577 char message[31];
578
579 strncpy(message, mChattext.c_str(), sizeof(message));
580 stream.Write((unsigned char)ID_CHAT_MESSAGE);
581 stream.Write(message, sizeof(message));
582 mClient->Send(&stream, LOW_PRIORITY, RELIABLE_ORDERED, 0);
583 mChatlog.push_back(mChattext);
584 mChatOrigin.push_back(true);
585 mSelectedChatmessage = mChatlog.size() - 1;
586 mChattext = "";
587 mChatCursorPosition = 0;
588 SoundManager::getSingleton().playSound("sounds/chat.wav", ROUND_START_SOUND_VOLUME);
589 }
590 }
591 if (imgui.doButton(GEN_ID, Vector2(500, 95), TextManager::GAME_QUIT))
592 {
593 switchState(new MainMenuState);
594 }
595 if (imgui.doButton(GEN_ID, Vector2(285, 125), TextManager::RP_SAVE))
596 {
597 mSaveReplay = true;
598 imgui.resetSelection();
599 }
600 imgui.doCursor();
601 }
602 }
603 }
604
getStateName() const605 const char* NetworkGameState::getStateName() const
606 {
607 return "NetworkGameState";
608 }
609
610 // ---------------------------------------------------------------------------------------------------------------------------------
611 // implementation of the local host state
612 // ----------------------------------------
613
NetworkHostState()614 NetworkHostState::NetworkHostState() : mServer( ), mClient( new RakClient ), mGameState(nullptr)
615 {
616 // read config
617 /// \todo we need read-only access here!
618 UserConfig config;
619 config.loadFile("config.xml");
620 PlayerSide localSide = (PlayerSide)config.getInteger("network_side");
621
622 // load/init players
623 if(localSide == LEFT_PLAYER)
624 {
625 mLocalPlayer = config.loadPlayerIdentity(LEFT_PLAYER, true);
626 }
627 else
628 {
629 mLocalPlayer = config.loadPlayerIdentity(RIGHT_PLAYER, true);
630 }
631
632 ServerInfo info( mLocalPlayer.getName().c_str());
633 std::string rulesfile = config.getString("rules");
634
635 mServer.reset( new DedicatedServer(info, rulesfile, 4));
636
637 // connect to server
638 if (!mClient->Connect(info.hostname, info.port, 0, 0, RAKNET_THREAD_SLEEP_TIME))
639 throw( std::runtime_error(std::string("Could not connect to server ") + info.hostname) );
640
641
642 }
643
~NetworkHostState()644 NetworkHostState::~NetworkHostState()
645 {
646 delete mGameState;
647 }
648
step_impl()649 void NetworkHostState::step_impl()
650 {
651 packet_ptr packet;
652 if( mGameState == nullptr )
653 {
654 while (packet = mClient->Receive())
655 {
656 switch(packet->data[0])
657 {
658 // as soon as we are connected to the server
659 case ID_CONNECTION_REQUEST_ACCEPTED:
660 {
661 // ----------------------------------------------------
662 // Send ENTER SERVER packet
663 RakNet::BitStream stream;
664 stream.Write((unsigned char)ID_ENTER_SERVER);
665
666 // Send preferred side
667 stream.Write( mLocalPlayer.getPreferredSide() );
668
669 // Send playername
670 char myname[16];
671 strncpy(myname, mLocalPlayer.getName().c_str(), sizeof(myname));
672 stream.Write(myname, sizeof(myname));
673
674 // send color settings
675 stream.Write(mLocalPlayer.getStaticColor().toInt());
676
677 mClient->Send(&stream, HIGH_PRIORITY, RELIABLE_ORDERED, 0);
678
679 // Send ENTER GAME packet
680
681 RakNet::BitStream stream2;
682 stream2.Write((char)ID_CHALLENGE);
683 auto writer = createGenericWriter(&stream2);
684 writer->generic<PlayerID>( UNASSIGNED_PLAYER_ID );
685
686 mClient->Send(&stream2, HIGH_PRIORITY, RELIABLE_ORDERED, 0);
687
688 mGameState = new NetworkGameState(mClient);
689
690 break;
691 }
692 case ID_SERVER_STATUS:
693 {
694
695 }
696 break;
697 default:
698 std::cout << "Unknown packet " << int(packet->data[0]) << " received\n";
699 }
700 }
701 }
702
703 if(mServer->hasActiveGame())
704 {
705 mServer->allowNewPlayers(false);
706 }
707
708 mServer->processPackets();
709
710 /// \todo make this gamespeed independent
711 mLobbyCounter++;
712 if(mLobbyCounter % (750 /*10s*/) == 0 )
713 {
714 mServer->updateLobby();
715 }
716
717 mServer->updateGames();
718
719 if( mGameState )
720 mGameState->step_impl();
721 }
722
getStateName() const723 const char* NetworkHostState::getStateName() const
724 {
725 return "NetworkHostState";
726 }
727
728 // definition of syslog for client hosted games
syslog(int pri,const char * format,...)729 void syslog(int pri, const char* format, ...)
730 {
731 // do nothing?
732 }
733
734 // debug counters
735 int SWLS_PacketCount;
736 int SWLS_Connections;
737 int SWLS_Games;
738 int SWLS_GameSteps;
739 int SWLS_ServerEntered;
740