bool GameSession::init() { Game::shared().getEventManager()->addEventHandler(EVENT_GAME_FULLSTATE, this); input = new GameSessionInput(this); input->init(); if(!initShaders()) return false; if(!initVertices()) return false; Root::shared().addInputListener(input); Root::shared().addFrameListener(input); Root::shared().addFrameListener(this); // init factions localFaction = new Faction; localFaction->setColor(0); factions.push_back(localFaction); Faction* otherFaction = new Faction; otherFaction->setColor(1); factions.push_back(otherFaction); Scene* scene = Root::shared().makeDefaultScene(); if(!scene) return false; Camera* cam = scene->getCamera(); cam->setPosition(vec3(0.0f, 150.0f, 0.0f)); cam->setCameraAngle(0.0f, -60.0f); cam->setZoom(300.0f); Object* obj; // init map vector<Arya::Material*> tileSet; tileSet.push_back(Arya::MaterialManager::shared().getMaterial("grass.tga")); tileSet.push_back(Arya::MaterialManager::shared().getMaterial("rock.tga")); tileSet.push_back(Arya::MaterialManager::shared().getMaterial("snow.tga")); tileSet.push_back(Arya::MaterialManager::shared().getMaterial("dirt.tga")); vector<Arya::Texture*> skyset; skyset.push_back(Arya::TextureManager::shared().getTexture("transparentClouds.png")); skyset.push_back(Arya::TextureManager::shared().getTexture("stars.jpg")); if(!scene->setMap("heightmap.raw", "watermap.raw", tileSet, skyset, Arya::TextureManager::shared().getTexture("splatmap.tga"))) return false; for(int i = 0; i < 30; ++ i) { Unit* unit = new Unit(0); float heightModel = Root::shared().getScene()->getMap()->getTerrain()->heightAtGroundPosition(20.0f * (i / 10), -50.0f+20.0f*(i % 10)); obj = scene->createObject(); obj->setModel(ModelManager::shared().getModel("ogros.aryamodel")); obj->setAnimation("stand"); unit->setObject(obj); unit->setPosition(vec3(20 * (i / 10), heightModel, -50 + 20 * (i % 10))); localFaction->addUnit(unit); } for(int i = 0; i < 30; ++ i) { Unit* unit = new Unit(0); float heightModel = Root::shared().getScene()->getMap()->getTerrain()->heightAtGroundPosition(-100.0f + 20.0f * (i / 10), -100.0f+20.0f*(i % 10)); obj = scene->createObject(); obj->setModel(ModelManager::shared().getModel("ogros.aryamodel")); obj->setAnimation("stand"); unit->setObject(obj); unit->setPosition(vec3(-100.0 + 20 * (i / 10), heightModel, -100.0 + 20 * (i % 10))); otherFaction->addUnit(unit); } for(int i = 0; i < 10; ++ i) { Unit* unit = new Unit(1); float heightModel = Root::shared().getScene()->getMap()->getTerrain()->heightAtGroundPosition(-200.0f + 20.0f * (i / 10), -50.0f+20.0f*(i % 10)); obj = scene->createObject(); obj->setModel(ModelManager::shared().getModel("hep.aryamodel")); obj->setAnimation("stand"); unit->setObject(obj); unit->setPosition(vec3(-200.0f + 20 * (i / 10), heightModel, -50 + 20 * (i % 10))); localFaction->addUnit(unit); } selectionDecalHandle = 0; Texture* selectionTex = TextureManager::shared().getTexture("selection.png"); if(selectionTex) selectionDecalHandle = selectionTex->handle; return true; }
void ClientGameSession::handleEvent(Packet& packet) { int id = packet.getId(); switch(id) { case EVENT_GAME_FULLSTATE: { int newGameTime; packet >> newGameTime; GAME_LOG_DEBUG("Full game state received. Old gametimer = " << gameTimer << ". New server gametime = " << newGameTime << ". Estimated delay = " << Game::shared().getNetworkDelay()); //Round the delay to 10 ms so that the game timer is always a multiple of 10 ms gameTimer = newGameTime + ((int)(Game::shared().getNetworkDelay()*1000)/10)*10; int count; packet >> count; for(int i = 0; i < count; ++i) { int clientId; packet >> clientId; int factionId; packet >> factionId; Faction* faction = getFactionById(factionId); if(!faction) { faction = createFaction(factionId); factions.push_back(faction); } faction->deserialize(packet); faction->setClientId(clientId); if(clientId == Game::shared().getClientId()) localFaction = faction; //If any of the units that we have was NOT sent in this list they must be deleted //So we keep a list of IDs that we have and check which ones are in the packet //This method might be a bit slow but this process only happens in rare situations //so we do not bother adding extra member variables to the unit class to accomplish this vector<int> allIDs; for(list<Unit*>::iterator it = factions[i]->getUnits().begin(); it != factions[i]->getUnits().end(); ++it) allIDs.push_back((*it)->getId()); int unitCount; packet >> unitCount; for(int i = 0; i < unitCount; ++i) { int id; packet >> id; for(vector<int>::iterator iter = allIDs.begin(); iter != allIDs.end(); ++iter) if( *iter == id ){ allIDs.erase(iter); break; } Unit* unit = getUnitById(id); bool newUnit = false; if(!unit) { newUnit = true; unit = createUnit(id, 0); } unit->deserialize(packet); if(faction == localFaction) unit->setLocal(true); Object* obj = unit->getObject(); if(!obj) obj = Root::shared().getScene()->createObject(); obj->setModel(ModelManager::shared().getModel(unit->getInfo()->modelname + ".aryamodel")); obj->setAnimation("stand"); unit->setObject(obj); float heightModel = map->heightAtGroundPosition(unit->getPosition().x, unit->getPosition().z); unit->setPosition(vec3(unit->getPosition().x, heightModel, unit->getPosition().z)); if(newUnit) faction->addUnit(unit); if(unit->getType() == 2 && faction == localFaction) { input->setSpecPos(unit->getPosition()); } unit->getInfo()->onSpawn(unit); } //now allIDs contains a list of units that were not in the packet so they must be deleted //note that we can not just delete them because of reference counts and so on. //we make them obsolte so that they are deleted next frame for(vector<int>::iterator iter = allIDs.begin(); iter != allIDs.end(); ++iter) { Unit* unit = getUnitById(*iter); //if unit == 0 then there are some serious issues ;) if(unit) unit->markForDelete(); } } rebuildCellList(); } break; case EVENT_CLIENT_CONNECTED: { int clientId; packet >> clientId; int factionId; packet >> factionId; Faction* faction = createFaction(clientId); faction->deserialize(packet); faction->setClientId(clientId); factions.push_back(faction); if(clientId == Game::shared().getClientId()) localFaction = faction; int unitCount; packet >> unitCount; for(int i = 0; i < unitCount; ++i) { int id; packet >> id; Unit* unit = createUnit(id, 0); unit->deserialize(packet); if(faction == localFaction) unit->setLocal(true); Object* obj = Root::shared().getScene()->createObject(); obj->setModel(ModelManager::shared().getModel(unit->getInfo()->modelname + ".aryamodel")); obj->setAnimation("stand"); unit->setObject(obj); float heightModel = map->heightAtGroundPosition(unit->getPosition().x, unit->getPosition().z); unit->setPosition(vec3(unit->getPosition().x, heightModel, unit->getPosition().z)); faction->addUnit(unit); } } break; case EVENT_CLIENT_DISCONNECTED: { int id; packet >> id; GAME_LOG_INFO("Client " << id << " disconnected."); for(vector<Faction*>::iterator iter = factions.begin(); iter != factions.end(); ++iter) { if( (*iter)->getClientId() == id ) { GAME_LOG_INFO("Client " << id << " removed from game session. NOT removing faction!"); //delete *iter; //iter = factions.erase(iter); break; } } } break; case EVENT_MOVE_UNIT: { int timeStamp; packet >> timeStamp; int numUnits; packet >> numUnits; GAME_LOG_DEBUG("Move packet for " << numUnits << " units. " << (gameTimer - timeStamp) << " ms delay. Sent at server-gametime " << timeStamp << ". Recieved at client-gametime " << gameTimer); int unitId; int nodeCount; vec2 pos; float yaw; vec2 tempPos; vector<vec2> pathNodes; for(int i = 0; i < numUnits; ++i) { packet >> unitId; packet >> pos; packet >> yaw; packet >> nodeCount; pathNodes.clear(); for(int i = 0; i < nodeCount; ++i){ packet >> tempPos; pathNodes.push_back(tempPos); } Unit* unit = getUnitById(unitId); if(unit) unit->setUnitMovement(timeStamp, pos, yaw, pathNodes); } break; } case EVENT_ATTACK_MOVE_UNIT: { int timeStamp; packet >> timeStamp; int numUnits; packet >> numUnits; int unitId, targetUnitId; for(int i = 0; i < numUnits; ++i) { packet >> unitId >> targetUnitId; Unit* unit = getUnitById(unitId); Unit* targetUnit = getUnitById(targetUnitId); if(unit && targetUnit) unit->setTargetUnit(timeStamp, targetUnit); } break; } case EVENT_UNIT_DIED: { int id; packet >> id; Unit* unit = getUnitById(id); if(unit) { unit->makeDead(); unit->getInfo()->onDeath(unit); } } break; case EVENT_UNIT_SPAWNED: { int factionId, unitId; packet >> factionId >> unitId; Faction* faction = getFactionById(factionId); if(!faction) { GAME_LOG_WARNING("Unit spawn packet received for invalid faction!"); } else { Unit* unit = getUnitById(unitId); bool newUnit = false; if(unit) GAME_LOG_WARNING("Spawn packet for unit that already existed"); else { newUnit = true; unit = createUnit(unitId, 0); } unit->deserialize(packet); if(faction == localFaction) unit->setLocal(true); if(newUnit) unit->setCellFromList(unitCells); Object* obj = unit->getObject(); if(!obj) obj = Root::shared().getScene()->createObject(); obj->setModel(ModelManager::shared().getModel(unit->getInfo()->modelname + ".aryamodel")); obj->setAnimation("stand"); unit->setObject(obj); float heightModel = map->heightAtGroundPosition(unit->getPosition().x, unit->getPosition().z); unit->setPosition(vec3(unit->getPosition().x, heightModel, unit->getPosition().z)); //This must happen after the object is set, because //then it will set the correct tint color if(newUnit) faction->addUnit(unit); unit->getInfo()->onSpawn(unit); } } break; case EVENT_PLAYER_DEFEAT: { int factionID; packet >> factionID; LOG_INFO("Player lost: " << factionID + 1); Arya::SoundManager::shared().play("defeat.wav"); } break; case EVENT_PLAYER_VICTORY: { int factionID; packet >> factionID; LOG_INFO("Game won by player: " << factionID + 1); Arya::SoundManager::shared().play("victory.wav"); } break; default: GAME_LOG_INFO("ClientGameSession: unknown event received! (" << id << ")"); break; } }