1 /***************************************************************************
2 clientsim.cpp - Client-side networked simulation
3 -------------------
4 begin : di jan 14 2003
5 copyright : (C) 2003 by CJP
6 email : cornware-cjp@users.sourceforge.net
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include <cstdio>
19
20 #include "timer.h"
21 #include "clientsim.h"
22 #include "textmessage.h"
23 #include "movingobject.h"
24
25 #include "netmessages.h"
26
CClientSim(CGameCore * gc,CClientNet * net)27 CClientSim::CClientSim(CGameCore *gc, CClientNet *net)
28 {
29 m_GameCore = gc;
30 m_Net = net;
31
32 m_PreviousTime = theWorld->m_LastTime;
33 }
34
~CClientSim()35 CClientSim::~CClientSim()
36 {
37 }
38
getTrackname(CGameCore::LoadStatusCallback callBackFun)39 CString CClientSim::getTrackname(CGameCore::LoadStatusCallback callBackFun)
40 {
41 m_Net->sendTextMessage(USNET_READY);
42
43 float t = CTimer::getTime();
44 float t_lastcontact = t;
45 while(t - t_lastcontact < 10.0)
46 {
47 t = CTimer::getTime();
48
49 m_Net->sendTextMessage(USNET_STATUS); //request for status
50
51 CMessageBuffer *buf = m_Net->receiveExpectedData(CMessageBuffer::textMessage, 500); //0.5 second
52 if(buf != NULL)
53 {
54 t_lastcontact = t;
55
56 CTextMessage tm;
57 tm.setBuffer(*buf);
58
59 if(buf->getAC() != 0)
60 m_Net->sendConfirmation(*buf, 0);
61
62 delete buf;
63
64 //We received the track file data:
65 CString trk = USNET_TRACK;
66 if(tm.m_Message.mid(0,trk.length()) == trk)
67 return tm.m_Message.mid(trk.length());
68
69 //We received a status update:
70 CString sts = USNET_STATUS;
71 if(callBackFun != NULL && tm.m_Message.mid(0,sts.length()) == sts)
72 if(!callBackFun(tm.m_Message.mid(sts.length()), -1.0))
73 return ""; //user wants to quit
74 }
75 }
76
77 return ""; //Timeout
78 }
79
update()80 bool CClientSim::update()
81 {
82 //the moving objects:
83 vector<CDataObject *> objs = theWorld->getObjectArray(CDataObject::eMovingObject);
84
85 float now = theWorld->m_LastTime;
86
87 if(now < m_PreviousTime - 0.01) //then we obviously started a new game
88 m_PreviousTime = now;
89
90 //if some amount of time has passed:
91 if(now > m_PreviousTime + 0.04) //25 times per second
92 {
93 m_PreviousTime = now;
94
95 //send input info
96 for(unsigned int j=0; j < objs.size(); j++)
97 {
98 CMovingObject *mo = (CMovingObject *)objs[j];
99
100 if( !m_GameCore->isLocalPlayer(mo->getMovObjID()) ) continue; //only local players
101
102 CMessageBuffer b = mo->m_InputData->getBuffer();
103 m_Net->sendData(b);
104 }
105 }
106
107 //clear the collision arrays:
108 for(unsigned int i=0; i < objs.size(); i++)
109 ((CMovingObject *)objs[i])->m_AllCollisions.clear();
110
111 //receive object info
112 //the receiveData function was already called by the gamecore
113 for(unsigned int i=0; i < m_Net->m_ReceiveBuffer.size(); i++)
114 {
115 CMessageBuffer &buf = m_Net->m_ReceiveBuffer[i];
116
117 //Tell the server that we received it (in cases when needed)
118 if(buf.getAC() != 0)
119 m_Net->sendConfirmation(buf, 0);
120
121 switch(buf.getType())
122 {
123 case CMessageBuffer::car:
124 case CMessageBuffer::movingObject:
125 {
126 CBinBuffer data = buf.getData();
127 unsigned int pos = 0;
128 Uint8 ID = data.getUint8(pos);
129
130 //find the corresponding moving object
131 CMovingObject *mo = NULL;
132 //first candidate
133 if(ID < objs.size())
134 {
135 CMovingObject *tmp = (CMovingObject *)objs[ID];
136 if(tmp->getMovObjID() == ID)
137 mo = tmp;
138 }
139 //all other objects
140 if(mo == NULL)
141 for(unsigned int j=0; j < objs.size(); j++)
142 {
143 CMovingObject *tmp = (CMovingObject *)objs[j];
144 if(tmp->getMovObjID() == ID)
145 mo = tmp;
146 }
147
148 if(mo == NULL) break; //not found
149
150 mo->setBuffer(buf);
151 }
152 break;
153
154 case CMessageBuffer::hiscore:
155 m_Hiscore.setBuffer(buf);
156 return false; //ending the game: we received a hiscore
157 break;
158
159 case CMessageBuffer::chat:
160 {
161 CChatMessage msg;
162 msg.setBuffer(buf);
163 theWorld->m_ChatSystem.m_InQueue.push_back(msg); //chat message received from server
164 //printf("Chat message received: %s\n", msg.m_Message.c_str());
165 }
166 break;
167
168 default:
169 break;
170 }
171
172 //TODO: maybe delete the used messages (maybe not necessary)
173 }
174
175 return true;
176 }
177