00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "srv-physics.h"
00036
00037 #include "srv-hosts.h"
00038 #include "srv-object.h"
00039 #include "srv-players.h"
00040
00041 #include "aesop-physics/aesop-physics.h"
00042 #include "map-manager/map-manager.h"
00043
00044 #include "netrq/netrq.h"
00045
00046
00047
00048 namespace aesop {
00049
00050
00051 static const int s_maxPorIdBytes = 64;
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 static const int s_maxPORBytes = 70;
00064
00065
00066 struct object_context_t {
00067 object_context_t(void) throw() { this->clear(); }
00068 void clear(void) throw() {
00069 dyn = NULL;
00070 queue = NULL;
00071 clock = 0;
00072 recipient = 0;
00073 }
00074
00075
00076 MapDynamics * dyn;
00077 netrq::Queue * queue;
00078 dword_t clock;
00079 conn_id_t recipient;
00080 };
00081
00082
00083
00085
00086
00087
00089
00090 class PhysicsObjectRequest : public netrq::Request {
00091 public:
00092 ~PhysicsObjectRequest(void) throw() { }
00093
00094
00095 const char * getId(void) const throw() { return m_id; }
00096 int getMaxBytes(void) const throw() { return s_maxPORBytes; }
00097 void write(IO xdrbuf::Output * output);
00098
00099
00100 static smart_ptr<netrq::Request> create(
00101 IN conn_id_t recipientUdpConn,
00102 IN smart_ptr<PhysicsObject> obj,
00103 IN const char * id) {
00104 ASSERT(recipientUdpConn, "null");
00105 ASSERT(obj, "null");
00106 ASSERT(id && id[0], "null or empty");
00107
00108 smart_ptr<PhysicsObjectRequest> local =
00109 new PhysicsObjectRequest;
00110 ASSERT(local, "out of memory");
00111
00112 strcpy(local->m_id, id);
00113 local->m_obj = obj;
00114 local->m_recipient = recipientUdpConn;
00115
00116 return local;
00117 }
00118
00119 private:
00120 PhysicsObjectRequest(void) throw() { }
00121
00122
00123
00124
00125 char m_id[s_maxPorIdBytes];
00126 conn_id_t m_recipient;
00127 smart_ptr<PhysicsObject> m_obj;
00128 };
00129
00130
00131
00132 void
00133 PhysicsObjectRequest::write
00134 (
00135 IO xdrbuf::Output * out
00136 )
00137 {
00138 ASSERT(out, "null");
00139 ASSERT(m_obj, "null");
00140
00141
00142
00143
00144 dword_t id = m_obj->getId();
00145 if (!id) {
00146 return;
00147 }
00148
00149
00150 out->openPacklet('o');
00151
00152
00153 out->addInt32Packlet('i', (int32_t *) &id, 1);
00154
00155
00156 point3d_t pos = m_obj->getPosition();
00157 out->addFloatPacklet('p', &pos.x, 3);
00158
00159
00160 quaternion_t orient = m_obj->getOrientation();
00161 out->addFloatPacklet('o', &orient.x, 4);
00162
00163
00164 point3d_t linear = m_obj->getLinearVelocity();
00165 out->addFloatPacklet('l', &linear.x, 3);
00166
00167
00168 point3d_t angular = m_obj->getAngularVelocity();
00169 out->addFloatPacklet('a', &angular.x, 3);
00170
00171
00172 smart_ptr<Instance> instance = getInstanceFromPhysicsObject(m_obj);
00173 if (instance) {
00174 smart_ptr<ServerObject> so = getServerObject(instance);
00175 if (so) {
00176 const char * state = so->getAnimationState(m_recipient);
00177 if (state) {
00178 int len = strlen(state);
00179
00180
00181 out->addStringPacklet('n', state, len);
00182 }
00183 }
00184 }
00185
00186
00187 out->closePacklet('o');
00188
00189 }
00190
00191
00192
00193 void
00194 addObjectRequestToQueue
00195 (
00196 IN smart_ptr<PhysicsObject> obj,
00197 IN conn_id_t recipientUdp,
00198 IN netrq::Queue * queue,
00199 IN dword_t clock
00200 )
00201 {
00202 ASSERT(obj, "null");
00203 ASSERT(recipientUdp, "null");
00204 ASSERT(queue, "null");
00205
00206
00207 long id = obj->getId();
00208 if (!id) {
00209 return;
00210 }
00211 char buffer[s_maxPorIdBytes];
00212 sprintf(buffer, "por-%u-%ld", recipientUdp, id);
00213
00214
00215 if (queue->containsRequest(buffer))
00216 return;
00217
00218
00219 smart_ptr<netrq::Request> por =
00220 PhysicsObjectRequest::create(recipientUdp, obj, buffer);
00221 ASSERT(por, "out of memory");
00222
00223
00224
00225 queue->addRequest(clock, por);
00226 }
00227
00228
00229
00230 static void
00231 sendObject
00232 (
00233 IN smart_ptr<Instance>& instance,
00234 IN smart_ptr<PhysicsObject>& obj,
00235 IN void * ctx
00236 )
00237 {
00238 ASSERT(instance, "null");
00239 ASSERT(obj, "null");
00240 object_context_t * poc = (object_context_t *) ctx;
00241 ASSERT(poc, "null");
00242 ASSERT(poc->dyn, "null");
00243 ASSERT(poc->queue, "null");
00244 ASSERT(poc->recipient, "null");
00245
00246 if (obj->getMass() <= 0.0) {
00247 return;
00248 }
00249
00250
00251 addObjectRequestToQueue(obj, poc->recipient, poc->queue,
00252 poc->clock + (rand() % 3));
00253 }
00254
00255
00256
00257 static void
00258 sendObjects
00259 (
00260 IN LeafZone * lz,
00261 IN void * context
00262 )
00263 {
00264 ASSERT(lz, "null");
00265 object_context_t * poc = (object_context_t *) context;
00266 ASSERT(poc, "null");
00267 ASSERT(poc->dyn, "null");
00268
00269
00270 poc->dyn->iterateInstancesInZone(lz, sendObject, context);
00271 }
00272
00273
00274
00276
00277
00278
00280
00281 void
00282 addPhysicsMessagesToQueue
00283 (
00284 IN dword_t clock,
00285 IN HostManager * hostMgr,
00286 IN PlayerManager * playerMgr,
00287 IN MapManager * mapMgr
00288 )
00289 {
00290 ASSERT(hostMgr, "null");
00291 ASSERT(playerMgr, "null");
00292 ASSERT(mapMgr, "null");
00293
00294
00295 HostManager::iterator_t i;
00296 host_rec_t hr;
00297 hostMgr->getIterator(i);
00298 while (hostMgr->getNextHost(i, hr)) {
00299
00300
00301 if (!hr.netQueue) {
00302 continue;
00303 }
00304
00305
00306
00307 PlayerManager::iterator_t j;
00308 playerMgr->getIterator(hr.udpConn, j);
00309 player_rec_t pr;
00310 while (playerMgr->getNextPlayer(j, pr)) {
00311 if (!pr.obj) {
00312 continue;
00313 }
00314
00315 addObjectRequestToQueue(pr.obj, hr.udpConn, hr.netQueue,
00316 clock);
00317 }
00318
00319
00320 playerMgr->getIterator(hr.udpConn, j);
00321 while (playerMgr->getNextPlayer(j, pr)) {
00322
00323 if (pr.mapId.isEmpty() || !pr.obj) {
00324
00325 continue;
00326 }
00327
00328
00329 smart_ptr<MapDynamics> dyn = mapMgr->getMap(pr.mapId);
00330 if (!dyn)
00331 continue;
00332 Map * map = dyn->getMap();
00333 ASSERT(map, "null");
00334
00335
00336 Zone * root = map->getRootZone();
00337 LeafZone * leaf = root->getLeafZone(pr.obj->getPosition());
00338 if (!leaf) {
00339 DPRINTF("No leaf zone contains player!");
00340 continue;
00341 }
00342
00343
00344 object_context_t oc;
00345 oc.dyn = dyn;
00346 oc.queue = hr.netQueue;
00347 oc.clock = clock;
00348 oc.recipient = hr.udpConn;
00349
00350
00351 leaf->iterateVisibleZones(sendObjects, (void *) &oc);
00352 }
00353 }
00354 }
00355
00356
00357
00358 };
00359