Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/orxonox/objects/worldentities/ControllableEntity.cc @ 2518

Last change on this file since 2518 was 2427, checked in by rgrieder, 16 years ago

Changed the way setPosition, setVelocity, setOrientation and setAngularVelocity is handled in MobileEntity and upwards.
This allows to introduce a lost feature: Position of an enemy ship on the client can't be set anymore at all (local changes were allowed before).

  • Property svn:eol-style set to native
File size: 15.3 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      Reto Grieder
26 *
27 */
28
29#include "OrxonoxStableHeaders.h"
30#include "ControllableEntity.h"
31
32#include "core/CoreIncludes.h"
33#include "core/Core.h"
34#include "core/XMLPort.h"
35#include "core/Template.h"
36
37#include "objects/infos/PlayerInfo.h"
38#include "objects/worldentities/Camera.h"
39#include "objects/worldentities/CameraPosition.h"
40#include "overlays/OverlayGroup.h"
41
42namespace orxonox
43{
44    CreateFactory(ControllableEntity);
45
46    ControllableEntity::ControllableEntity(BaseObject* creator) : MobileEntity(creator)
47    {
48        RegisterObject(ControllableEntity);
49
50        this->bControlled_ = false;
51        this->server_overwrite_ = 0;
52        this->client_overwrite_ = 0;
53        this->player_ = 0;
54        this->playerID_ = network::OBJECTID_UNKNOWN;
55        this->hud_ = 0;
56        this->camera_ = 0;
57        this->bDestroyWhenPlayerLeft_ = false;
58
59        this->server_position_         = Vector3::ZERO;
60        this->client_position_         = Vector3::ZERO;
61        this->server_linear_velocity_  = Vector3::ZERO;
62        this->client_linear_velocity_  = Vector3::ZERO;
63        this->server_orientation_      = Quaternion::IDENTITY;
64        this->client_orientation_      = Quaternion::IDENTITY;
65        this->server_angular_velocity_ = Vector3::ZERO;
66        this->client_angular_velocity_ = Vector3::ZERO;
67
68        this->registerVariables();
69    }
70
71    ControllableEntity::~ControllableEntity()
72    {
73        if (this->isInitialized())
74        {
75            if (this->bControlled_)
76                this->stopLocalControl();
77
78            if (this->hud_)
79                delete this->hud_;
80
81            if (this->camera_)
82                delete this->camera_;
83
84            if (this->getPlayer() && this->getPlayer()->getControllableEntity() == this)
85                this->getPlayer()->stopControl(this, false);
86        }
87    }
88
89    void ControllableEntity::XMLPort(Element& xmlelement, XMLPort::Mode mode)
90    {
91        SUPER(ControllableEntity, XMLPort, xmlelement, mode);
92
93        XMLPortParam(ControllableEntity, "hudtemplate", setHudTemplate, getHudTemplate, xmlelement, mode);
94        XMLPortParam(ControllableEntity, "camerapositiontemplate", setCameraPositionTemplate, getCameraPositionTemkplate, xmlelement, mode);
95
96        XMLPortObject(ControllableEntity, CameraPosition, "camerapositions", addCameraPosition, getCameraPosition, xmlelement, mode);
97    }
98
99    void ControllableEntity::addCameraPosition(CameraPosition* position)
100    {
101        this->attach(position);
102        this->cameraPositions_.push_back(position);
103    }
104
105    CameraPosition* ControllableEntity::getCameraPosition(unsigned int index) const
106    {
107        unsigned int i = 0;
108        for (std::list<CameraPosition*>::const_iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
109        {
110            if (i == index)
111                return (*it);
112            ++i;
113        }
114        return 0;
115    }
116
117    void ControllableEntity::switchCamera()
118    {
119        if (this->camera_)
120        {
121            if (this->camera_->getParent() == this && this->cameraPositions_.size() > 0)
122            {
123                this->cameraPositions_.front()->attachCamera(this->camera_);
124            }
125            else if (this->cameraPositions_.size() > 0)
126            {
127                for (std::list<CameraPosition*>::const_iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
128                {
129                    if ((*it) == this->camera_->getParent())
130                    {
131                        ++it;
132                        if (it != this->cameraPositions_.end())
133                            (*it)->attachCamera(this->camera_);
134                        else
135                            (*this->cameraPositions_.begin())->attachCamera(this->camera_);
136                        break;
137                    }
138                }
139            }
140            else
141            {
142                this->attach(this->camera_);
143            }
144        }
145    }
146
147    void ControllableEntity::setPlayer(PlayerInfo* player)
148    {
149        if (!player)
150        {
151            this->removePlayer();
152            return;
153        }
154
155        this->player_ = player;
156        this->playerID_ = player->getObjectID();
157        this->bControlled_ = (player->isLocalPlayer() && player->isHumanPlayer());
158        if (this->bControlled_)
159        {
160            this->startLocalControl();
161
162            if (!Core::isMaster())
163            {
164                this->client_overwrite_ = this->server_overwrite_;
165COUT(0) << "CE: bidirectional synchronization" << std::endl;
166                this->setObjectMode(network::direction::bidirectional);
167            }
168        }
169    }
170
171    void ControllableEntity::removePlayer()
172    {
173        if (this->bControlled_)
174            this->stopLocalControl();
175
176        this->player_ = 0;
177        this->playerID_ = network::OBJECTID_UNKNOWN;
178        this->bControlled_ = false;
179        this->setObjectMode(network::direction::toclient);
180
181        if (this->bDestroyWhenPlayerLeft_)
182            delete this;
183    }
184
185    void ControllableEntity::networkcallback_changedplayerID()
186    {
187        // just do this in case the entity wasn't yet synchronized when the corresponding PlayerInfo got our objectID
188        if (this->playerID_ != network::OBJECTID_UNKNOWN)
189        {
190            this->player_ = dynamic_cast<PlayerInfo*>(network::Synchronisable::getSynchronisable(this->playerID_));
191            if (this->player_ && (this->player_->getControllableEntity() != this))
192                this->player_->startControl(this);
193        }
194    }
195
196    void ControllableEntity::startLocalControl()
197    {
198//        std::cout << this->getObjectID() << " ###### start local control" << std::endl;
199        this->camera_ = new Camera(this);
200        this->camera_->requestFocus();
201        if (this->cameraPositionTemplate_ != "")
202            this->addTemplate(this->cameraPositionTemplate_);
203        if (this->cameraPositions_.size() > 0)
204            this->cameraPositions_.front()->attachCamera(this->camera_);
205        else
206            this->attach(this->camera_);
207
208        if (this->hudtemplate_ != "")
209        {
210            this->hud_ = new OverlayGroup(this);
211            this->hud_->addTemplate(this->hudtemplate_);
212        }
213    }
214
215    void ControllableEntity::stopLocalControl()
216    {
217//        std::cout << "###### stop local control" << std::endl;
218        this->camera_->detachFromParent();
219        delete this->camera_;
220        this->camera_ = 0;
221
222        delete this->hud_;
223        this->hud_ = 0;
224    }
225
226    void ControllableEntity::tick(float dt)
227    {
228        MobileEntity::tick(dt);
229
230        if (this->isActive())
231        {
232            // Check whether Bullet doesn't do the physics for us
233            if (!this->isDynamic())
234            {
235                if (Core::isMaster())
236                {
237                    this->server_position_ = this->getPosition();
238                    this->server_orientation_ = this->getOrientation();
239                    this->server_linear_velocity_ = this->getVelocity();
240                    this->server_angular_velocity_ = this->getAngularVelocity();
241                }
242                else if (this->bControlled_)
243                {
244                    this->client_position_ = this->getPosition();
245                    this->client_orientation_ = this->getOrientation();
246                    this->client_linear_velocity_ = this->getVelocity();
247                    this->client_angular_velocity_ = this->getAngularVelocity();
248                }
249            }
250        }
251    }
252
253    void ControllableEntity::registerVariables()
254    {
255        REGISTERSTRING(this->cameraPositionTemplate_, network::direction::toclient);
256
257        REGISTERDATA(this->server_position_,         network::direction::toclient, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerPosition));
258        REGISTERDATA(this->server_linear_velocity_,  network::direction::toclient, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerLinearVelocity));
259        REGISTERDATA(this->server_orientation_,      network::direction::toclient, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerOrientation));
260        REGISTERDATA(this->server_angular_velocity_, network::direction::toclient, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerAngularVelocity));
261
262        REGISTERDATA(this->server_overwrite_,        network::direction::toclient, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::processOverwrite));
263        REGISTERDATA(this->client_overwrite_,        network::direction::toserver);
264
265        REGISTERDATA(this->client_position_,         network::direction::toserver, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientPosition));
266        REGISTERDATA(this->client_linear_velocity_,  network::direction::toserver, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientLinearVelocity));
267        REGISTERDATA(this->client_orientation_,      network::direction::toserver, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientOrientation));
268        REGISTERDATA(this->client_angular_velocity_, network::direction::toserver, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientAngularVelocity));
269
270        REGISTERDATA(this->playerID_, network::direction::toclient, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::networkcallback_changedplayerID));
271    }
272
273    void ControllableEntity::processServerPosition()
274    {
275        if (!this->bControlled_)
276            this->setPosition(this->server_position_);
277    }
278
279    void ControllableEntity::processServerLinearVelocity()
280    {
281        if (!this->bControlled_)
282            this->setVelocity(this->server_linear_velocity_);
283    }
284
285    void ControllableEntity::processServerOrientation()
286    {
287        if (!this->bControlled_)
288            this->setOrientation(this->server_orientation_);
289    }
290
291    void ControllableEntity::processServerAngularVelocity()
292    {
293        if (!this->bControlled_)
294            this->setAngularVelocity(this->server_angular_velocity_);
295    }
296
297    void ControllableEntity::processOverwrite()
298    {
299        if (this->bControlled_)
300        {
301            this->setPosition(this->server_position_);
302            this->setOrientation(this->server_orientation_);
303            this->setVelocity(this->server_linear_velocity_);
304            this->setAngularVelocity(this->server_angular_velocity_);
305
306            this->client_overwrite_ = this->server_overwrite_;
307        }
308    }
309
310    void ControllableEntity::processClientPosition()
311    {
312        if (this->server_overwrite_ == this->client_overwrite_)
313        {
314            this->setPosition(this->client_position_);
315            // The call above increments the overwrite. This is not desired to reduce traffic
316            --this->server_overwrite_;
317        }
318    }
319
320    void ControllableEntity::processClientLinearVelocity()
321    {
322        if (this->server_overwrite_ == this->client_overwrite_)
323        {
324            this->setVelocity(this->client_linear_velocity_);
325            // The call above increments the overwrite. This is not desired to reduce traffic
326            --this->server_overwrite_;
327        }
328    }
329
330    void ControllableEntity::processClientOrientation()
331    {
332        if (this->server_overwrite_ == this->client_overwrite_)
333        {
334            this->setOrientation(this->client_orientation_);
335            // The call above increments the overwrite. This is not desired to reduce traffic
336            --this->server_overwrite_;
337        }
338    }
339
340    void ControllableEntity::processClientAngularVelocity()
341    {
342        if (this->server_overwrite_ == this->client_overwrite_)
343        {
344            this->setAngularVelocity(this->client_angular_velocity_);
345            // The call above increments the overwrite. This is not desired to reduce traffic
346            --this->server_overwrite_;
347        }
348    }
349
350    void ControllableEntity::setPosition(const Vector3& position)
351    {
352        if (Core::isMaster())
353        {
354            MobileEntity::setPosition(position);
355            this->server_position_ = this->getPosition();
356            ++this->server_overwrite_;
357        }
358        else if (this->bControlled_)
359        {
360            MobileEntity::setPosition(position);
361            this->client_position_ = this->getPosition();
362        }
363    }
364
365    void ControllableEntity::setOrientation(const Quaternion& orientation)
366    {
367        if (Core::isMaster())
368        {
369            MobileEntity::setOrientation(orientation);
370            this->server_orientation_ = this->getOrientation();
371            ++this->server_overwrite_;
372        }
373        else if (this->bControlled_)
374        {
375            MobileEntity::setOrientation(orientation);
376            this->client_orientation_ = this->getOrientation();
377        }
378    }
379
380    void ControllableEntity::setVelocity(const Vector3& velocity)
381    {
382        if (Core::isMaster())
383        {
384            MobileEntity::setVelocity(velocity);
385            this->server_linear_velocity_ = this->getVelocity();
386            ++this->server_overwrite_;
387        }
388        else if (this->bControlled_)
389        {
390            MobileEntity::setVelocity(velocity);
391            this->client_linear_velocity_ = this->getVelocity();
392        }
393    }
394
395    void ControllableEntity::setAngularVelocity(const Vector3& velocity)
396    {
397        if (Core::isMaster())
398        {
399            MobileEntity::setAngularVelocity(velocity);
400            this->server_angular_velocity_ = this->getAngularVelocity();
401            ++this->server_overwrite_;
402        }
403        else if (this->bControlled_)
404        {
405            MobileEntity::setAngularVelocity(velocity);
406            this->client_angular_velocity_ = this->getAngularVelocity();
407        }
408    }
409
410    void ControllableEntity::setWorldTransform(const btTransform& worldTrans)
411    {
412        MobileEntity::setWorldTransform(worldTrans);
413        if (Core::isMaster())
414        {
415            this->server_position_ = this->getPosition();
416            this->server_orientation_ = this->getOrientation();
417            this->server_linear_velocity_ = this->getVelocity();
418            this->server_angular_velocity_ = this->getAngularVelocity();
419        }
420        else if (this->bControlled_)
421        {
422            this->client_position_ = this->getPosition();
423            this->client_orientation_ = this->getOrientation();
424            this->client_linear_velocity_ = this->getVelocity();
425            this->client_angular_velocity_ = this->getAngularVelocity();
426        }
427    }
428}
Note: See TracBrowser for help on using the repository browser.