Show connectstate.cpp syntax highlighted
/***************************************************************************
connectstate.cpp
-------------------
begin : Wed Feb 2 2005
copyright : (C) 2005 by Brendon Lloyd Higgins
email : bh_doc@users.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 <client.h>
#include <connectstate.h>
#include <loadstate.h>
#include <playerclient.h>
#include <ClanLib/core.h>
#include <ClanLib/display.h>
#include <iostream>
ConnectState::ConnectState(const CL_IPAddress& serv):
serverIP(serv),
netsession(0),
nextSlot(0),
players(0),
me(0),
state(AWAIT_HANDSHAKE),
next(0) {
}
ConnectState::~ConnectState() {
}
ClientState* ConnectState::go(Client* client) {
netsession = new CL_NetSession(Network::Session::NAME);
CL_Surface w("gui/main/waiting", client->getResources());
CL_Display::get_current_window()->set_cursor(
CL_Sprite("gui/main/mice/busy", client->getResources()));
nextSlot = new CL_Slot(
netsession->sig_netstream_connect(Network::Channel::HANDSHAKE)
.connect(this, &ConnectState::onNetHandshake));
CL_Slot slotDisconnect = netsession->sig_computer_disconnected()
.connect(this, &ConnectState::onDisconnect);
// TODO
// CL_Slot slotSay = netsession->sig_netpacket_receive(
// Channel::SAY).connect(this, &ConnectState::onSay);
CL_Slot slotAdmin = netsession->sig_netpacket_receive(
Network::Channel::ADMIN).connect(this, &ConnectState::onAdmin);
try {
server = netsession->connect(serverIP);
} catch (const CL_Error& e) {
std::cout << "Error: " << e.message << "; Is the server running?"
<< std::endl;
delete nextSlot;
delete netsession;
return 0;
}
while (!(next || state == FAIL)) {
CL_Display::clear(CL_Color(127, 0, 0));
w.draw(0, 0);
CL_Display::flip();
CL_System::keep_alive(50);
}
delete nextSlot;
if (state == FAIL) {
// We've failed. Die. TODO Go back to main menu.
std::cout << "Connection failed!" << std::endl;
for (PlayerList::iterator i = players->begin(); i != players->end();
++i) {
delete *i;
}
delete players;
server.disconnect("Connect failed.");
delete netsession;
return 0;
} else {
return next;
}
}
void ConnectState::onStart(CL_NetStream& stream) {
next = new LoadState(netsession, server, stream, players, me);
}
void ConnectState::onNetHandshake(CL_NetStream& stream) {
stream.output.write_int32(FREEPOP_NETPROTOCOL);
int x = stream.input.read_int32();
if (x != FREEPOP_NETPROTOCOL) {
std::cout << "Can't connect: Different protocol version." << std::endl;
state = FAIL;
return;
}
stream.output.write_uint8(Network::Handshake::PLAY);
if (stream.input.read_bool8()) {
std::cout << "Connected." << std::endl;
} else {
std::cout << "Connection refused." << std::endl;
state = FAIL;
return;
}
players = new PlayerList;
int n = stream.input.read_uint32();
if (n == 0) {
std::cout << "No players sent from server." << std::endl;
state = FAIL;
return;
}
for (int i = 0; i < n; ++i) {
onPlayerCreate(stream.input);
}
if (me == 0) {
std::cout << "No local player sent from server." << std::endl;
state = FAIL;
return;
}
state = AWAIT_START;
delete nextSlot;
nextSlot = new CL_Slot(netsession->sig_netstream_connect(Network::Channel::START)
.connect(this, &ConnectState::onStart));
stream.output.write_bool8(true);
}
void ConnectState::onDisconnect(CL_NetComputer& computer) {
std::cout << "Disconnected from server at "
<< computer.get_address().get_address()
<< " (" << computer.get_disconnect_reason() << ")" << std::endl;
state = FAIL;
if (next) {
delete next;
next = 0;
}
}
void ConnectState::onAdmin(CL_NetPacket& packet, CL_NetComputer &computer) {
// TODO Make sure it's actually from the server.
int type = packet.input.read_int32();
if (type == Network::Admin::PAUSE_DEMAND) {
// Ignore
} else if (type == Network::Admin::UNPAUSE_DEMAND) {
// Ignore
} else if (type == Network::Admin::PLAYER_CREATE) {
onPlayerCreate(packet.input);
} else if (type == Network::Admin::PLAYER_MESSAGE) {
onPlayerMessage(packet);
} else if (type == Network::Admin::PLAYER_REMOVE) {
onPlayerRemove(packet);
} else if (type == Network::Admin::STOP_DEMAND) {
// TODO
// logicState = END;
}
}
void ConnectState::onPlayerCreate(CL_InputSource& is) {
PlayerClient* pl = new PlayerClient(is);
players->push_back(pl);
if (pl->isLocal()) {
me = pl;
std::cout << "You (" << pl->getName() << " # " << pl->getSlot()
<< ") connected." << std::endl;
} else {
std::cout << "Player " << pl->getSlot() << " (" << pl->getName()
<< ") connected." << std::endl;
}
}
void ConnectState::onPlayerMessage(CL_NetPacket& p) {
int s = p.input.read_int32();
PlayerList::iterator i;
for (i = players->begin(); i != players->end() && (*i)->getSlot() != s;
++i) {
// NO-OP.
}
if (i == players->end()) {
return;
}
(*i)->onMessage(p);
}
void ConnectState::onPlayerRemove(CL_NetPacket& p) {
int s = p.input.read_int32();
int r = p.input.read_int32();
PlayerList::iterator i;
for (i = players->begin(); i != players->end() && (*i)->getSlot() != s;
++i) {
// NO-OP.
}
if (i == players->end()) {
return;
}
std::cout << "Player " << s << " (" << (*i)->getName()
<< ") has gone. " << Player::Remove::STRINGS[r] << std::endl;
players->erase(i);
}
See more files for this project here