/* * PVVMUD a 3D MUD * Copyright (C) 1998-1999 Programvareverkstedet (pvv@pvv.org) * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "server.H" #include <iostream.h> #include "mud.H" //#include "cell.H" //#include "area.H" #include "srvgosmanager.H" #include "option.H" CMud::CMud(COption *option){ TRACE_CREATE("Mud"); m_option = option; m_userDB = new CUserDB(m_option->getString("userdb")); m_mudTime = 0; m_timeKeeper = new CTimeKeeper(); m_markedClient = FALSE; m_markedGOS = FALSE; m_markedWorld = FALSE; m_clientList = new CObjectList(); m_gosList = new CObjectList(); m_worldList = new CObjectList(); m_clientSocket = new CMudSrvSocket(this,option->getInt("port"),m_timeKeeper); m_GOSSocket = new CSrvGOSSrvSocket(this,option->getInt("gos_port"), m_timeKeeper); m_worldSocket =new CSrvWorldSrvSocket(this,option->getInt("world_port"), m_timeKeeper); m_timeKeeper->addHeartBeat(SCHEDULE_INTERVAL,this); m_gos = NULL; m_geoCache = new CSrvGEOCache(this); } CMud::~CMud(){ TRACE_DELETE("Mud"); if (m_clientList != NULL) { m_clientList->deleteAll(); delete m_clientList; } if (m_gosList != NULL) { m_gosList->deleteAll(); delete m_gosList; } if (m_clientSocket != NULL) delete m_clientSocket; if (m_GOSSocket != NULL) delete m_GOSSocket; if (m_world != NULL) delete m_world; if (m_gos != NULL) delete m_gos; } CSrvWorld * CMud::getWorld(){ return m_world; } COption * CMud::getOption(){ return m_option; } CUserDB * CMud::getUserDB(){ return m_userDB; } void CMud::addClient(CClientManager * client){ m_clientList->addLast(client); } void CMud::removeClient(CClientManager * client){ m_clientList->remove(client); } void CMud::checkMarkedClient(){ CObjectListItem * item = m_clientList->getFirst(); while (item != NULL){ CClientManager * client = (CClientManager*)item->getObject(); item = item->getNext(); if (client->getQuit()){ removeClient(client); delete client; } } } void CMud::addGOS(CSrvGOSManager * gos){ m_gosList->addLast(gos); } void CMud::removeGOS(CSrvGOSManager * gos){ m_gosList->remove(gos); } void CMud::checkMarkedGOS(){ CObjectListItem * item = m_gosList->getFirst(); while (item != NULL){ CSrvGOSManager * gos = (CSrvGOSManager*)item->getObject(); item = item->getNext(); if (gos->getOnLine()){ // First time this it true notify everybody that are waiting for a GOS. if (m_gos == NULL){ try { m_gos = new CSrvGOS(this,m_timeKeeper,gos->getAddress()); } catch (CException * e){ cdebug << *e << "\nERROR: Failed to connect to gos: " << gos->getAddress()->getAddressString() << "\n"; delete e; } } gos->setRunning(); } if (gos->getQuit()){ cdebug << "Removing GOS from server\n"; removeGOS(gos); delete gos; // Remove gos: Have to include a test to check if this is the gos // that went down. if (m_gos != NULL){ delete m_gos; m_gos = NULL; } } } } CInetAddress * CMud::getGOSAddress(){ CSrvGOSManager * foundGOS = NULL; int foundNum; CObjectListItem * item = m_gosList->getFirst(); while (item != NULL){ CSrvGOSManager * gos = (CSrvGOSManager*)item->getObject(); item = item->getNext(); if (gos->getRunning()){ if ((foundGOS == NULL) || (gos->getNumClients() < foundNum)){ foundNum = gos->getNumClients(); foundGOS = gos; } } } if (foundGOS != NULL){ foundGOS->addNumClients(); return foundGOS->getAddress(); } return NULL; } int CMud::freeGOSAddress(CInetAddress * address){ CObjectListItem * item = m_gosList->getFirst(); while (item != NULL){ CSrvGOSManager * gos = (CSrvGOSManager*)item->getObject(); item = item->getNext(); if (gos->getAddress() == address){ gos->addNumClients(-1); return TRUE; } } return FALSE; } void CMud::addWorld(CSrvWorldManager * worldSrv){ m_worldList->addLast(worldSrv); } void CMud::removeWorld(CSrvWorldManager * worldSrv){ m_worldList->remove(worldSrv); if (m_world != NULL) m_world->removeListener( worldSrv ); } void CMud::checkMarkedWorld(){ CObjectListItem * item = m_worldList->getFirst(); while (item != NULL){ CSrvWorldManager * worldSrv = (CSrvWorldManager*)item->getObject(); item = item->getNext(); if (worldSrv->getOnLine()){ // First time this it true notify everybody that are waiting for a // world server. if (m_world != NULL){ m_world->addListener( worldSrv ); m_world->sendWorld( worldSrv ); } worldSrv->setRunning(); } if (worldSrv->getQuit()){ cdebug << "Removing WorldSrv from server\n"; removeWorld(worldSrv); delete worldSrv; } } } CInetAddress * CMud::getWorldSrvAddress(){ CSrvWorldManager * foundWorld = NULL; int foundNum; CObjectListItem * item = m_worldList->getFirst(); while (item != NULL){ CSrvWorldManager * worldSrv = (CSrvWorldManager*)item->getObject(); item = item->getNext(); if (worldSrv->getRunning()){ if ((foundWorld == NULL) || (worldSrv->getNumClients() < foundNum)){ foundNum = worldSrv->getNumClients(); foundWorld = worldSrv; } } } if (foundWorld != NULL){ foundWorld->addNumClients(); return foundWorld->getAddress(); } return NULL; } int CMud::freeWorldAddress(CInetAddress * address){ CObjectListItem * item = m_worldList->getFirst(); while (item != NULL){ CSrvWorldManager * worldSrv = (CSrvWorldManager*)item->getObject(); item = item->getNext(); if (worldSrv->getAddress() == address){ worldSrv->addNumClients(-1); return TRUE; } } return FALSE; } int CMud::timeKeeperHB(){ m_mudTime ++; // cdebug << "Schedule Mud Time = " << m_mudTime << " tics\n"; if (m_markedClient){ checkMarkedClient(); m_markedClient = FALSE; } if (m_markedGOS){ checkMarkedGOS(); m_markedGOS = FALSE; } if (m_markedWorld){ checkMarkedWorld(); m_markedWorld = FALSE; } // m_world->animate( (double)SCHEDULE_INTERVAL / 1000.0 ); m_world->animate( ); return TRUE; } void CMud::loadWorld(){ m_world = newWorld(); createWorld(m_world); CObjectListItem * item = m_worldList->getFirst(); while (item != NULL){ CSrvWorldManager * worldSrv = (CSrvWorldManager*)item->getObject(); item = item->getNext(); if (worldSrv->getRunning()) m_world->addListener(worldSrv); } } CSrvWorld * CMud::newWorld(){ return new CSrvWorld(this); } void CMud::createWorld(CSrvWorld * world){ cdebug << "CreateWorld not overloaded!\n"; } void CMud::run(){ loadWorld(); m_timeKeeper->mainLoop(); } void CMud::stop(){ m_timeKeeper->stopLoop(); } void CMud::request(int requestType,int requestId){ if (m_gos != NULL) m_gos->request(requestType,requestId); } void CMud::error(){ } void CMud::geometry(CGeometry * geometry){ CGeometry * geo = (CGeometry*)m_geoCache->add(geometry->getId(),geometry); if (geo != NULL) delete geo; // char name[256]; // sprintf(name,"tmp/%i.geo",geometry->getId()); // FILE * geofile = fopen(name,"w"); // geometry->writeBOG(geofile); // fclose(geofile); } void CMud::material(CMaterial * material){ delete material; } void CMud::texture(CTexture * texture){ delete texture; } CGeometry * CMud::getGeometry(DWORD geometryId){ return (CGeometry*)m_geoCache->get(geometryId); } /////////////////////////////////////////////////////////////////////////////// // chatMessage // Send a message to every client connected /////////////////////////////////////////////////////////////////////////////// void CMud::chatMessage(const char * message){ CObjectListItem * item = m_clientList->getFirst(); while (item != NULL){ CClientManager * client = (CClientManager*)item->getObject(); item = item->getNext(); client->sendMsg( message ); } }