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;
}
Beispiel #4
0
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;
    }
    }
}