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