Client* ClientConnectionSet::Add(LPSOCKADDR_IN addr) { int newclientnum; // Get a random uniq client number Client* testclient; do { newclientnum = psserver->rng->Get(0x8fffff); //make clientnum random testclient = FindAny(newclientnum); } while(testclient != NULL); // Have uniq client number, create the new client Client* client = new Client(); if(!client->Initialize(addr, newclientnum)) { Bug1("Client Init failed?!?\n"); delete client; return NULL; } CS::Threading::RecursiveMutexScopedLock lock(mutex); addrHash.PutUnique(SockAddress(client->GetAddress()), client); hash.Put(client->GetClientNum(), client); return client; }
void psMovementManager::HandleMessage(MsgEntry* me) { switch ( me->GetType() ) { case MSGTYPE_MOVEINFO: // Initial info about modes and moves { if (ready) { Bug1("Received second set of movement info!"); return; } psMovementInfoMessage movemsg(me); SetupMovements(movemsg); return; } case MSGTYPE_MOVELOCK: // Movement lockout started { // The server will override any attempts to move during a lockout. // The client should lockout controls too, until the server says otherwise. psMoveLockMessage lockmsg(me); LockMoves(lockmsg.locked); return; } case MSGTYPE_MOVEMOD: // Movement modifier { psMoveModMsg modmsg(me); HandleMod(modmsg); return; } } }
void psMovementManager::SetupMovements(psMovementInfoMessage& movemsg) { #ifdef MOVE_DEBUG printf("\nReceived character modes:\n"); #endif for (size_t i=0; i<movemsg.modes; i++) { uint32 id; const char* name; csVector3 move_mod; csVector3 rotate_mod; const char* idle_anim; movemsg.GetMode(id, name, move_mod, rotate_mod, idle_anim); #ifdef MOVE_DEBUG printf("Got mode: %u, %s, (%.2f,%.2f,%.2f), (%.2f,%.2f,%.2f), %s\n", id,name,move_mod.x,move_mod.y,move_mod.z, rotate_mod.x,rotate_mod.y,rotate_mod.z,idle_anim); #endif psCharMode* newmode = new psCharMode; newmode->id = id; newmode->name = name; newmode->modifier.move = move_mod; newmode->modifier.rotate = rotate_mod; newmode->idle_anim = idle_anim; modes.Put(id,newmode); } if (movemsg.modes == 0) { Bug1("Received no character modes!"); } #ifdef MOVE_DEBUG printf("\nReceived movement types:\n"); #endif for (size_t i=0; i<movemsg.moves; i++) { uint32 id; const char* name; csVector3 base_move; csVector3 base_rotate; movemsg.GetMove(id, name, base_move, base_rotate); #ifdef MOVE_DEBUG printf("Got move: %u, %s, (%.2f,%.2f,%.2f), (%.2f,%.2f,%.2f)\n", id,name,base_move.x,base_move.y,base_move.z, base_rotate.x,base_rotate.y,base_rotate.z); #endif psMovement* newmove = new psMovement; newmove->id = id; newmove->name = name; newmove->motion.move = base_move; newmove->motion.rotate = base_rotate; CS_ASSERT(id < sizeof(activeMoves)*8); moves.Put(id,newmove); } if (movemsg.moves == 0) { Bug1("Received no movement types!"); } forward = FindMovement("forward"); backward = FindMovement("backward"); run = FindCharMode("run"); walk = FindCharMode("normal"); const psMovement* kbdrotL = FindMovement("rotate left"); const psMovement* kbdrotR = FindMovement("rotate right"); if (kbdrotL && kbdrotR) kbdRotate = (1 << kbdrotL->id) | (1 << kbdrotR->id); //TODO: make this configurable? defaultmode = walk; actormode = run; toggleRun = true; ready = true; }
void WeatherManager::HandleWeatherEvent(psWeatherGameEvent* event) { { CS::Threading::MutexScopedLock lock(eventsMutex); events.Delete(event); // Delete this from our "db" } // See if we want to ignore this event for(size_t i = 0; i < ignored.GetSize(); i++) { if(event == ignored[i]) { ignored.DeleteIndex(i); return; } } switch(event->type) { case psWeatherMessage::SNOW: case psWeatherMessage::RAIN: { event->si->current_rain_drops = event->value; Notify4(LOG_WEATHER,"New %s in sector '%s': %d",event->type == psWeatherMessage::SNOW ? "snow" : "rain", event->si->name.GetData(),event->value); psWeatherMessage::NetWeatherInfo info; info.has_downfall = true; info.downfall_is_snow = (event->type == psWeatherMessage::SNOW); info.has_fog = true; info.has_lightning = false; info.downfall_drops = event->value; // Save current fog and calculate new. if(event->value) { // Only save the fog 'history' once. After that we just override. if(!event->si->densitySaved) { event->si->fog_density_old = event->si->fog_density; event->si->densitySaved = true; } // Set fog colour if there's not already fog. if(!event->si->fog_density) { event->si->r = 255; event->si->g = 255; event->si->b = 255; } if(info.downfall_drops < 8000) { // Calculate fog to be linear in range 0 to 200 event->si->fog_density = (int)(200.0f*(info.downfall_drops-1000.0f)/8000.0f); } else { event->si->fog_density = 200; } } else if(event->si->fog_density) { // Restore fog, if the fog wasn't turned off. event->si->fog_density = event->si->fog_density_old; event->si->densitySaved = false; } info.fog_density = event->si->fog_density; info.r = event->si->r; info.g = event->si->g; info.b = event->si->b; info.sector = event->sector; if(event->fade) { info.downfall_fade = event->fade; info.fog_fade = event->fade; } else { if(event->value) { info.downfall_fade = event->si->GetRandomWeatherFadeIn((unsigned int)event->type); info.fog_fade = info.downfall_fade; } else { info.downfall_fade = event->si->GetRandomWeatherFadeOut((unsigned int)event->type); info.fog_fade = info.downfall_fade; } } Notify4(LOG_WEATHER,"Drops: %d Density: %d Sector: %s\n", info.downfall_drops,info.fog_density,info.sector.GetDataSafe()); psWeatherMessage rain(0,info); if(rain.valid) psserver->GetEventManager()->Broadcast(rain.msg,NetBase::BC_EVERYONE); else { Bug1("Could not create valid psWeatherMessage (rain) for broadcast.\n"); } // Make sure we don't have any other events in this sector that will disturb // Simple case is when event types are equal. In addition we have to test // for the mutal exclusive case where we are changing from snow to rain or // rain to snow. { CS::Threading::MutexScopedLock lock(eventsMutex); for(size_t i = 0; i < events.GetSize(); i++) { psWeatherGameEvent* evt = events[i]; if(evt->sector == event->sector && (evt->type == event->type || ((evt->type == psWeatherMessage::RAIN || evt->type == psWeatherMessage::SNOW) && (event->type == psWeatherMessage::RAIN || event->type == psWeatherMessage::SNOW)))) { ignored.Push(evt); // Ignore when the eventmanager handles the event events.DeleteIndex(i); i--; Notify4(LOG_WEATHER,"Removed disturbing event for sector '%s' (%d,%d)", evt->sector.GetData(),evt->value,evt->duration); } } } if(event->value) // Queue event to turn off rain/snow. { if(event->type != psWeatherMessage::SNOW) event->si->is_raining = true; else event->si->is_snowing = true; if(event->si->GetWeatherEnabled((unsigned int) psWeatherMessage::LIGHTNING) && event->value > 2000 && event->si->is_raining) { // Queue lightning during rain storm here first QueueNextEvent(event->si->GetRandomWeatherGap((unsigned int) psWeatherMessage::LIGHTNING), psWeatherMessage::LIGHTNING, 0, 0, 0, event->si->name, event->si, event->clientnum); } // Queue event to stop rain/snow int duration; if(event->duration != -1) { if(event->duration) { duration = event->duration; } else { duration = event->si->GetRandomWeatherDuration((unsigned int) event->type); } QueueNextEvent(duration, event->type, 0, 0, event->fade, event->si->name, event->si); } } else // Stop rain/snow. { if(event->type== psWeatherMessage::SNOW) event->si->is_snowing = false; else event->si->is_raining = false; // Queue event to turn on again later if enabled StartWeather(event->si); } break; } case psWeatherMessage::FOG: { // Update sector weather info event->si->fog_density = event->value; event->si->r = event->cr; event->si->g = event->cg; event->si->b = event->cb; // Update the clients psWeatherMessage::NetWeatherInfo info; info.has_downfall = false; info.downfall_is_snow = false; info.has_fog = true; info.has_lightning = false; info.sector = event->si->name; info.fog_density = event->si->fog_density; info.r = event->cr; info.g = event->cg; info.b = event->cb; info.downfall_drops = 0; info.downfall_fade = 0; Notify3(LOG_WEATHER,"New Fog in sector '%s': %d", event->si->name.GetData(), event->value); // Save the fade in so we can reverse it when fading out. if(event->fade) { event->si->fogFade = event->fade; } else { // We're removing fog, so removed the 'saved' flag. event->si->densitySaved = false; } info.fog_fade = event->si->fogFade; psWeatherMessage fog(0,info); if(fog.valid) psserver->GetEventManager()->Broadcast(fog.msg,NetBase::BC_EVERYONE); else { Bug1("Could not create valid psWeatherMessage (fog) for broadcast.\n"); } if(event->value) // Queue event to turn off fog. { // Queue event to stop rain/snow int duration; if(event->duration != -1) { if(event->duration) { duration = event->duration; } else { duration = event->si->GetRandomWeatherDuration((unsigned int) event->type); } QueueNextEvent(duration, event->type, 0, 0, event->si->GetRandomWeatherFadeOut((unsigned int)psWeatherMessage::FOG), event->si->name, event->si); } } else // Stop fog. { // Queue event to turn on again later if enabled StartWeather(event->si, psWeatherMessage::FOG); } break; } case psWeatherMessage::LIGHTNING: { if(event->si->is_raining) { Notify2(LOG_WEATHER,"Lightning in sector '%s'",event->sector.GetData()); psWeatherMessage::NetWeatherInfo info; info.has_downfall = false; info.downfall_is_snow = false; info.has_fog = false; info.has_lightning = true; info.sector = event->sector; info.fog_fade = info.downfall_fade = 0; info.r = info.g = info.b = 0; info.downfall_drops = info.fog_density = 0; psWeatherMessage lightning(0,info, event->clientnum); if(lightning.valid) { psserver->GetEventManager()->Broadcast(lightning.msg); } else { Bug1("Could not create valid psWeatherMessage (lightning) for broadcast.\n"); } if(event->si->is_raining && event->si->GetWeatherEnabled((unsigned int) psWeatherMessage::LIGHTNING)) { QueueNextEvent(event->si->GetRandomWeatherGap((unsigned int) psWeatherMessage::LIGHTNING), psWeatherMessage::LIGHTNING, 0, 0, 0, event->si->name, event->si, event->clientnum); } } break; } case psWeatherMessage::DAYNIGHT: { QueueNextEvent(GAME_MINUTE_IN_TICKS, psWeatherMessage::DAYNIGHT, 0, 0, 0, NULL, NULL); gameTimeMinute++; if(gameTimeMinute >= 60) { gameTimeMinute = 0; gameTimeHour++; if(gameTimeHour >= 24) { gameTimeHour = 0; gameTimeDay++; if(gameTimeDay >= monthLengths[gameTimeMonth-1]+1) { gameTimeDay = 1; gameTimeMonth++; if(gameTimeMonth >= MONTH_COUNT+1) { gameTimeMonth = 1; gameTimeYear++; } } } // Only save and broadcast every game hour. SaveGameTime(); BroadcastGameTime(); } else { // Super clients should get the time every minute BroadcastGameTimeSuperclients(); } break; } default: { break; } } }