Show worldclient.cpp syntax highlighted
/***************************************************************************
worldclient.cpp
-------------------
begin : Thu Nov 14 2002
copyright : (C) 2002 by Brendon Higgins
email : freepop-devel@lists.sourceforge.net
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <common.h>
#include <entity.h>
#include <entityclient.h>
#include <entityclientfactory.h>
#include <identity.h>
#include <paintable.h>
#include <playerclient.h>
#include <worldclient.h>
#include <stdexcept>
WorldClient::WorldClient(CL_InputSource* i, CL_NetSession* s, const Rules* r,
const PlayerList* p):
map(i, s), rules(r), players(p),
slotMessage(s->sig_netpacket_receive(Network::Channel::ENTITY)
.connect(this, &WorldClient::onMessage)) {
}
WorldClient::~WorldClient() {
clearEntities();
clearPaintables();
}
MapClient* WorldClient::getMap() {
return ↦
}
const MapClient* WorldClient::getMap() const {
return ↦
}
WorldClient::EntityClientList* WorldClient::getEntities() {
return &entities;
}
const WorldClient::EntityClientList* WorldClient::getEntities() const {
return &entities;
}
void WorldClient::addEntity(EntityClient* e) {
entities.push_back(e);
paintablesAdd(e);
}
void WorldClient::destroyEntity(EntityClient* e) {
for (EntityClientList::iterator i(entities.begin());
i != entities.end(); ++i) {
if (*i == e) {
paintablesErase(e);
delete e;
entities.erase(i);
break;
}
}
}
EntityClient* WorldClient::findEntity(const Identity& id) {
for (EntityClientList::iterator i(entities.begin());
i != entities.end(); ++i) {
if ((*i)->getIdentity() == id) {
return *i;
}
}
return 0;
}
void WorldClient::clearEntities() {
for (EntityClientList::iterator i(entities.begin());
i != entities.end(); ++i) {
paintablesErase(*i);
delete *i;
}
entities.clear();
}
void WorldClient::paintablesAdd(Paintable* d) {
paintables.push_back(d);
}
void WorldClient::paintablesErase(Paintable* d) {
for (PaintableIterator i = paintables.begin(); i != paintables.end(); ++i) {
if (*i == d) {
paintables.erase(i);
return;
}
}
}
void WorldClient::clearPaintables() {
for (PaintableIterator i = paintables.begin(); i != paintables.end(); ++i) {
delete (*i);
}
paintables.clear();
}
void WorldClient::drawUpdate(unsigned int d) {
sortPaintables();
PaintableIterator i = paintables.begin();
while (i != paintables.end()) {
if (!(*i)->drawUpdate(this, d)) {
delete (*i);
i = paintables.erase(i);
continue;
}
++i;
}
}
void WorldClient::draw() const {
map.draw();
for (PaintableList::const_iterator i = paintables.begin();
i != paintables.end(); ++i) {
(*i)->draw(this);
}
}
void WorldClient::predict(unsigned int d) {
for (EntityClientList::iterator i(entities.begin()); i != entities.end();
++i) {
(*i)->predict(this, d);
}
}
void WorldClient::playerColourChange() {
for (PaintableIterator i = paintables.begin(); i != paintables.end(); ++i) {
(*i)->playerColourChange(this);
}
}
const Rules* WorldClient::getRules() const {
return rules;
}
const PlayerClient* WorldClient::findPlayer(int s) const {
for (PlayerList::const_iterator i = players->begin(); i != players->end();
++i) {
if (s == (*i)->getSlot()) {
return *i;
}
}
assert(0 && "No player found!");
return 0;
}
const Rotation& WorldClient::getDisplayRotation() const {
return getMap()->getDisplayRotation();
}
void WorldClient::displayRotateClock() {
getMap()->displayRotateClock();
displayRotationChange(getDisplayRotation());
}
void WorldClient::displayRotateAnti() {
getMap()->displayRotateAnti();
displayRotationChange(getDisplayRotation());
}
void WorldClient::sortPaintables() {
// Use stable_sort to avoid flickering sprites.
std::stable_sort(paintables.begin(), paintables.end(),
PaintableSorter(this));
}
WorldClient::PaintableSorter::PaintableSorter(const WorldClient* w): c(w) {
}
bool WorldClient::PaintableSorter::operator()(Paintable* d1, Paintable* d2) {
return d1->drawSortIndex(c) < d2->drawSortIndex(c);
}
void WorldClient::onMessage(CL_NetPacket& p, CL_NetComputer &c) {
// TODO Make sure it's actually coming from the server.
Identity id = Identity::extract(p.input);
int m = p.input.read_uint16();
if (m == Entity::Message::CREATE) {
EntityClient* e = EntityClientFactory::build(this, p, id);
if (!e) {
throw std::runtime_error("Error creating entity.");
}
addEntity(e);
} else {
EntityClient* e = findEntity(id);
if (!e) {
// Tell the server we'd like a proper CREATE message.
CL_NetPacket out;
out.output.write_uint32(Network::Admin::ENTITY_SEND_CREATE);
id.inject(out.output);
c.send(Network::Channel::ADMIN, out);
return;
}
if (m == Entity::Message::FULL_UPDATE) {
e->onFullUpdate(this, p);
} else if (m == Entity::Message::DESTROY) {
e->onDestroy(this, p.input.read_uint32());
destroyEntity(e);
} else {
e->onMessage(this, m, p);
}
}
}
void WorldClient::displayRotationChange(const Rotation& r) {
for (PaintableIterator i = paintables.begin(); i != paintables.end(); ++i) {
(*i)->displayRotationChange(this, r);
}
sortPaintables();
}
See more files for this project here