示例#1
0
void CCountryFlags::LoadCountryflagsIndexfile()
{
	IOHANDLE File = Storage()->OpenFile("countryflags/index.txt", IOFLAG_READ, IStorageTW::TYPE_ALL);
	if(!File)
	{
		Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", "couldn't open index file");
		return;
	}

	char aOrigin[128];
	CLineReader LineReader;
	LineReader.Init(File);
	char *pLine;
	while((pLine = LineReader.Get()))
	{
		if(!str_length(pLine) || pLine[0] == '#') // skip empty lines and comments
			continue;

		str_copy(aOrigin, pLine, sizeof(aOrigin));
		char *pReplacement = LineReader.Get();
		if(!pReplacement)
		{
			Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", "unexpected end of index file");
			break;
		}

		if(pReplacement[0] != '=' || pReplacement[1] != '=' || pReplacement[2] != ' ')
		{
			char aBuf[128];
			str_format(aBuf, sizeof(aBuf), "malform replacement for index '%s'", aOrigin);
			Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", aBuf);
			continue;
		}

		int CountryCode = str_toint(pReplacement+3);
		if(CountryCode < CODE_LB || CountryCode > CODE_UB)
		{
			char aBuf[128];
			str_format(aBuf, sizeof(aBuf), "country code '%i' not within valid code range [%i..%i]", CountryCode, CODE_LB, CODE_UB);
			Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", aBuf);
			continue;
		}

		// load the graphic file
		char aBuf[128];
		CImageInfo Info;
		if(g_Config.m_ClLoadCountryFlags)
		{
			str_format(aBuf, sizeof(aBuf), "countryflags/%s.png", aOrigin);
			if(!Graphics()->LoadPNG(&Info, aBuf, IStorageTW::TYPE_ALL))
			{
				char aMsg[128];
				str_format(aMsg, sizeof(aMsg), "failed to load '%s'", aBuf);
				Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", aMsg);
				continue;
			}
		}

		// add entry
		CCountryFlag CountryFlag;
		CountryFlag.m_CountryCode = CountryCode;
		str_copy(CountryFlag.m_aCountryCodeString, aOrigin, sizeof(CountryFlag.m_aCountryCodeString));
		if(g_Config.m_ClLoadCountryFlags)
		{
			CountryFlag.m_Texture = Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0);
			mem_free(Info.m_pData);
		}
		else
			CountryFlag.m_Texture = -1;
		if(g_Config.m_Debug)
		{
			str_format(aBuf, sizeof(aBuf), "loaded country flag '%s'", aOrigin);
			Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", aBuf);
		}
		m_aCountryFlags.add_unsorted(CountryFlag);
	}
	io_close(File);
	m_aCountryFlags.sort_range();

	// find index of default item
	int DefaultIndex = 0, Index = 0;
	for(sorted_array<CCountryFlag>::range r = m_aCountryFlags.all(); !r.empty(); r.pop_front(), ++Index)
		if(r.front().m_CountryCode == -1)
		{
			DefaultIndex = Index;
			break;
		}

	// init LUT
	if(DefaultIndex != 0)
		for(int i = 0; i < CODE_RANGE; ++i)
			m_CodeIndexLUT[i] = DefaultIndex;
	else
		mem_zero(m_CodeIndexLUT, sizeof(m_CodeIndexLUT));
	for(int i = 0; i < m_aCountryFlags.size(); ++i)
		m_CodeIndexLUT[max(0, (m_aCountryFlags[i].m_CountryCode-CODE_LB)%CODE_RANGE)] = i;
}
示例#2
0
文件: ctf.cpp 项目: Susa/teeworlds
void CGameControllerCTF::Tick()
{
	IGameController::Tick();

	if(GameServer()->m_World.m_ResetRequested || GameServer()->m_World.m_Paused)
		return;

	for(int fi = 0; fi < 2; fi++)
	{
		CFlag *F = m_apFlags[fi];

		if(!F)
			continue;

		// flag hits death-tile or left the game layer, reset it
		if(GameServer()->Collision()->GetCollisionAt(F->m_Pos.x, F->m_Pos.y)&CCollision::COLFLAG_DEATH || F->GameLayerClipped(F->m_Pos))
		{
			GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", "flag_return");
			GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN);
			F->Reset();
			continue;
		}

		//
		if(F->m_pCarryingCharacter)
		{
			// update flag position
			F->m_Pos = F->m_pCarryingCharacter->m_Pos;

			if(m_apFlags[fi^1] && m_apFlags[fi^1]->m_AtStand)
			{
				if(distance(F->m_Pos, m_apFlags[fi^1]->m_Pos) < CFlag::ms_PhysSize + CCharacter::ms_PhysSize)
				{
					// CAPTURE! \o/
					m_aTeamscore[fi^1] += 100;
					F->m_pCarryingCharacter->GetPlayer()->m_Score += 5;

					char aBuf[512];
					str_format(aBuf, sizeof(aBuf), "flag_capture player='%d:%s'",
						F->m_pCarryingCharacter->GetPlayer()->GetCID(),
						Server()->ClientName(F->m_pCarryingCharacter->GetPlayer()->GetCID()));
					GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);

					float CaptureTime = (Server()->Tick() - F->m_GrabTick)/(float)Server()->TickSpeed();
					if(CaptureTime <= 60)
					{
						str_format(aBuf, sizeof(aBuf), "The %s flag was captured by '%s' (%d.%s%d seconds)", fi ? "blue" : "red", Server()->ClientName(F->m_pCarryingCharacter->GetPlayer()->GetCID()), (int)CaptureTime%60, ((int)(CaptureTime*100)%100)<10?"0":"", (int)(CaptureTime*100)%100);
					}
					else
					{
						str_format(aBuf, sizeof(aBuf), "The %s flag was captured by '%s'", fi ? "blue" : "red", Server()->ClientName(F->m_pCarryingCharacter->GetPlayer()->GetCID()));
					}
					GameServer()->SendChat(-1, -2, aBuf);
					for(int i = 0; i < 2; i++)
						m_apFlags[i]->Reset();

					GameServer()->CreateSoundGlobal(SOUND_CTF_CAPTURE);
				}
			}
		}
		else
		{
			CCharacter *apCloseCCharacters[MAX_CLIENTS];
			int Num = GameServer()->m_World.FindEntities(F->m_Pos, CFlag::ms_PhysSize, (CEntity**)apCloseCCharacters, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
			for(int i = 0; i < Num; i++)
			{
				if(!apCloseCCharacters[i]->IsAlive() || apCloseCCharacters[i]->GetPlayer()->GetTeam() == TEAM_SPECTATORS || GameServer()->Collision()->IntersectLine(F->m_Pos, apCloseCCharacters[i]->m_Pos, NULL, NULL))
					continue;

				if(apCloseCCharacters[i]->GetPlayer()->GetTeam() == F->m_Team)
				{
					// return the flag
					if(!F->m_AtStand)
					{
						CCharacter *pChr = apCloseCCharacters[i];
						pChr->GetPlayer()->m_Score += 1;

						char aBuf[256];
						str_format(aBuf, sizeof(aBuf), "flag_return player='%d:%s'",
							pChr->GetPlayer()->GetCID(),
							Server()->ClientName(pChr->GetPlayer()->GetCID()));
						GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);

						GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN);
						F->Reset();
					}
				}
				else
				{
					// take the flag
					if(F->m_AtStand)
					{
						m_aTeamscore[fi^1]++;
						F->m_GrabTick = Server()->Tick();
					}

					F->m_AtStand = 0;
					F->m_pCarryingCharacter = apCloseCCharacters[i];
					F->m_pCarryingCharacter->GetPlayer()->m_Score += 1;

					char aBuf[256];
					str_format(aBuf, sizeof(aBuf), "flag_grab player='%d:%s'",
						F->m_pCarryingCharacter->GetPlayer()->GetCID(),
						Server()->ClientName(F->m_pCarryingCharacter->GetPlayer()->GetCID()));
					GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);

					for(int c = 0; c < MAX_CLIENTS; c++)
					{
						CPlayer *pPlayer = GameServer()->m_apPlayers[c];
						if(!pPlayer)
							continue;

						if((pPlayer->GetTeam() == TEAM_SPECTATORS || pPlayer->m_DeadSpecMode) && pPlayer->GetSpectatorID() != SPEC_FREEVIEW &&
							GameServer()->m_apPlayers[pPlayer->GetSpectatorID()] && GameServer()->m_apPlayers[pPlayer->GetSpectatorID()]->GetTeam() == fi)
							GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_EN, c);
						else if(pPlayer->GetTeam() == fi)
							GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_EN, c);
						else
							GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_PL, c);
					}
					// demo record entry
					GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_EN, -2);
					break;
				}
			}

			if(!F->m_pCarryingCharacter && !F->m_AtStand)
			{
				if(Server()->Tick() > F->m_DropTick + Server()->TickSpeed()*30)
				{
					GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN);
					F->Reset();
				}
				else
				{
					F->m_Vel.y += GameServer()->m_World.m_Core.m_Tuning.m_Gravity;
					GameServer()->Collision()->MoveBox(&F->m_Pos, &F->m_Vel, vec2(F->ms_PhysSize, F->ms_PhysSize), 0.5f);
				}
			}
		}
	}
}
static int engine_find_datadir(char *argv0)
{
	/* 1) use provided data-dir override */
	if(datadir[0])
	{
		if(fs_is_dir(datadir))
			return 0;
		else
		{
			dbg_msg("engine/datadir", "specified data-dir '%s' does not exist", datadir);
			return -1;
		}
	}
	
	/* 2) use data-dir in PWD if present */
	if(fs_is_dir("data"))
	{
		strcpy(datadir, "data");
		return 0;
	}
	
	/* 3) use compiled-in data-dir if present */
	if (fs_is_dir(DATA_DIR))
	{
		strcpy(datadir, DATA_DIR);
		return 0;
	}
	
	/* 4) check for usable path in argv[0] */
	{
		unsigned int pos = strrchr(argv0, '/') - argv0;
		
		if (pos < sizeof(datadir))
		{
			char basedir[sizeof(datadir)];
			strncpy(basedir, argv0, pos);
			basedir[pos] = '\0';
			str_format(datadir, sizeof(datadir), "%s/data", basedir);
			
			if (fs_is_dir(datadir))
				return 0;
		}
	}
	
#if defined(CONF_FAMILY_UNIX)
	/* 5) check for all default locations */
	{
		const char *sdirs[] = {
			"/usr/share/teeworlds",
			"/usr/local/share/teeworlds"
			"/opt/teeworlds"
		};
		const int sdirs_count = sizeof(sdirs) / sizeof(sdirs[0]);
		
		int i;
		for (i = 0; i < sdirs_count; i++)
		{
			if (fs_is_dir(sdirs[i]))
			{
				strcpy(datadir, sdirs[i]);
				return 0;
			}
		}
	}
#endif
	
	/* no data-dir found */
	dbg_msg("engine/datadir", "warning no data directory found");
	return -1;
}
示例#4
0
int vout_snapshot_SaveImage(char **name, int *sequential,
                             const block_t *image,
                             vlc_object_t *object,
                             const vout_snapshot_save_cfg_t *cfg)
{
    /* */
    char *filename;
    DIR *pathdir = vlc_opendir(cfg->path);
    if (pathdir != NULL) {
        /* The use specified a directory path */
        closedir(pathdir);

        /* */
        char *prefix = NULL;
        if (cfg->prefix_fmt)
            prefix = str_format(object, cfg->prefix_fmt);
        if (prefix)
            filename_sanitize(prefix);
        else {
            prefix = strdup("vlcsnap-");
            if (!prefix)
                goto error;
        }

        if (cfg->is_sequential) {
            for (int num = cfg->sequence; ; num++) {
                struct stat st;

                if (asprintf(&filename, "%s" DIR_SEP "%s%05d.%s",
                             cfg->path, prefix, num, cfg->format) < 0) {
                    free(prefix);
                    goto error;
                }
                if (vlc_stat(filename, &st)) {
                    *sequential = num;
                    break;
                }
                free(filename);
            }
        } else {
            struct tm    curtime;
            time_t       lcurtime = time(NULL) ;

            if (!localtime_r(&lcurtime, &curtime)) {
                const unsigned int id = (image->i_pts / 100000) & 0xFFFFFF;

                msg_Warn(object, "failed to get current time. Falling back to legacy snapshot naming");

                if (asprintf(&filename, "%s" DIR_SEP "%s%u.%s",
                             cfg->path, prefix, id, cfg->format) < 0)
                    filename = NULL;
            } else {
                /* suffix with the last decimal digit in 10s of seconds resolution
                 * FIXME gni ? */
                const int id = (image->i_pts / (100*1000)) & 0xFF;
                char buffer[128];

                if (!strftime(buffer, sizeof(buffer), "%Y-%m-%d-%Hh%Mm%Ss", &curtime))
                    strcpy(buffer, "error");

                if (asprintf(&filename, "%s" DIR_SEP "%s%s%1u.%s",
                             cfg->path, prefix, buffer, id, cfg->format) < 0)
                    filename = NULL;
            }
        }
        free(prefix);
    } else {
        /* The user specified a full path name (including file name) */
        filename = str_format(object, cfg->path);
        path_sanitize(filename);
    }

    if (!filename)
        goto error;

    /* Save the snapshot */
    FILE *file = vlc_fopen(filename, "wb");
    if (!file) {
        msg_Err(object, "Failed to open '%s'", filename);
        free(filename);
        goto error;
    }
    if (fwrite(image->p_buffer, image->i_buffer, 1, file) != 1) {
        msg_Err(object, "Failed to write to '%s'", filename);
        fclose(file);
        free(filename);
        goto error;
    }
    fclose(file);

    /* */
    if (name)
        *name = filename;
    else
        free(filename);

    return VLC_SUCCESS;

error:
    msg_Err(object, "could not save snapshot");
    return VLC_EGENERIC;
}
示例#5
0
void CCharacter::Tick()
{
	if(m_pPlayer->m_ForceBalanced)
	{
		char Buf[128];
		str_format(Buf, sizeof(Buf), "You were moved to %s due to team balancing", GameServer()->m_pController->GetTeamName(m_pPlayer->GetTeam()));
		GameServer()->SendBroadcast(Buf, m_pPlayer->GetCID());

		m_pPlayer->m_ForceBalanced = false;
	}

	m_Core.m_Input = m_Input;
	m_Core.Tick(true);

	// handle death-tiles and leaving gamelayer
	if(GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
		GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
		GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
		GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
		GameLayerClipped(m_Pos))
	{
		Die(m_pPlayer->GetCID(), WEAPON_WORLD);
	}

	// handle Weapons
	HandleWeapons();

/* INFECTION MODIFICATION START ***************************************/
	if(GetClass() == PLAYERCLASS_HUNTER)
	{
		if(IsGrounded()) m_AirJumpCounter = 0;
		if(m_Core.m_TriggeredEvents&COREEVENT_AIR_JUMP && m_AirJumpCounter < 1)
		{
			m_Core.m_Jumped &= ~2;
			m_AirJumpCounter++;
		}
	}
	
	if(m_pClassChooser)
	{
		if(GetClass() != PLAYERCLASS_NONE)
		{
			GameServer()->m_World.DestroyEntity(m_pClassChooser);
			m_pClassChooser = 0;
		}
		else
		{
			m_pClassChooser->m_Pos = m_Pos;
			m_pClassChooser->SetCursor(vec2(m_Input.m_TargetX, m_Input.m_TargetY));
			
			if(m_Input.m_Fire&1)
			{
				int ccRes = m_pClassChooser->SelectClass();
				if(ccRes)
				{				
					GameServer()->m_World.DestroyEntity(m_pClassChooser);
					m_pClassChooser = 0;
					
					m_pPlayer->SetClass(ccRes);
				}
			}
		}
	}
/* INFECTION MODIFICATION END *****************************************/

	// Previnput
	m_PrevInput = m_Input;
	return;
}
示例#6
0
void CSqlScore::ShowRankThread(void *pUser)
{
    lock_wait(gs_SqlLock);

    CSqlScoreData *pData = (CSqlScoreData *)pUser;

    // Connect to database
    if(pData->m_pSqlData->Connect())
    {
        try
        {
            // check strings
            char originalName[MAX_NAME_LENGTH];
            strcpy(originalName,pData->m_aName);
            pData->m_pSqlData->ClearString(pData->m_aName);

            // check sort methode
            char aBuf[600];

            pData->m_pSqlData->m_pStatement->execute("SET @rownum := 0;");
            str_format(aBuf, sizeof(aBuf), 	"SELECT Rank, one_rank.Name, one_rank.Time, UNIX_TIMESTAMP(CURRENT_TIMESTAMP)-UNIX_TIMESTAMP(r.Timestamp) as Ago, UNIX_TIMESTAMP(r.Timestamp) as stamp "
                       "FROM ("
                       "SELECT * FROM ("
                       "SELECT @rownum := @rownum + 1 AS RANK, Name, Time "
                       "FROM ("
                       "SELECT Name, min(Time) as Time "
                       "FROM %s_%s_race "
                       "Group By Name) as all_top_times "
                       "ORDER BY Time ASC) as all_ranks "
                       "WHERE all_ranks.Name = '%s') as one_rank "
                       "LEFT JOIN %s_%s_race as r "
                       "ON one_rank.Name = r.Name && one_rank.Time = r.Time "
                       "ORDER BY Ago ASC "
                       "LIMIT 0,1"
                       ";", pData->m_pSqlData->m_pPrefix, pData->m_pSqlData->m_aMap,pData->m_aName, pData->m_pSqlData->m_pPrefix, pData->m_pSqlData->m_aMap);

            pData->m_pSqlData->m_pResults = pData->m_pSqlData->m_pStatement->executeQuery(aBuf);

            if(pData->m_pSqlData->m_pResults->rowsCount() != 1)
            {
                str_format(aBuf, sizeof(aBuf), "%s is not ranked", originalName);
                pData->m_pSqlData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf);
            }
            else
            {
                pData->m_pSqlData->m_pResults->next();
                int since = (int)pData->m_pSqlData->m_pResults->getInt("Ago");
                char agoString[40];
                agoTimeToString(since,agoString);

                float Time = (float)pData->m_pSqlData->m_pResults->getDouble("Time");
                int Rank = (int)pData->m_pSqlData->m_pResults->getInt("Rank");
                if(g_Config.m_SvHideScore)
                    str_format(aBuf, sizeof(aBuf), "Your time: %d minute(s) %5.2f second(s)", (int)(Time/60), Time-((int)Time/60*60));
                else
                    str_format(aBuf, sizeof(aBuf), "%d. %s Time: %d minute(s) %5.2f second(s)", Rank, pData->m_pSqlData->m_pResults->getString("Name").c_str(), (int)(Time/60), Time-((int)Time/60*60), agoString);

                if(pData->m_pSqlData->m_pResults->getInt("stamp") != 0) {
                    pData->m_pSqlData->GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf, pData->m_ClientID);
                    str_format(aBuf, sizeof(aBuf), "Finished: %s ago", agoString);
                }
                if(pData->m_Search)
                    strcat(aBuf, pData->m_aRequestingPlayer);
                pData->m_pSqlData->GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf, pData->m_ClientID);

            }

            dbg_msg("SQL", "Showing rank done");

            // delete results and statement
            delete pData->m_pSqlData->m_pResults;
            delete pData->m_pSqlData->m_pStatement;
        }
        catch (sql::SQLException &e)
        {
            char aBuf[256];
            str_format(aBuf, sizeof(aBuf), "MySQL Error: %s", e.what());
            dbg_msg("SQL", aBuf);
            dbg_msg("SQL", "ERROR: Could not show rank");
        }

        // disconnect from database
        pData->m_pSqlData->Disconnect();//TODO:Check if an exception is caught will this still execute ?
    }

    delete pData;

    lock_release(gs_SqlLock);
}
示例#7
0
void CSqlScore::ShowTimesThread(void *pUser)
{
    lock_wait(gs_SqlLock);
    CSqlScoreData *pData = (CSqlScoreData *)pUser;

    // Connect to database
    if(pData->m_pSqlData->Connect())
    {
        try
        {
            char originalName[MAX_NAME_LENGTH];
            strcpy(originalName,pData->m_aName);
            pData->m_pSqlData->ClearString(pData->m_aName);

            char aBuf[512];

            if(pData->m_Search) // last 5 times of a player
                str_format(aBuf, sizeof(aBuf), "SELECT Time, UNIX_TIMESTAMP(CURRENT_TIMESTAMP)-UNIX_TIMESTAMP(Timestamp) as Ago, UNIX_TIMESTAMP(Timestamp) as Stamp FROM %s_%s_race WHERE Name = '%s' ORDER BY Ago ASC LIMIT %d, 5;", pData->m_pSqlData->m_pPrefix, pData->m_pSqlData->m_aMap, pData->m_aName, pData->m_Num-1);
            else // last 5 times of server
                str_format(aBuf, sizeof(aBuf), "SELECT Name, Time, UNIX_TIMESTAMP(CURRENT_TIMESTAMP)-UNIX_TIMESTAMP(Timestamp) as Ago, UNIX_TIMESTAMP(Timestamp) as Stamp FROM %s_%s_race ORDER BY Ago ASC LIMIT %d, 5;", pData->m_pSqlData->m_pPrefix, pData->m_pSqlData->m_aMap, pData->m_Num-1);

            pData->m_pSqlData->m_pResults = pData->m_pSqlData->m_pStatement->executeQuery(aBuf);

            // show top5
            if(pData->m_pSqlData->m_pResults->rowsCount() == 0) {
                pData->m_pSqlData->GameServer()->SendChatTarget(pData->m_ClientID, "There are no times in the specified range");
                goto end;
            }

            str_format(aBuf, sizeof(aBuf), "------------ Last Times No %d - %d ------------",pData->m_Num,pData->m_Num + pData->m_pSqlData->m_pResults->rowsCount() - 1);
            pData->m_pSqlData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf);

            float pTime = 0;
            int pSince = 0;
            int pStamp = 0;

            while(pData->m_pSqlData->m_pResults->next())
            {
                char pAgoString[40] = "\0";
                pSince = (int)pData->m_pSqlData->m_pResults->getInt("Ago");
                pStamp = (int)pData->m_pSqlData->m_pResults->getInt("Stamp");
                pTime = (float)pData->m_pSqlData->m_pResults->getDouble("Time");

                agoTimeToString(pSince,pAgoString);

                if(pData->m_Search) // last 5 times of a player
                {
                    if(pStamp == 0) // stamp is 00:00:00 cause it's an old entry from old times where there where no stamps yet
                        str_format(aBuf, sizeof(aBuf), "%d min %.2f sec, don't know how long ago", (int)(pTime/60), pTime-((int)pTime/60*60));
                    else
                        str_format(aBuf, sizeof(aBuf), "%s ago, %d min %.2f sec", pAgoString,(int)(pTime/60), pTime-((int)pTime/60*60));
                }
                else // last 5 times of the server
                {
                    if(pStamp == 0) // stamp is 00:00:00 cause it's an old entry from old times where there where no stamps yet
                        str_format(aBuf, sizeof(aBuf), "%s, %d m %.2f s, don't know when", pData->m_pSqlData->m_pResults->getString("Name").c_str(), (int)(pTime/60), pTime-((int)pTime/60*60));
                    else
                        str_format(aBuf, sizeof(aBuf), "%s, %s ago, %d m %.2f s", pData->m_pSqlData->m_pResults->getString("Name").c_str(), pAgoString, (int)(pTime/60), pTime-((int)pTime/60*60));
                }
                pData->m_pSqlData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf);
            }
            pData->m_pSqlData->GameServer()->SendChatTarget(pData->m_ClientID, "----------------------------------------------------");

            dbg_msg("SQL", "Showing times done");

            // delete results and statement
            delete pData->m_pSqlData->m_pResults;
            delete pData->m_pSqlData->m_pStatement;
        }
        catch (sql::SQLException &e)
        {
            char aBuf[256];
            str_format(aBuf, sizeof(aBuf), "MySQL Error: %s", e.what());
            dbg_msg("SQL", aBuf);
            dbg_msg("SQL", "ERROR: Could not show times");
        }
end:
        // disconnect from database
        pData->m_pSqlData->Disconnect();
    }
    delete pData;

    lock_release(gs_SqlLock);
}
void CAbstractIntegerEdit::CEntry::CopyToTextBuffer()
{
	str_format(m_aText, sizeof(m_aText), "%d", m_pIntegerEdit->GetValue());
	OnTextUpdated();
}
示例#9
0
void CGameConsole::OnRender()
{
	CUIRect Screen = *UI()->Screen();
	float ConsoleMaxHeight = Screen.h*3/5.0f;
	float ConsoleHeight;

	float Progress = (TimeNow()-(m_StateChangeEnd-m_StateChangeDuration))/float(m_StateChangeDuration);

	if (Progress >= 1.0f)
	{
		if (m_ConsoleState == CONSOLE_CLOSING)
			m_ConsoleState = CONSOLE_CLOSED;
		else if (m_ConsoleState == CONSOLE_OPENING)
			m_ConsoleState = CONSOLE_OPEN;

		Progress = 1.0f;
	}

	if (m_ConsoleState == CONSOLE_OPEN && g_Config.m_ClEditor)
		Toggle(CONSOLETYPE_LOCAL);

	if (m_ConsoleState == CONSOLE_CLOSED)
		return;

	if (m_ConsoleState == CONSOLE_OPEN)
		Input()->MouseModeAbsolute();

	float ConsoleHeightScale;

	if (m_ConsoleState == CONSOLE_OPENING)
		ConsoleHeightScale = ConsoleScaleFunc(Progress);
	else if (m_ConsoleState == CONSOLE_CLOSING)
		ConsoleHeightScale = ConsoleScaleFunc(1.0f-Progress);
	else //if (console_state == CONSOLE_OPEN)
		ConsoleHeightScale = ConsoleScaleFunc(1.0f);

	ConsoleHeight = ConsoleHeightScale*ConsoleMaxHeight;

	Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);

	// do console shadow
	Graphics()->TextureClear();
	Graphics()->QuadsBegin();
	IGraphics::CColorVertex Array[4] = {
		IGraphics::CColorVertex(0, 0,0,0, 0.5f),
		IGraphics::CColorVertex(1, 0,0,0, 0.5f),
		IGraphics::CColorVertex(2, 0,0,0, 0.0f),
		IGraphics::CColorVertex(3, 0,0,0, 0.0f)};
	Graphics()->SetColorVertex(Array, 4);
	IGraphics::CQuadItem QuadItem(0, ConsoleHeight, Screen.w, 10.0f);
	Graphics()->QuadsDrawTL(&QuadItem, 1);
	Graphics()->QuadsEnd();

	// do background
	Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CONSOLE_BG].m_Id);
	Graphics()->QuadsBegin();
	Graphics()->SetColor(0.2f, 0.2f, 0.2f,0.9f);
	if(m_ConsoleType == CONSOLETYPE_REMOTE)
		Graphics()->SetColor(0.4f, 0.2f, 0.2f,0.9f);
	Graphics()->QuadsSetSubset(0,-ConsoleHeight*0.075f,Screen.w*0.075f*0.5f,0);
	QuadItem = IGraphics::CQuadItem(0, 0, Screen.w, ConsoleHeight);
	Graphics()->QuadsDrawTL(&QuadItem, 1);
	Graphics()->QuadsEnd();

	// do small bar shadow
	Graphics()->TextureClear();
	Graphics()->QuadsBegin();
	Array[0] = IGraphics::CColorVertex(0, 0,0,0, 0.0f);
	Array[1] = IGraphics::CColorVertex(1, 0,0,0, 0.0f);
	Array[2] = IGraphics::CColorVertex(2, 0,0,0, 0.25f);
	Array[3] = IGraphics::CColorVertex(3, 0,0,0, 0.25f);
	Graphics()->SetColorVertex(Array, 4);
	QuadItem = IGraphics::CQuadItem(0, ConsoleHeight-20, Screen.w, 10);
	Graphics()->QuadsDrawTL(&QuadItem, 1);
	Graphics()->QuadsEnd();

	// do the lower bar
	Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CONSOLE_BAR].m_Id);
	Graphics()->QuadsBegin();
	Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.9f);
	Graphics()->QuadsSetSubset(0,0.1f,Screen.w*0.015f,1-0.1f);
	QuadItem = IGraphics::CQuadItem(0,ConsoleHeight-10.0f,Screen.w,10.0f);
	Graphics()->QuadsDrawTL(&QuadItem, 1);
	Graphics()->QuadsEnd();

	ConsoleHeight -= 22.0f;

	CInstance *pConsole = CurrentConsole();

	{
		float FontSize = 10.0f;
		float RowHeight = FontSize*1.25f;
		float x = 3;
		float y = ConsoleHeight - RowHeight - 5.0f;

		CRenderInfo Info;
		Info.m_pSelf = this;
		Info.m_WantedCompletion = pConsole->m_CompletionChosen;
		Info.m_EnumCount = 0;
		Info.m_Offset = pConsole->m_CompletionRenderOffset;
		Info.m_Width = Screen.w;
		Info.m_pCurrentCmd = pConsole->m_aCompletionBuffer;
		TextRender()->SetCursor(&Info.m_Cursor, x+Info.m_Offset, y+RowHeight+2.0f, FontSize, TEXTFLAG_RENDER);

		// render prompt
		CTextCursor Cursor;
		TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER);
		const char *pPrompt = "> ";
		if(m_ConsoleType == CONSOLETYPE_REMOTE)
		{
			if(Client()->State() == IClient::STATE_ONLINE)
			{
				if(Client()->RconAuthed())
					pPrompt = "rcon> ";
				else
					pPrompt = "ENTER PASSWORD> ";
			}
			else
				pPrompt = "NOT CONNECTED> ";
		}
		TextRender()->TextEx(&Cursor, pPrompt, -1);

		x = Cursor.m_X;

		//hide rcon password
		char aInputString[256];
		str_copy(aInputString, pConsole->m_Input.GetString(), sizeof(aInputString));
		if(m_ConsoleType == CONSOLETYPE_REMOTE && Client()->State() == IClient::STATE_ONLINE && !Client()->RconAuthed())
		{
			for(int i = 0; i < pConsole->m_Input.GetLength(); ++i)
				aInputString[i] = '*';
		}

		// render console input (wrap line)
		TextRender()->SetCursor(&Cursor, x, y, FontSize, 0);
		Cursor.m_LineWidth = Screen.w - 10.0f - x;
		TextRender()->TextEx(&Cursor, aInputString, pConsole->m_Input.GetCursorOffset());
		TextRender()->TextEx(&Cursor, aInputString+pConsole->m_Input.GetCursorOffset(), -1);
		int Lines = Cursor.m_LineCount;
		
		y -= (Lines - 1) * FontSize;
		TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER);
		Cursor.m_LineWidth = Screen.w - 10.0f - x;
		
		TextRender()->TextEx(&Cursor, aInputString, pConsole->m_Input.GetCursorOffset());
		static float MarkerOffset = TextRender()->TextWidth(0, FontSize, "|", -1)/3;
		CTextCursor Marker = Cursor;
		Marker.m_X -= MarkerOffset;
		Marker.m_LineWidth = -1;
		TextRender()->TextEx(&Marker, "|", -1);
		TextRender()->TextEx(&Cursor, aInputString+pConsole->m_Input.GetCursorOffset(), -1);

		// render possible commands
		if(m_ConsoleType == CONSOLETYPE_LOCAL || Client()->RconAuthed())
		{
			if(pConsole->m_Input.GetString()[0] != 0)
			{
				m_pConsole->PossibleCommands(pConsole->m_aCompletionBuffer, pConsole->m_CompletionFlagmask, m_ConsoleType != CGameConsole::CONSOLETYPE_LOCAL &&
					Client()->RconAuthed() && Client()->UseTempRconCommands(), PossibleCommandsRenderCallback, &Info);
				pConsole->m_CompletionRenderOffset = Info.m_Offset;

				if(Info.m_EnumCount <= 0)
				{
					if(pConsole->m_IsCommand)
					{
						char aBuf[512];
						str_format(aBuf, sizeof(aBuf), "Help: %s ", pConsole->m_aCommandHelp);
						TextRender()->TextEx(&Info.m_Cursor, aBuf, -1);
						TextRender()->TextColor(0.75f, 0.75f, 0.75f, 1);
						str_format(aBuf, sizeof(aBuf), "Syntax: %s %s", pConsole->m_aCommandName, pConsole->m_aCommandParams);
						TextRender()->TextEx(&Info.m_Cursor, aBuf, -1);
					}
				}
			}
		}
		TextRender()->TextColor(1,1,1,1);

		//	render log (actual page, wrap lines)
		CInstance::CBacklogEntry *pEntry = pConsole->m_Backlog.Last();
		float OffsetY = 0.0f;
		float LineOffset = 1.0f;
		for(int Page = 0; Page <= pConsole->m_BacklogActPage; ++Page, OffsetY = 0.0f)
		{
			while(pEntry)
			{
				// get y offset (calculate it if we haven't yet)
				if(pEntry->m_YOffset < 0.0f)
				{
					TextRender()->SetCursor(&Cursor, 0.0f, 0.0f, FontSize, 0);
					Cursor.m_LineWidth = Screen.w-10;
					TextRender()->TextEx(&Cursor, pEntry->m_aText, -1);
					pEntry->m_YOffset = Cursor.m_Y+Cursor.m_FontSize+LineOffset;
				}
				OffsetY += pEntry->m_YOffset;

				//	next page when lines reach the top
				if(y-OffsetY <= RowHeight)
					break;

				//	just render output from actual backlog page (render bottom up)
				if(Page == pConsole->m_BacklogActPage)
				{
					TextRender()->SetCursor(&Cursor, 0.0f, y-OffsetY, FontSize, TEXTFLAG_RENDER);
					Cursor.m_LineWidth = Screen.w-10.0f;
					TextRender()->TextEx(&Cursor, pEntry->m_aText, -1);
				}
				pEntry = pConsole->m_Backlog.Prev(pEntry);
			}

			//	actual backlog page number is too high, render last available page (current checked one, render top down)
			if(!pEntry && Page < pConsole->m_BacklogActPage)
			{
				pConsole->m_BacklogActPage = Page;
				pEntry = pConsole->m_Backlog.First();
				while(OffsetY > 0.0f && pEntry)
				{
					TextRender()->SetCursor(&Cursor, 0.0f, y-OffsetY, FontSize, TEXTFLAG_RENDER);
					Cursor.m_LineWidth = Screen.w-10.0f;
					TextRender()->TextEx(&Cursor, pEntry->m_aText, -1);
					OffsetY -= pEntry->m_YOffset;
					pEntry = pConsole->m_Backlog.Next(pEntry);
				}
				break;
			}
		}

		// render page
		char aBuf[128];
		str_format(aBuf, sizeof(aBuf), Localize("-Page %d-"), pConsole->m_BacklogActPage+1);
		TextRender()->Text(0, 10.0f, 0.0f, FontSize, aBuf, -1);

		// render version
		str_format(aBuf, sizeof(aBuf), "v%s", GAME_VERSION);
		float Width = TextRender()->TextWidth(0, FontSize, aBuf, -1);
		TextRender()->Text(0, Screen.w-Width-10.0f, 0.0f, FontSize, aBuf, -1);
	}
}
示例#10
0
void CMenus::RenderDemoList(CUIRect MainView)
{
	static int s_Inited = 0;
	if(!s_Inited)
	{
		DemolistPopulate();
		DemolistOnUpdate(true);
		s_Inited = 1;
	}

	// delete demo
	if(m_DemolistDelEntry)
	{
		if(m_DemolistSelectedIndex >= 0 && !m_DemolistSelectedIsDir)
		{
			char aBuf[512];
			str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_lDemos[m_DemolistSelectedIndex].m_aFilename);
			if(Storage()->RemoveFile(aBuf, m_lDemos[m_DemolistSelectedIndex].m_StorageType))
			{
				DemolistPopulate();
				DemolistOnUpdate(false);
			}
		}
		m_DemolistDelEntry = false;
	}

	char aFooterLabel[128] = {0};
	if(m_DemolistSelectedIndex >= 0)
	{
		CDemoItem *Item = &m_lDemos[m_DemolistSelectedIndex];
		if(str_comp(Item->m_aFilename, "..") == 0)
			str_copy(aFooterLabel, Localize("Parent Folder"), sizeof(aFooterLabel));
		else if(m_DemolistSelectedIsDir)
			str_copy(aFooterLabel, Localize("Folder"), sizeof(aFooterLabel));
		else
		{
			if(!Item->m_InfosLoaded)
			{
				char aBuffer[512];
				str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_aCurrentDemoFolder, Item->m_aFilename);
				Item->m_Valid = DemoPlayer()->GetDemoInfo(Storage(), aBuffer, Item->m_StorageType, Item->m_aMap, sizeof(Item->m_aMap));
				Item->m_InfosLoaded = true;
			}
			if(!Item->m_Valid)
				str_copy(aFooterLabel, Localize("Invalid Demo"), sizeof(aFooterLabel));
			else
				str_format(aFooterLabel, sizeof(aFooterLabel), "%s: %s", Localize("Map"), Item->m_aMap);
		}
	}
	
	// render background
	RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f);
	MainView.Margin(10.0f, &MainView);
	
	CUIRect ButtonBar, RefreshRect, PlayRect, DeleteRect, FileIcon;
	MainView.HSplitBottom(ms_ButtonHeight+5.0f, &MainView, &ButtonBar);
	ButtonBar.HSplitTop(5.0f, 0, &ButtonBar);
	ButtonBar.VSplitRight(130.0f, &ButtonBar, &PlayRect);
	ButtonBar.VSplitLeft(130.0f, &RefreshRect, &ButtonBar);
	ButtonBar.VSplitLeft(10.0f, &DeleteRect, &ButtonBar);
	ButtonBar.VSplitLeft(120.0f, &DeleteRect, &ButtonBar);
	
	static int s_DemoListId = 0;
	static float s_ScrollValue = 0;
	UiDoListboxStart(&s_DemoListId, &MainView, 17.0f, Localize("Demos"), aFooterLabel, m_lDemos.size(), 1, m_DemolistSelectedIndex, s_ScrollValue);
	for(sorted_array<CDemoItem>::range r = m_lDemos.all(); !r.empty(); r.pop_front())
	{
		CListboxItem Item = UiDoListboxNextItem((void*)(&r.front()));
		if(Item.m_Visible)
		{
			Item.m_Rect.VSplitLeft(Item.m_Rect.h, &FileIcon, &Item.m_Rect);
			Item.m_Rect.VSplitLeft(5.0f, 0, &Item.m_Rect);
			DoButton_Icon(IMAGE_FILEICONS, r.front().m_IsDir?SPRITE_FILE_FOLDER:SPRITE_FILE_DEMO1, &FileIcon);
			UI()->DoLabel(&Item.m_Rect, r.front().m_aName, Item.m_Rect.h*ms_FontmodHeight, -1);
		}
	}
	bool Activated = false;
	m_DemolistSelectedIndex = UiDoListboxEnd(&s_ScrollValue, &Activated);
	DemolistOnUpdate(false);
	
	static int s_RefreshButton = 0;
	if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &RefreshRect))
	{
		DemolistPopulate();
		DemolistOnUpdate(false);
	}

	static int s_PlayButton = 0;
	if(DoButton_Menu(&s_PlayButton, m_DemolistSelectedIsDir?Localize("Open"):Localize("Play"), 0, &PlayRect) || Activated)
	{
		if(m_DemolistSelectedIndex >= 0)
		{
			if(m_DemolistSelectedIsDir)	// folder
			{
				if(str_comp(m_lDemos[m_DemolistSelectedIndex].m_aFilename, "..") == 0)	// parent folder
					fs_parent_dir(m_aCurrentDemoFolder);
				else	// sub folder
				{
					char aTemp[256];
					str_copy(aTemp, m_aCurrentDemoFolder, sizeof(aTemp));
					str_format(m_aCurrentDemoFolder, sizeof(m_aCurrentDemoFolder), "%s/%s", aTemp, m_lDemos[m_DemolistSelectedIndex].m_aFilename);
					m_DemolistStorageType = m_lDemos[m_DemolistSelectedIndex].m_StorageType;
				}
				DemolistPopulate();
				DemolistOnUpdate(true);
			}
			else // file
			{
				char aBuf[512];
				str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_lDemos[m_DemolistSelectedIndex].m_aFilename);
				const char *pError = Client()->DemoPlayer_Play(aBuf, m_lDemos[m_DemolistSelectedIndex].m_StorageType);
				if(pError)
					PopupMessage(Localize("Error"), str_comp(pError, "error loading demo") ? pError : Localize("Error loading demo"), Localize("Ok"));
				else
				{
					UI()->SetActiveItem(0);
					return;
				}
			}
		}
	}
	
	if(!m_DemolistSelectedIsDir)
	{
		static int s_DeleteButton = 0;
		if(DoButton_Menu(&s_DeleteButton, Localize("Delete"), 0, &DeleteRect) || m_DeletePressed)
		{
			if(m_DemolistSelectedIndex >= 0)
			{
				UI()->SetActiveItem(0);
				m_Popup = POPUP_DELETE_DEMO;
			}
		}
	}
}
示例#11
0
文件: player.cpp 项目: Chairn/ddnet
void CPlayer::Tick()
{
#ifdef CONF_DEBUG
	if(!g_Config.m_DbgDummies || m_ClientID < MAX_CLIENTS-g_Config.m_DbgDummies)
#endif
	if(!Server()->ClientIngame(m_ClientID))
		return;

	if(m_KillMe != 0)
	{
		KillCharacter(m_KillMe);
		m_KillMe = 0;
		return;
	}

	if (m_ChatScore > 0)
		m_ChatScore--;

	if (m_ForcePauseTime > 0)
		m_ForcePauseTime--;

	Server()->SetClientScore(m_ClientID, m_Score);

	// do latency stuff
	{
		IServer::CClientInfo Info;
		if(Server()->GetClientInfo(m_ClientID, &Info))
		{
			m_Latency.m_Accum += Info.m_Latency;
			m_Latency.m_AccumMax = max(m_Latency.m_AccumMax, Info.m_Latency);
			m_Latency.m_AccumMin = min(m_Latency.m_AccumMin, Info.m_Latency);
		}
		// each second
		if(Server()->Tick()%Server()->TickSpeed() == 0)
		{
			m_Latency.m_Avg = m_Latency.m_Accum/Server()->TickSpeed();
			m_Latency.m_Max = m_Latency.m_AccumMax;
			m_Latency.m_Min = m_Latency.m_AccumMin;
			m_Latency.m_Accum = 0;
			m_Latency.m_AccumMin = 1000;
			m_Latency.m_AccumMax = 0;
		}
	}

	if(((CServer *)Server())->m_NetServer.ErrorString(m_ClientID)[0])
	{
		char aBuf[512];
		str_format(aBuf, sizeof(aBuf), "'%s' would have timed out, but can use timeout protection now", Server()->ClientName(m_ClientID));
		GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
		((CServer *)(Server()))->m_NetServer.ResetErrorString(m_ClientID);
	}

	if(!GameServer()->m_World.m_Paused)
	{
		if(!m_pCharacter && m_Team == TEAM_SPECTATORS && m_SpectatorID == SPEC_FREEVIEW)
			m_ViewPos -= vec2(clamp(m_ViewPos.x-m_LatestActivity.m_TargetX, -500.0f, 500.0f), clamp(m_ViewPos.y-m_LatestActivity.m_TargetY, -400.0f, 400.0f));

		if(!m_pCharacter && m_DieTick+Server()->TickSpeed()*3 <= Server()->Tick())
			m_Spawning = true;

		if(m_pCharacter)
		{
			if(m_pCharacter->IsAlive())
			{
				if(m_Paused >= PAUSED_FORCE)
				{
					if(m_ForcePauseTime == 0)
					m_Paused = PAUSED_NONE;
					ProcessPause();
				}
				else if(m_Paused == PAUSED_PAUSED && m_NextPauseTick < Server()->Tick())
				{
					if((!m_pCharacter->GetWeaponGot(WEAPON_NINJA) || m_pCharacter->m_FreezeTime) && m_pCharacter->IsGrounded() && m_pCharacter->m_Pos == m_pCharacter->m_PrevPos)
						ProcessPause();
				}
				else if(m_NextPauseTick < Server()->Tick())
				{
					ProcessPause();
				}
				if(!m_Paused)
					m_ViewPos = m_pCharacter->m_Pos;
			}
			else if(!m_pCharacter->IsPaused())
			{
				delete m_pCharacter;
				m_pCharacter = 0;
			}
		}
		else if(m_Spawning && !m_WeakHookSpawn)
			TryRespawn();
	}
	else
	{
		++m_DieTick;
		++m_JoinTick;
		++m_LastActionTick;
		++m_TeamChangeTick;
	}

	m_TuneZoneOld = m_TuneZone; // determine needed tunings with viewpos
	int CurrentIndex = GameServer()->Collision()->GetMapIndex(m_ViewPos);
	m_TuneZone = GameServer()->Collision()->IsTune(CurrentIndex);

	if (m_TuneZone != m_TuneZoneOld) // dont send tunigs all the time
	{
		GameServer()->SendTuningParams(m_ClientID, m_TuneZone);
	}
}
示例#12
0
void CMenus::RenderDemoPlayer(CUIRect MainView)
{
	const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
	
	const float SeekBarHeight = 15.0f;
	const float ButtonbarHeight = 20.0f;
	const float NameBarHeight = 20.0f;
	const float Margins = 5.0f;
	float TotalHeight;
	
	if(m_MenuActive)
		TotalHeight = SeekBarHeight+ButtonbarHeight+NameBarHeight+Margins*3;
	else
		TotalHeight = SeekBarHeight+Margins*2;
	
	MainView.HSplitBottom(TotalHeight, 0, &MainView);
	MainView.VSplitLeft(250.0f, 0, &MainView);
	MainView.VSplitRight(250.0f, &MainView, 0);
	
	RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_T, 10.0f);
		
	MainView.Margin(5.0f, &MainView);
	
	CUIRect SeekBar, ButtonBar, NameBar;
	
	int CurrentTick = pInfo->m_CurrentTick - pInfo->m_FirstTick;
	int TotalTicks = pInfo->m_LastTick - pInfo->m_FirstTick;
	
	if(m_MenuActive)
	{
		MainView.HSplitTop(SeekBarHeight, &SeekBar, &ButtonBar);
		ButtonBar.HSplitTop(Margins, 0, &ButtonBar);
		ButtonBar.HSplitBottom(NameBarHeight, &ButtonBar, &NameBar);
		NameBar.HSplitTop(4.0f, 0, &NameBar);
	}
	else
		SeekBar = MainView;

	// do seekbar
	{
		static int s_SeekBarId = 0;
		void *id = &s_SeekBarId;
		char aBuffer[128];
		
		RenderTools()->DrawUIRect(&SeekBar, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 5.0f);
		
		float Amount = CurrentTick/(float)TotalTicks;
		
		CUIRect FilledBar = SeekBar;
		FilledBar.w = 10.0f + (FilledBar.w-10.0f)*Amount;
		
		RenderTools()->DrawUIRect(&FilledBar, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f);
		
		str_format(aBuffer, sizeof(aBuffer), "%d:%02d / %d:%02d",
			CurrentTick/SERVER_TICK_SPEED/60, (CurrentTick/SERVER_TICK_SPEED)%60,
			TotalTicks/SERVER_TICK_SPEED/60, (TotalTicks/SERVER_TICK_SPEED)%60);
		UI()->DoLabel(&SeekBar, aBuffer, SeekBar.h*0.70f, 0);

		// do the logic
	    int Inside = UI()->MouseInside(&SeekBar);
			
		if(UI()->ActiveItem() == id)
		{
			if(!UI()->MouseButton(0))
				UI()->SetActiveItem(0);
			else
			{
				static float PrevAmount = 0.0f;
				float Amount = (UI()->MouseX()-SeekBar.x)/(float)SeekBar.w;
				if(Amount > 0.0f && Amount < 1.0f && absolute(PrevAmount-Amount) >= 0.01f)
				{
					PrevAmount = Amount;
					m_pClient->OnReset();
					m_pClient->m_SuppressEvents = true;
					DemoPlayer()->SetPos(Amount);
					m_pClient->m_SuppressEvents = false;
				}
			}
		}
		else if(UI()->HotItem() == id)
		{
			if(UI()->MouseButton(0))
				UI()->SetActiveItem(id);
		}		
		
		if(Inside)
			UI()->SetHotItem(id);
	}	

	if(CurrentTick == TotalTicks)
	{
	DemoPlayer()->Pause();
	DemoPlayer()->SetPos(0);
	}

	if(m_MenuActive)
	{
		// do buttons
		CUIRect Button;
		
		// combined play and pause button
		ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
		static int s_PlayPauseButton = 0;
		if(!pInfo->m_Paused)
		{
			if(DoButton_DemoPlayer_Sprite(&s_PlayPauseButton, SPRITE_DEMOBUTTON_PAUSE, pInfo->m_Paused, &Button))
				DemoPlayer()->Pause();
		}
		else
		{
			if(DoButton_DemoPlayer_Sprite(&s_PlayPauseButton, SPRITE_DEMOBUTTON_PLAY, !pInfo->m_Paused, &Button))
				DemoPlayer()->Unpause();
		}
		
		// stop button
		
		ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
		ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
		static int s_ResetButton = 0;
		if(DoButton_DemoPlayer_Sprite(&s_ResetButton, SPRITE_DEMOBUTTON_STOP, false, &Button))
		{
			DemoPlayer()->Pause(); 
			DemoPlayer()->SetPos(0);
		}

		// slowdown
		ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
		ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
		static int s_SlowDownButton = 0;
		if(DoButton_DemoPlayer_Sprite(&s_SlowDownButton, SPRITE_DEMOBUTTON_SLOWER, 0, &Button))
		{
			if(pInfo->m_Speed > 4.0f) DemoPlayer()->SetSpeed(4.0f);
			else if(pInfo->m_Speed > 2.0f) DemoPlayer()->SetSpeed(2.0f);
			else if(pInfo->m_Speed > 1.0f) DemoPlayer()->SetSpeed(1.0f);
			else if(pInfo->m_Speed > 0.75f) DemoPlayer()->SetSpeed(0.75f);
			else if(pInfo->m_Speed > 0.5f) DemoPlayer()->SetSpeed(0.5f);
			else if(pInfo->m_Speed > 0.25f) DemoPlayer()->SetSpeed(0.25f);
			else if(pInfo->m_Speed > 0.1f) DemoPlayer()->SetSpeed(0.1f);
			else DemoPlayer()->SetSpeed(0.05f);
		}
		
		// fastforward
		ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
		ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
		static int s_FastForwardButton = 0;
		if(DoButton_DemoPlayer_Sprite(&s_FastForwardButton, SPRITE_DEMOBUTTON_FASTER, 0, &Button))
		{
			if(pInfo->m_Speed < 0.1f) DemoPlayer()->SetSpeed(0.1f);
			else if(pInfo->m_Speed < 0.25f) DemoPlayer()->SetSpeed(0.25f);
			else if(pInfo->m_Speed < 0.5f) DemoPlayer()->SetSpeed(0.5f);
			else if(pInfo->m_Speed < 0.75f) DemoPlayer()->SetSpeed(0.75f);
			else if(pInfo->m_Speed < 1.0f) DemoPlayer()->SetSpeed(1.0f);
			else if(pInfo->m_Speed < 2.0f) DemoPlayer()->SetSpeed(2.0f);
			else if(pInfo->m_Speed < 4.0f) DemoPlayer()->SetSpeed(4.0f);
			else DemoPlayer()->SetSpeed(8.0f);
		}

		// speed meter
		ButtonBar.VSplitLeft(Margins*3, 0, &ButtonBar);
		char aBuffer[64];
		if(pInfo->m_Speed >= 1.0f)
			str_format(aBuffer, sizeof(aBuffer), "x%.0f", pInfo->m_Speed);
		else
			str_format(aBuffer, sizeof(aBuffer), "x%.2f", pInfo->m_Speed);
		UI()->DoLabel(&ButtonBar, aBuffer, Button.h*0.7f, -1);

		// close button
		ButtonBar.VSplitRight(ButtonbarHeight*3, &ButtonBar, &Button);
		static int s_ExitButton = 0;
		if(DoButton_DemoPlayer(&s_ExitButton, Localize("Close"), 0, &Button))
			Client()->Disconnect();

		// demo name
		char aBuf[128];
		str_format(aBuf, sizeof(aBuf), "Demofile: %s", DemoPlayer()->GetDemoName());
		CTextCursor Cursor;
		TextRender()->SetCursor(&Cursor, NameBar.x, NameBar.y, Button.h*0.5f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
		Cursor.m_LineWidth = MainView.w;
		TextRender()->TextEx(&Cursor, aBuf, -1);
	}
}
示例#13
0
文件: console.cpp 项目: ftk/XXLDDRace
CConsole::CConsole(int FlagMask)
{
	m_FlagMask = FlagMask;
	m_AccessLevel = ACCESS_LEVEL_ADMIN;
	m_pRecycleList = 0;
	m_TempCommands.Reset();
	m_StoreCommands = true;
	m_paStrokeStr[0] = "0";
	m_paStrokeStr[1] = "1";
	m_ExecutionQueue.Reset();
	m_pFirstCommand = 0;
	m_pFirstExec = 0;
	mem_zero(m_aPrintCB, sizeof(m_aPrintCB));
	m_NumPrintCB = 0;

	m_pStorage = 0;

	m_pCurTick = NULL;

	m_pNameToIDfn = NULL;
	
	#if !defined(_MSC_VER) || _MSC_VER >= 1700 // workaround for msvc < 2012
	commands.max_load_factor(0.75f);
	commands.reserve(512);
	#endif

	// register some basic commands
	Register("echo", "r", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_Echo, this, "Echo the text");
	Register("+echo", "r", CFGFLAG_SERVER|CFGFLAG_CLIENT, ([] (IConsole::IResult *pResult, void *pUserData)
	{
		char aBuf[1024];
		str_format(aBuf, sizeof(aBuf), "%s %s", pResult->GetString(1), pResult->GetString(0));
		((CConsole*)pUserData)->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Console", aBuf);
	}), this, "Echo the text");

	Register("exec", "r", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_Exec, this, "Execute the specified file");

	Register("toggle", "sii", CFGFLAG_SERVER|CFGFLAG_CLIENT, ConToggle, this, "Toggle config value");
	Register("+toggle", "sii", CFGFLAG_CLIENT, ConToggleStroke, this, "Toggle config value via keypress");

	Register("level_command", "s?i", CFGFLAG_SERVER, ConModCommandAccess, this, "Specify command accessibility");
	Register("subadmin_status", "", CFGFLAG_SERVER, ConSubAdminCommandStatus, this, "List all commands which are accessible for sub admins");
	Register("mod_status", "", CFGFLAG_SERVER, ConModCommandStatus, this, "List all commands which are accessible for moderators");
	Register("user_status", "", CFGFLAG_SERVER, ConUserCommandStatus, this, "List all commands which are accessible for users");
	Register("cmdlist", "", CFGFLAG_SERVER|CFGFLAG_CHAT, ConUserCommandStatus, this, "List all commands which are accessible for users");
	
	Register("register_stub", "s", CFGFLAG_CLIENT|CFGFLAG_SERVER, ([](IConsole::IResult *pResult, void * pSelf)
	{
		int len = str_length(pResult->GetString(0)) + 1;
		char * cmdname = new char[len];
		str_copy(cmdname, pResult->GetString(0), len);
		((CConsole*)pSelf)->Register(cmdname, "?r", CFGFLAG_CLIENT|CFGFLAG_SERVER|CFGFLAG_CHAT, [](IConsole::IResult *, void *) {}, pSelf, "STUB");
	}), this, "Register dummy command");
	Register("register_alias", "sr", CFGFLAG_CLIENT|CFGFLAG_SERVER, ([](IConsole::IResult *pResult, void * pSelf)
	{
		int aliaslen = str_length(pResult->GetString(0)) + 1;
		char * aliasname = new char[aliaslen];
		str_copy(aliasname, pResult->GetString(0), aliaslen);
		
		int cmdlen = str_length(pResult->GetString(1)) + 1;
		char * cmdname = new char[cmdlen];
		str_copy(cmdname, pResult->GetString(1), cmdlen);
		
		((CConsole*)pSelf)->Register(aliasname, "?r", CFGFLAG_CLIENT|CFGFLAG_SERVER, ([](IConsole::IResult *pArgs, void * pUser)
		{
			auto& info = *(std::pair<CConsole *, char *> *)pUser;
			if(pArgs->NumArguments())
			{
				char aBuf[1024];
				str_format(aBuf, sizeof(aBuf), "%s %s", info.second, pArgs->GetString(0));
				info.first->ExecuteLine(aBuf, pArgs->m_ClientID);
			}
			else
			{
				info.first->ExecuteLine(info.second, pArgs->m_ClientID);
			}
		}), (void *)(new std::pair<CConsole *, char *>((CConsole*)pSelf, cmdname)), cmdname);
	}), this, "Register alias");
	

	/*Register("commands_size", "", CFGFLAG_SERVER|CFGFLAG_CLIENT, 
		([](IConsole::IResult *, void * ptr) 
		{
			CConsole * self = (CConsole *)ptr;
			char buf[128];
			str_format(buf, sizeof(buf), "size: %u load: %f", self->commands.size(), self->commands.load_factor());
			self->Print(IConsole::OUTPUT_LEVEL_STANDARD, "test", buf);
		}), this, "Total amount of commands");*/

	Register("set_timer", "iir", CFGFLAG_SERVER|CFGFLAG_CLIENT, ConSetTimer, this, "Exec command after n ms (the first argument is stroke)");
	Register("+set_timer", "ir", CFGFLAG_SERVER|CFGFLAG_CLIENT, ConSetTimer, this, "Exec command after n ms");
	Register("set_ticktimer", "iir", CFGFLAG_SERVER|CFGFLAG_CLIENT, ConSetTickTimer, this, "Exec command after n ticks (the first argument is stroke)");
	Register("+set_ticktimer", "ir", CFGFLAG_SERVER|CFGFLAG_CLIENT, ConSetTickTimer, this, "Exec command after n ticks");

	// TODO: this should disappear
	#define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Flags,Desc) \
	{ \
                static CNumericVariableData<int> Data = { this, &g_Config.m_##Name, Min, Max }; \
		Register(#ScriptName, "?i", Flags, IntVariableCommand, &Data, Desc); \
	}

#define MACRO_CONFIG_FLOAT(Name,ScriptName,Def,Min,Max,Flags,Desc)        \
        {                                                               \
                static CNumericVariableData<float> Data = { this, &g_Config.m_##Name, Min, Max }; \
                Register(#ScriptName, "?i", Flags, FloatVariableCommand, &Data, Desc); \
	}

	#define MACRO_CONFIG_STR(Name,ScriptName,Len,Def,Flags,Desc) \
	{ \
		static CStrVariableData Data = { this, g_Config.m_##Name, Len }; \
		Register(#ScriptName, "?r", Flags, StrVariableCommand, &Data, Desc); \
	}

	#include "config_variables.h"

	#undef MACRO_CONFIG_INT
	#undef MACRO_CONFIG_STR

	// DDRace

	m_Cheated = false;
}
示例#14
0
文件: console.cpp 项目: ftk/XXLDDRace
void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, int ClientID)
{
	while(pStr && *pStr)
	{
		CResult Result;
		Result.m_ClientID = ClientID;
		const char *pEnd = pStr;
		const char *pNextPart = 0;
		int InString = 0;

		while(*pEnd)
		{
			if(*pEnd == '"')
				InString ^= 1;
			else if(*pEnd == '\\') // escape sequences
			{
				if(pEnd[1] == '"')
					pEnd++;
			}
			else if(!InString)
			{
				if(*pEnd == ';') // command separator
				{
					pNextPart = pEnd+1;
					break;
				}
				else if(*pEnd == '#') // comment, no need to do anything more
					break;
			}

			pEnd++;
		}

		if(ParseStart(&Result, pStr, (pEnd-pStr) + 1) != 0)
			return;

		if(!*Result.m_pCommand)
			return;

		CCommand *pCommand = FindCommand(Result.m_pCommand, m_FlagMask);

		if(pCommand)
		{
			if(pCommand->GetAccessLevel() >= m_AccessLevel)
			{
				int IsStrokeCommand = 0;
				if(Result.m_pCommand[0] == '+')
				{
					// insert the stroke direction token
					Result.AddArgument(m_paStrokeStr[Stroke]);
					IsStrokeCommand = 1;
				}

				if(Stroke || IsStrokeCommand)
				{
					if(ParseArgs(&Result, pCommand->m_pParams))
					{
						char aBuf[256];
						str_format(aBuf, sizeof(aBuf), "Invalid arguments... Usage: %s %s", pCommand->m_pName, pCommand->m_pParams);
						Print(OUTPUT_LEVEL_STANDARD, "Console", aBuf);
					}
					else if(m_StoreCommands && pCommand->m_Flags&CFGFLAG_STORE)
					{
						m_ExecutionQueue.AddEntry();
						m_ExecutionQueue.m_pLast->m_pfnCommandCallback = pCommand->m_pfnCallback;
						m_ExecutionQueue.m_pLast->m_pCommandUserData = pCommand->m_pUserData;
						m_ExecutionQueue.m_pLast->m_Result = Result;
					}
					else
					{
						if(Result.GetVictim() == CResult::VICTIM_ME)
							Result.SetVictim(ClientID);

						if(pCommand->m_Flags&CMDFLAG_TEST && !g_Config.m_SvTestingCommands)
							return;

						if (Result.HasVictim())
						{
							if (m_AccessLevel == ACCESS_LEVEL_HELPER && Result.GetVictim() != ClientID)
								Print(OUTPUT_LEVEL_STANDARD, "Console", "Helpers can execute commands only on their self.");
							else
							{
								if(Result.GetVictim() == CResult::VICTIM_ALL)
								{
									for (int i = 0; i < MAX_CLIENTS; i++)
									{
										Result.SetVictim(i);
										pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
									}
								}
								else
									pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
							}
						}
						else
							pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
					}
				}
			}
			else if(Stroke)
			{
				char aBuf[256];
				str_format(aBuf, sizeof(aBuf), "Access for command %s denied.", Result.m_pCommand);
				Print(OUTPUT_LEVEL_STANDARD, "Console", aBuf);
			}
		}
		else if(Stroke)
		{
			char aBuf[256];
			str_format(aBuf, sizeof(aBuf), "No such command: %s.", Result.m_pCommand);
			Print(OUTPUT_LEVEL_STANDARD, "Console", aBuf);
		}

		pStr = pNextPart;
	}
}
示例#15
0
文件: hud.cpp 项目: Landil/teeworlds
void CHud::RenderScoreHud()
{
	int GameFlags = m_pClient->m_Snap.m_pGameobj->m_Flags;
	float Whole = 300*Graphics()->ScreenAspect();
	
	// render small score hud
	if(!(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver) && (GameFlags&GAMEFLAG_TEAMS))
	{
		char aScoreTeam[2][32];
		str_format(aScoreTeam[TEAM_RED], sizeof(aScoreTeam)/2, "%d", m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed);
		str_format(aScoreTeam[TEAM_BLUE], sizeof(aScoreTeam)/2, "%d", m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue);
		float aScoreTeamWidth[2] = {TextRender()->TextWidth(0, 14.0f, aScoreTeam[TEAM_RED], -1), TextRender()->TextWidth(0, 14.0f, aScoreTeam[TEAM_BLUE], -1)};
		float ScoreWidthMax = max(max(aScoreTeamWidth[TEAM_RED], aScoreTeamWidth[TEAM_BLUE]), TextRender()->TextWidth(0, 14.0f, "100", -1));
		float Split = 3.0f;
		float ImageSize = GameFlags&GAMEFLAG_FLAGS ? 16.0f : Split;
		
		for(int t = 0; t < 2; t++)
		{
			// draw box
			Graphics()->BlendNormal();
			Graphics()->TextureSet(-1);
			Graphics()->QuadsBegin();
			if(t == 0)
				Graphics()->SetColor(1.0f, 0.0f, 0.0f, 0.25f);
			else
				Graphics()->SetColor(0.0f, 0.0f, 1.0f, 0.25f);
			RenderTools()->DrawRoundRectExt(Whole-ScoreWidthMax-ImageSize-2*Split, 245.0f+t*20, ScoreWidthMax+ImageSize+2*Split, 18.0f, 5.0f, CUI::CORNER_L);
			Graphics()->QuadsEnd();

			// draw score
			TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreTeamWidth[t])/2-Split, 245.0f+t*20, 14.0f, aScoreTeam[t], -1);

			if(GameFlags&GAMEFLAG_FLAGS && m_pClient->m_Snap.m_paFlags[t])
			{
				if(m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy == -2 || (m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy == -1 && ((Client()->GameTick()/10)&1)))
				{
					// draw flag
					Graphics()->BlendNormal();
					Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
					Graphics()->QuadsBegin();
					RenderTools()->SelectSprite(t==0?SPRITE_FLAG_RED:SPRITE_FLAG_BLUE);
					IGraphics::CQuadItem QuadItem(Whole-ScoreWidthMax-ImageSize, 246.0f+t*20, ImageSize/2, ImageSize);
					Graphics()->QuadsDrawTL(&QuadItem, 1);
					Graphics()->QuadsEnd();
				}
				else if(m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy >= 0)
				{
					// draw name of the flag holder
					int Id = m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy%MAX_CLIENTS;
					const char *pName = m_pClient->m_aClients[Id].m_aName;
					float w = TextRender()->TextWidth(0, 10.0f, pName, -1);
					TextRender()->Text(0, Whole-ScoreWidthMax-ImageSize-3*Split-w, 247.0f+t*20, 10.0f, pName, -1);

					// draw tee of the flag holder
					CTeeRenderInfo Info = m_pClient->m_aClients[Id].m_RenderInfo;
					Info.m_Size = 18.0f;
					RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0),
						vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, 246.0f+Info.m_Size/2+t*20));
				}
			}
		}
	}
}
示例#16
0
	void FindDatadir(const char *pArgv0)
	{
		// 1) use data-dir in PWD if present
		if(fs_is_dir("data/mapres"))
		{
			str_copy(m_aDatadir, "data", sizeof(m_aDatadir));
			return;
		}

		// 2) use compiled-in data-dir if present
		if(fs_is_dir(DATA_DIR "/mapres"))
		{
			str_copy(m_aDatadir, DATA_DIR, sizeof(m_aDatadir));
			return;
		}

		// 3) check for usable path in argv[0]
		{
			unsigned int Pos = ~0U;
			for(unsigned i = 0; pArgv0[i]; i++)
				if(pArgv0[i] == '/' || pArgv0[i] == '\\')
					Pos = i;

			if(Pos < MAX_PATH_LENGTH)
			{
				char aBaseDir[MAX_PATH_LENGTH];
				str_copy(aBaseDir, pArgv0, Pos+1);
				str_format(m_aDatadir, sizeof(m_aDatadir), "%s/data", aBaseDir);
				str_append(aBaseDir, "/data/mapres", sizeof(aBaseDir));

				if(fs_is_dir(aBaseDir))
					return;
				else
					m_aDatadir[0] = 0;
			}
		}

	#if defined(CONF_FAMILY_UNIX)
		// 4) check for all default locations
		{
			const char *aDirs[] = {
				"/usr/share/teeworlds/data",
				"/usr/share/games/teeworlds/data",
				"/usr/local/share/teeworlds/data",
				"/usr/local/share/games/teeworlds/data",
				"/usr/pkg/share/teeworlds/data",
				"/usr/pkg/share/games/teeworlds/data",
				"/opt/teeworlds/data"
			};
			const int DirsCount = sizeof(aDirs) / sizeof(aDirs[0]);

			int i;
			for (i = 0; i < DirsCount; i++)
			{
				char aBuf[128];
				str_format(aBuf, sizeof(aBuf), "%s/mapres", aDirs[i]);
				if(fs_is_dir(aBuf))
				{
					str_copy(m_aDatadir, aDirs[i], sizeof(m_aDatadir));
					return;
				}
			}
		}
	#endif

		// no data-dir found
		dbg_msg("storage", "warning no data directory found");
	}
示例#17
0
void CChat::AddLine(int ClientID, int Team, const char *pLine)
{
	if(ClientID != -1 && m_pClient->m_aClients[ClientID].m_aName[0] == '\0') // unknown client
		return;
	
	char *p = const_cast<char*>(pLine);
	while(*p)
	{
		pLine = p;
		// find line seperator and strip multiline
		while(*p)
		{
			if(*p++ == '\n')
			{
				*(p-1) = 0;
				break;
			}
		}

		m_CurrentLine = (m_CurrentLine+1)%MAX_LINES;
		m_aLines[m_CurrentLine].m_Time = time_get();
		m_aLines[m_CurrentLine].m_YOffset[0] = -1.0f;
		m_aLines[m_CurrentLine].m_YOffset[1] = -1.0f;
		m_aLines[m_CurrentLine].m_ClientID = ClientID;
		m_aLines[m_CurrentLine].m_Team = Team;
		m_aLines[m_CurrentLine].m_NameColor = -2;
		m_aLines[m_CurrentLine].m_Highlighted = str_find_nocase(pLine, m_pClient->m_aClients[m_pClient->m_Snap.m_LocalClientID].m_aName) != 0;

		if(ClientID == -1) // server message
		{
			str_copy(m_aLines[m_CurrentLine].m_aName, "*** ", sizeof(m_aLines[m_CurrentLine].m_aName));
			str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), "%s", pLine);
		}
		else
		{
			if(m_pClient->m_aClients[ClientID].m_Team == TEAM_SPECTATORS)
				m_aLines[m_CurrentLine].m_NameColor = TEAM_SPECTATORS;

			if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS)
			{
				if(m_pClient->m_aClients[ClientID].m_Team == TEAM_RED)
					m_aLines[m_CurrentLine].m_NameColor = TEAM_RED;
				else if(m_pClient->m_aClients[ClientID].m_Team == TEAM_BLUE)
					m_aLines[m_CurrentLine].m_NameColor = TEAM_BLUE;
			}
			
			str_copy(m_aLines[m_CurrentLine].m_aName, m_pClient->m_aClients[ClientID].m_aName, sizeof(m_aLines[m_CurrentLine].m_aName));
			str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), ": %s", pLine);
		}
		
		char aBuf[1024];
		str_format(aBuf, sizeof(aBuf), "%s%s", m_aLines[m_CurrentLine].m_aName, m_aLines[m_CurrentLine].m_aText);
		Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chat", aBuf);
	}

	// play sound
	if(ClientID >= 0)
		m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0, vec2(0,0));
	else
		m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_SERVER, 0, vec2(0,0));
}
示例#18
0
	const char *GetPath(int Type, const char *pDir, char *pBuffer, unsigned BufferSize)
	{
		str_format(pBuffer, BufferSize, "%s%s%s", m_aaStoragePaths[Type], !m_aaStoragePaths[Type][0] ? "" : "/", pDir);
		return pBuffer;
	}
示例#19
0
bool CSqlScore::Connect()
{
    try
    {
        // Create connection
        m_pDriver = get_driver_instance();
        char aBuf[256];
        str_format(aBuf, sizeof(aBuf), "tcp://%s:%d", m_pIp, m_Port);
        m_pConnection = m_pDriver->connect(aBuf, m_pUser, m_pPass);

        // Create Statement
        m_pStatement = m_pConnection->createStatement();

        // Create database if not exists
        str_format(aBuf, sizeof(aBuf), "CREATE DATABASE IF NOT EXISTS %s", m_pDatabase);
        m_pStatement->execute(aBuf);

        // Connect to specific database
        m_pConnection->setSchema(m_pDatabase);
        dbg_msg("SQL", "SQL connection established");
        return true;
    }
    catch (sql::SQLException &e)
    {
        char aBuf[256];
        str_format(aBuf, sizeof(aBuf), "MySQL Error: %s", e.what());
        dbg_msg("SQL", aBuf);

        dbg_msg("SQL", "ERROR: SQL connection failed");
        return false;
    }
    catch (const std::exception& ex) {
        // ...
        dbg_msg("SQL", "1 %s",ex.what());

    } catch (const std::string& ex) {
        // ...
        dbg_msg("SQL", "2 %s",ex.c_str());
    }
    catch( int )
    {
        dbg_msg("SQL", "3 %s");
    }
    catch( float )
    {
        dbg_msg("SQL", "4 %s");
    }

    catch( char[] )
    {
        dbg_msg("SQL", "5 %s");
    }

    catch( char )
    {
        dbg_msg("SQL", "6 %s");
    }
    catch (...)
    {
        dbg_msg("SQL", "Unknown Error cause by the MySQL/C++ Connector, my advice compile server_debug and use it");

        dbg_msg("SQL", "ERROR: SQL connection failed");
        return false;
    }
    return false;
}
示例#20
0
void DEBUGHUD::render_tuning()
{
	// render tuning debugging
	if(!config.dbg_tuning)
		return;
		
	TUNING_PARAMS standard_tuning;
		
	gfx_mapscreen(0, 0, 300*gfx_screenaspect(), 300);
	
	float y = 50.0f;
	int count = 0;
	for(int i = 0; i < gameclient.tuning.num(); i++)
	{
		char buf[128];
		float current, standard;
		gameclient.tuning.get(i, &current);
		standard_tuning.get(i, &standard);
		
		if(standard == current)
			gfx_text_color(1,1,1,1.0f);
		else
			gfx_text_color(1,0.25f,0.25f,1.0f);

		float w;
		float x = 5.0f;
		
		str_format(buf, sizeof(buf), "%.2f", standard);
		x += 20.0f;
		w = gfx_text_width(0, 5, buf, -1);
		gfx_text(0x0, x-w, y+count*6, 5, buf, -1);

		str_format(buf, sizeof(buf), "%.2f", current);
		x += 20.0f;
		w = gfx_text_width(0, 5, buf, -1);
		gfx_text(0x0, x-w, y+count*6, 5, buf, -1);

		x += 5.0f;
		gfx_text(0x0, x, y+count*6, 5, gameclient.tuning.names[i], -1);
		
		count++;
	}
	
	y = y+count*6;
	
	gfx_texture_set(-1);
	gfx_blend_normal();
	gfx_lines_begin();
	float height = 50.0f;
	float pv = 1;
	for(int i = 0; i < 100; i++)
	{
		float speed = i/100.0f * 3000;
		float ramp = velocity_ramp(speed, gameclient.tuning.velramp_start, gameclient.tuning.velramp_range, gameclient.tuning.velramp_curvature);
		float rampedspeed = (speed * ramp)/1000.0f;
		gfx_lines_draw((i-1)*2, y+height-pv*height, i*2, y+height-rampedspeed*height);
		//gfx_lines_draw((i-1)*2, 200, i*2, 200);
		pv = rampedspeed;
	}
	gfx_lines_end();
	gfx_text_color(1,1,1,1);
}
示例#21
0
void CSqlScore::agoTimeToString(int agoTime, char agoString[]) {
    char aBuf[20];
    int times[7] = {
        60 * 60 * 24 * 365 ,
        60 * 60 * 24 * 30 ,
        60 * 60 * 24 * 7,
        60 * 60 * 24 ,
        60 * 60 ,
        60 ,
        1
    };
    char names[7][6] = {
        "year",
        "month",
        "week",
        "day",
        "hour",
        "min",
        "sec"
    };

    int seconds = 0;
    char name[6];
    int count = 0;
    int i = 0;

    // finding biggest match
    for(i = 0; i<7; i++) {
        seconds = times[i];
        strcpy(name,names[i]);

        count = floor((float)agoTime/(float)seconds);
        if(count != 0) {
            break;
        }
    }

    if(count == 1) {
        str_format(aBuf, sizeof(aBuf), "%d %s", 1 , name);
    } else {
        str_format(aBuf, sizeof(aBuf), "%d %ss", count , name);
    }
    strcat(agoString,aBuf);

    if (i + 1 < 7) {
        // getting second piece now
        int seconds2 = times[i+1];
        char name2[6];
        strcpy(name2,names[i+1]);

        // add second piece if it's greater than 0
        int count2 = floor((float)(agoTime - (seconds * count)) / (float)seconds2);

        if (count2 != 0) {
            if(count2 == 1) {
                str_format(aBuf, sizeof(aBuf), " and %d %s", 1 , name2);
            } else {
                str_format(aBuf, sizeof(aBuf), " and %d %ss", count2 , name2);
            }
            strcat(agoString,aBuf);
        }
    }
}
示例#22
0
文件: nameplates.cpp 项目: Laxa/ddnet
void CNamePlates::RenderNameplate(
	const CNetObj_Character *pPrevChar,
	const CNetObj_Character *pPlayerChar,
	const CNetObj_PlayerInfo *pPlayerInfo
	)
{
	float IntraTick = Client()->IntraGameTick();
	int ClientID = pPlayerInfo->m_ClientID;

	vec2 Position;
	if((!m_pClient->AntiPingPlayers() && !pPlayerInfo->m_Local) || m_pClient->m_Snap.m_SpecInfo.m_Active)
	{
		Position = mix(vec2(pPrevChar->m_X, pPrevChar->m_Y), vec2(pPlayerChar->m_X, pPlayerChar->m_Y), IntraTick);
	}
	else if(!m_pClient->AntiPingPlayers() && pPlayerInfo->m_Local)
	{
		Position = vec2(m_pClient->m_LocalCharacterPos.x, m_pClient->m_LocalCharacterPos.y);
	}
	else
	{
		Position = m_pPlayers->m_CurPredictedPos[ClientID];
	}

	bool OtherTeam;

	if(m_pClient->m_aClients[m_pClient->m_Snap.m_LocalClientID].m_Team == TEAM_SPECTATORS && m_pClient->m_Snap.m_SpecInfo.m_SpectatorID == SPEC_FREEVIEW)
		OtherTeam = false;
	else if(m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_Snap.m_SpecInfo.m_SpectatorID != SPEC_FREEVIEW)
		OtherTeam = m_pClient->m_Teams.Team(pPlayerInfo->m_ClientID) != m_pClient->m_Teams.Team(m_pClient->m_Snap.m_SpecInfo.m_SpectatorID);
	else
		OtherTeam = m_pClient->m_Teams.Team(pPlayerInfo->m_ClientID) != m_pClient->m_Teams.Team(m_pClient->m_Snap.m_LocalClientID);

	float FontSize = 18.0f + 20.0f * g_Config.m_ClNameplatesSize / 100.0f;
	float FontSizeClan = 18.0f + 20.0f * g_Config.m_ClNameplatesClanSize / 100.0f;
	// render name plate
	if(!pPlayerInfo->m_Local || g_Config.m_ClNameplatesOwn)
	{
		float a = 1;
		if(g_Config.m_ClNameplatesAlways == 0)
			a = clamp(1-powf(distance(m_pClient->m_pControls->m_TargetPos[g_Config.m_ClDummy], Position)/200.0f,16.0f), 0.0f, 1.0f);

		const char *pName = m_pClient->m_aClients[pPlayerInfo->m_ClientID].m_aName;
		if(str_comp(pName, m_aNamePlates[ClientID].m_aName) != 0 || FontSize != m_aNamePlates[ClientID].m_NameTextFontSize)
		{
			mem_copy(m_aNamePlates[ClientID].m_aName, pName, sizeof(m_aNamePlates[ClientID].m_aName));
			m_aNamePlates[ClientID].m_NameTextFontSize = FontSize;

			m_aNamePlates[ClientID].m_NameTextWidth = TextRender()->TextWidth(0, FontSize, pName, -1);

			if(m_aNamePlates[ClientID].m_NameTextContainerIndex != -1)
				TextRender()->DeleteTextContainer(m_aNamePlates[ClientID].m_NameTextContainerIndex);

			CTextCursor Cursor;
			TextRender()->SetCursor(&Cursor, 0, 0, FontSize, TEXTFLAG_RENDER);
			Cursor.m_LineWidth = -1;

			// create nameplates at standard zoom
			float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
			Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
			MapscreenToGroup(m_pClient->m_pCamera->m_Center.x, m_pClient->m_pCamera->m_Center.y, Layers()->GameGroup());
			m_aNamePlates[ClientID].m_NameTextContainerIndex = TextRender()->CreateTextContainer(&Cursor, pName);
			Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1);
		}

		if(g_Config.m_ClNameplatesClan)
		{
			const char *pClan = m_pClient->m_aClients[ClientID].m_aClan;
			if(str_comp(pClan, m_aNamePlates[ClientID].m_aClanName) != 0 || FontSizeClan != m_aNamePlates[ClientID].m_ClanNameTextFontSize)
			{
				mem_copy(m_aNamePlates[ClientID].m_aClanName, pClan, sizeof(m_aNamePlates[ClientID].m_aClanName));
				m_aNamePlates[ClientID].m_ClanNameTextFontSize = FontSizeClan;

				m_aNamePlates[ClientID].m_ClanNameTextWidth = TextRender()->TextWidth(0, FontSizeClan, pClan, -1);

				if(m_aNamePlates[ClientID].m_ClanNameTextContainerIndex != -1)
					TextRender()->DeleteTextContainer(m_aNamePlates[ClientID].m_ClanNameTextContainerIndex);

				CTextCursor Cursor;
				TextRender()->SetCursor(&Cursor, 0, 0, FontSizeClan, TEXTFLAG_RENDER);
				Cursor.m_LineWidth = -1;

				// create nameplates at standard zoom
				float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
				Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
				MapscreenToGroup(m_pClient->m_pCamera->m_Center.x, m_pClient->m_pCamera->m_Center.y, Layers()->GameGroup());
				m_aNamePlates[ClientID].m_ClanNameTextContainerIndex = TextRender()->CreateTextContainer(&Cursor, pClan);
				Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1);
			}
		}

		float tw = m_aNamePlates[ClientID].m_NameTextWidth;
		vec3 rgb = vec3(1.0f, 1.0f, 1.0f);
		if(g_Config.m_ClNameplatesTeamcolors && m_pClient->m_Teams.Team(ClientID))
			rgb = HslToRgb(vec3(m_pClient->m_Teams.Team(ClientID) / 64.0f, 1.0f, 0.75f));

		STextRenderColor TColor;
		STextRenderColor TOutlineColor;

		if(OtherTeam)
		{
			TOutlineColor.Set(0.0f, 0.0f, 0.0f, 0.2f);
			TColor.Set(rgb.r, rgb.g, rgb.b, g_Config.m_ClShowOthersAlpha / 100.0f);
		}
		else
		{
			TOutlineColor.Set(0.0f, 0.0f, 0.0f, 0.5f*a);
			TColor.Set(rgb.r, rgb.g, rgb.b, a);
		}
		if(g_Config.m_ClNameplatesTeamcolors && m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS)
		{
			if(m_pClient->m_aClients[ClientID].m_Team == TEAM_RED)
				TColor.Set(1.0f, 0.5f, 0.5f, a);
			else if(m_pClient->m_aClients[ClientID].m_Team == TEAM_BLUE)
				TColor.Set(0.7f, 0.7f, 1.0f, a);
		}

		if(m_aNamePlates[ClientID].m_NameTextContainerIndex != -1)
			TextRender()->RenderTextContainer(m_aNamePlates[ClientID].m_NameTextContainerIndex, &TColor, &TOutlineColor, Position.x - tw / 2.0f, Position.y - FontSize - 38.0f);

		if(g_Config.m_ClNameplatesClan)
		{
			if(m_aNamePlates[ClientID].m_ClanNameTextContainerIndex != -1)
				TextRender()->RenderTextContainer(m_aNamePlates[ClientID].m_ClanNameTextContainerIndex, &TColor, &TOutlineColor, Position.x - m_aNamePlates[ClientID].m_ClanNameTextWidth / 2.0f, Position.y - FontSize - FontSizeClan - 38.0f);
		}

		if(g_Config.m_Debug) // render client id when in debug as well
		{
			char aBuf[128];
			str_format(aBuf, sizeof(aBuf),"%d", pPlayerInfo->m_ClientID);
			float Offset = g_Config.m_ClNameplatesClan ? (FontSize * 2 + FontSizeClan) : (FontSize * 2);
			float tw_id = TextRender()->TextWidth(0, FontSize, aBuf, -1);
			TextRender()->Text(0, Position.x-tw_id/2.0f, Position.y-Offset-38.0f, 28.0f, aBuf, -1);
		}

		TextRender()->TextColor(1,1,1,1);
		TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f);
	}
}
示例#23
0
/*
	TODO: chopp up this function into smaller working parts
*/
int CNetServer::Recv(CNetChunk *pChunk)
{
	while(1)
	{
		NETADDR Addr;

		// check for a chunk
		if(m_RecvUnpacker.FetchChunk(pChunk))
			return 1;

		// TODO: empty the recvinfo
		int Bytes = net_udp_recv(m_Socket, &Addr, m_RecvUnpacker.m_aBuffer, NET_MAX_PACKETSIZE);

		// no more packets for now
		if(Bytes <= 0)
			break;

		if(CNetBase::UnpackPacket(m_RecvUnpacker.m_aBuffer, Bytes, &m_RecvUnpacker.m_Data) == 0)
		{
			// check if we just should drop the packet
			char aBuf[128];
			if(NetBan() && NetBan()->IsBanned(&Addr, aBuf, sizeof(aBuf)))
			{
				// banned, reply with a message
				CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, aBuf, str_length(aBuf)+1);
				continue;
			}

			if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONNLESS)
			{
				pChunk->m_Flags = NETSENDFLAG_CONNLESS;
				pChunk->m_ClientID = -1;
				pChunk->m_Address = Addr;
				pChunk->m_DataSize = m_RecvUnpacker.m_Data.m_DataSize;
				pChunk->m_pData = m_RecvUnpacker.m_Data.m_aChunkData;
				return 1;
			}
			else
			{
				// TODO: check size here
				if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONTROL && m_RecvUnpacker.m_Data.m_aChunkData[0] == NET_CTRLMSG_CONNECT)
				{
					bool Found = false;

					// check if we already got this client
					for(int i = 0; i < MaxClients(); i++)
					{
						if(m_aSlots[i].m_Connection.State() != NET_CONNSTATE_OFFLINE &&
							net_addr_comp(m_aSlots[i].m_Connection.PeerAddress(), &Addr) == 0)
						{
							Found = true; // silent ignore.. we got this client already
							break;
						}
					}

					// client that wants to connect
					if(!Found)
					{
						// only allow a specific number of players with the same ip
						NETADDR ThisAddr = Addr, OtherAddr;
						int FoundAddr = 1;
						ThisAddr.port = 0;
						for(int i = 0; i < MaxClients(); ++i)
						{
							if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE)
								continue;

							OtherAddr = *m_aSlots[i].m_Connection.PeerAddress();
							OtherAddr.port = 0;
							if(!net_addr_comp(&ThisAddr, &OtherAddr))
							{
								if(FoundAddr++ >= m_MaxClientsPerIP)
								{
									char aBuf[128];
									str_format(aBuf, sizeof(aBuf), "Only %d players with the same IP are allowed", m_MaxClientsPerIP);
									CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, aBuf, sizeof(aBuf));
									return 0;
								}
							}
						}

						for(int i = 0; i < MaxClients(); i++)
						{
							if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE)
							{
								Found = true;
								m_aSlots[i].m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr);
								if(m_pfnNewClient)
									m_pfnNewClient(i, m_UserPtr);
								break;
							}
						}

						if(!Found)
						{
							const char FullMsg[] = "This server is full";
							CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, FullMsg, sizeof(FullMsg));
						}
					}
				}
				else
				{
					// normal packet, find matching slot
					for(int i = 0; i < MaxClients(); i++)
					{
						if(net_addr_comp(m_aSlots[i].m_Connection.PeerAddress(), &Addr) == 0)
						{
							if(m_aSlots[i].m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr))
							{
								if(m_RecvUnpacker.m_Data.m_DataSize)
									m_RecvUnpacker.Start(&Addr, &m_aSlots[i].m_Connection, i);
							}
						}
					}
				}
			}
		}
	}
	return 0;
}
示例#24
0
void mods_message(int msgtype, int client_id)
{
	void *rawmsg = netmsg_secure_unpack(msgtype);
	PLAYER *p = game.players[client_id];
	
	if(!rawmsg)
	{
		dbg_msg("server", "dropped weird message '%s' (%d), failed on '%s'", netmsg_get_name(msgtype), msgtype, netmsg_failed_on());
		return;
	}
	
	if(msgtype == NETMSGTYPE_CL_SAY)
	{
		NETMSG_CL_SAY *msg = (NETMSG_CL_SAY *)rawmsg;
		int team = msg->team;
		if(team)
			team = p->team;
		else
			team = GAMECONTEXT::CHAT_ALL;
		
		if(config.sv_spamprotection && p->last_chat+time_freq() > time_get())
		{
			if(!strcmp(msg->message, "/rank") && game.controller->is_race())
				game.players[client_id]->last_chat = time_get()+time_freq()*10;
			else 
				game.players[client_id]->last_chat = time_get();
		}
		else
 		{
			game.players[client_id]->last_chat = time_get();
			if(!strcmp(msg->message, "/info"))
			{
				char buf[128];
				str_format(buf, sizeof(buf), "DJUMP 0.32 from EliteKuchen.", RACE_VERSION);
				game.send_chat_target(client_id, buf);
				str_format(buf, sizeof(buf), "based on : Race mod %s from Rajh and Redix.", RACE_VERSION);
				game.send_chat_target(client_id, buf);
			}
			else if(!strncmp(msg->message, "/top5", 5) && game.controller->is_race())
			{
				const char *pt = msg->message;
				int number = 0;
				pt += 6;
				while(*pt && *pt >= '0' && *pt <= '9')
				{
					number = number*10+(*pt-'0');
					pt++;
				}
				if(number)
					((GAMECONTROLLER_RACE*)game.controller)->score.top5_draw(client_id, number);
				else
					((GAMECONTROLLER_RACE*)game.controller)->score.top5_draw(client_id, 0);
			}
			else if(!strncmp(msg->message, "/rank", 5) && game.controller->is_race())
			{
				char buf[512];
				const char *name = msg->message;
				name += 6;
				int pos;
				PLAYER_SCORE *pscore;
				
				if(!strcmp(msg->message, "/rank"))
					pscore = ((GAMECONTROLLER_RACE*)game.controller)->score.search_score(client_id, 1, &pos);
				else
					pscore = ((GAMECONTROLLER_RACE*)game.controller)->score.search_name(name, &pos, 1);
				
				if(pscore && pos > -1)
				{
					int punkte = pscore->points;
					char client_name[128];
					str_format(client_name, sizeof(client_name), " (%s)", server_clientname(client_id));
					str_format(buf, sizeof(buf), "%d. %s Points:%d", pos, pscore->name, punkte);
					if(strcmp(msg->message, "/rank"))
						strcat(buf, client_name);
					game.send_chat(-1, GAMECONTEXT::CHAT_ALL, buf);
					game.players[client_id]->last_chat = time_get()+time_freq()*3;
					return;
				}
				else if(pos == -1)
					str_format(buf, sizeof(buf), "Several players were found.");
				else
					str_format(buf, sizeof(buf), "%s is not ranked", strcmp(msg->message, "/rank")?name:server_clientname(client_id));
				
				game.send_chat_target(client_id, buf);
			}
			else if(!strcmp(msg->message, "/cmdlist"))
			{
				game.send_chat_target(client_id, "---Command List---");
				game.send_chat_target(client_id, "\"/info\" information about the mod");
				game.send_chat_target(client_id, "\"/rank\" shows your rank");
				game.send_chat_target(client_id, "\"/rank NAME\" shows the rank of a specific player");
				game.send_chat_target(client_id, "\"/top5 X\" shows the top 5");
			}
			else if(!strncmp(msg->message, "/", 1))
			{
				game.send_chat_target(client_id, "Wrong command.");
				game.send_chat_target(client_id, "Say \"/cmdlist\" for list of command available.");
			}
			else
				game.send_chat(client_id, team, msg->message);
		}
	}
	else if(msgtype == NETMSGTYPE_CL_CALLVOTE)
	{
		int64 now = time_get();
		if(game.vote_closetime)
		{
			game.send_chat_target(client_id, "Wait for current vote to end before calling a new one.");
			return;
		}
		
		int64 timeleft = p->last_votecall + time_freq()*60 - now;
		if(timeleft > 0)
		{
			char chatmsg[512] = {0};
			str_format(chatmsg, sizeof(chatmsg), "You must wait %d seconds before making another vote", (timeleft/time_freq())+1);
			game.send_chat_target(client_id, chatmsg);
			return;
		}
		
		char chatmsg[512] = {0};
		char desc[512] = {0};
		char cmd[512] = {0};
		NETMSG_CL_CALLVOTE *msg = (NETMSG_CL_CALLVOTE *)rawmsg;
		if(str_comp_nocase(msg->type, "option") == 0)
		{
			VOTEOPTION *option = voteoption_first;
			while(option)
			{
				if(str_comp_nocase(msg->value, option->command) == 0)
				{
					str_format(chatmsg, sizeof(chatmsg), "%s called vote to change server option '%s'", server_clientname(client_id), option->command);
					str_format(desc, sizeof(desc), "%s", option->command);
					str_format(cmd, sizeof(cmd), "%s", option->command);
					break;
				}

				option = option->next;
			}
			
			if(!option)
			{
				str_format(chatmsg, sizeof(chatmsg), "'%s' isn't an option on this server", msg->value);
				game.send_chat_target(client_id, chatmsg);
				return;
			}
		}
		else if(str_comp_nocase(msg->type, "kick") == 0)
		{
			if(!config.sv_vote_kick)
			{
				game.send_chat_target(client_id, "Server does not allow voting to kick players");
				return;
			}
			
			int kick_id = atoi(msg->value);
			if(kick_id < 0 || kick_id >= MAX_CLIENTS || !game.players[kick_id])
			{
				game.send_chat_target(client_id, "Invalid client id to kick");
				return;
			}
			
			str_format(chatmsg, sizeof(chatmsg), "%s called for vote to kick '%s'", server_clientname(client_id), server_clientname(kick_id));
			str_format(desc, sizeof(desc), "Kick '%s'", server_clientname(kick_id));
			str_format(cmd, sizeof(cmd), "kick %d", kick_id);
			if (!config.sv_vote_kick_bantime)
				str_format(cmd, sizeof(cmd), "kick %d", kick_id);
			else
				str_format(cmd, sizeof(cmd), "ban %d %d", kick_id, config.sv_vote_kick_bantime);
		}
		
		if(cmd[0])
		{
			game.send_chat(-1, GAMECONTEXT::CHAT_ALL, chatmsg);
			game.start_vote(desc, cmd);
			p->vote = 1;
			game.vote_creator = client_id;
			p->last_votecall = now;
			game.send_vote_status(-1);
		}
	}
	else if(msgtype == NETMSGTYPE_CL_VOTE)
	{
		if(!game.vote_closetime)
			return;

		if(p->vote == 0)
		{
			NETMSG_CL_VOTE *msg = (NETMSG_CL_VOTE *)rawmsg;
			p->vote = msg->vote;
			game.send_vote_status(-1);
		}
	}
	else if (msgtype == NETMSGTYPE_CL_SETTEAM && !game.world.paused)
	{
		NETMSG_CL_SETTEAM *msg = (NETMSG_CL_SETTEAM *)rawmsg;
		
		if(p->team == msg->team || (config.sv_spamprotection && p->last_setteam+time_freq()*3 > time_get()))
			return;

		// Switch team on given client and kill/respawn him
		if(game.controller->can_join_team(msg->team, client_id))
		{
			if(game.controller->can_change_team(p, msg->team))
			{
				p->last_setteam = time_get();
				p->set_team(msg->team);
				(void) game.controller->check_team_balance();
			}
			else
				game.send_broadcast("Teams must be balanced, please join other team", client_id);
		}
		else
		{
			char buf[128];
			str_format(buf, sizeof(buf), "Only %d active players are allowed", config.sv_max_clients-config.sv_spectator_slots);
			game.send_broadcast(buf, client_id);
		}
	}
	else if (msgtype == NETMSGTYPE_CL_CHANGEINFO || msgtype == NETMSGTYPE_CL_STARTINFO)
	{
		NETMSG_CL_CHANGEINFO *msg = (NETMSG_CL_CHANGEINFO *)rawmsg;
		
		if(config.sv_spamprotection && p->last_changeinfo+time_freq()*5 > time_get())
			return;
			
		p->last_changeinfo = time_get();
		
		p->use_custom_color = msg->use_custom_color;
		p->color_body = msg->color_body;
		p->color_feet = msg->color_feet;

		// check for invalid chars
		unsigned char *name = (unsigned char *)msg->name;
		while (*name)
		{
			if(*name < 32)
				*name = ' ';
			name++;
		}

		// copy old name
		char oldname[MAX_NAME_LENGTH];
		str_copy(oldname, server_clientname(client_id), MAX_NAME_LENGTH);
		
		server_setclientname(client_id, msg->name);
		if(msgtype == NETMSGTYPE_CL_CHANGEINFO && strcmp(oldname, server_clientname(client_id)) != 0)
		{
			char chattext[256];
			str_format(chattext, sizeof(chattext), "%s changed name to %s", oldname, server_clientname(client_id));
			game.send_chat(-1, GAMECONTEXT::CHAT_ALL, chattext);
		}
		
		// set skin
		str_copy(p->skin_name, msg->skin, sizeof(p->skin_name));
		
		game.controller->on_player_info_change(p);
		
		if(msgtype == NETMSGTYPE_CL_STARTINFO)
		{
			// send vote options
			NETMSG_SV_VOTE_CLEAROPTIONS clearmsg;
			clearmsg.pack(MSGFLAG_VITAL);
			server_send_msg(client_id);
			VOTEOPTION *current = voteoption_first;
			while(current)
			{
				NETMSG_SV_VOTE_OPTION optionmsg;
				optionmsg.command = current->command;
				optionmsg.pack(MSGFLAG_VITAL);
				server_send_msg(client_id);
				current = current->next;
			}
			
			// send tuning parameters to client
			send_tuning_params(client_id);

			//
			NETMSG_SV_READYTOENTER m;
			m.pack(MSGFLAG_VITAL|MSGFLAG_FLUSH);
			server_send_msg(client_id);
		}
	}
	else if (msgtype == NETMSGTYPE_CL_EMOTICON && !game.world.paused)
	{
		NETMSG_CL_EMOTICON *msg = (NETMSG_CL_EMOTICON *)rawmsg;
		
		if(config.sv_spamprotection && p->last_emote+time_freq()*3 > time_get())
			return;
			
		p->last_emote = time_get();
		
		game.send_emoticon(client_id, msg->emoticon);
	}
	else if (msgtype == NETMSGTYPE_CL_KILL && !game.world.paused)
	{
		if(p->last_kill+time_freq()*3 > time_get())
			return;
		
		p->last_kill = time_get();
		p->kill_character(WEAPON_SELF);
		p->respawn_tick = server_tick()+server_tickspeed()*3;
		if(game.controller->is_race())
			p->respawn_tick = server_tick();
	}
}
示例#25
0
void CCharacter::TickDefered()
{
	// advance the dummy
	{
		CWorldCore TempWorld;
		m_ReckoningCore.Init(&TempWorld, GameServer()->Collision());
		m_ReckoningCore.Tick(false);
		m_ReckoningCore.Move();
		m_ReckoningCore.Quantize();
	}

	//lastsentcore
	vec2 StartPos = m_Core.m_Pos;
	vec2 StartVel = m_Core.m_Vel;
	bool StuckBefore = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f));

	m_Core.Move();
	bool StuckAfterMove = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f));
	m_Core.Quantize();
	bool StuckAfterQuant = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f));
	m_Pos = m_Core.m_Pos;

	if(!StuckBefore && (StuckAfterMove || StuckAfterQuant))
	{
		// Hackish solution to get rid of strict-aliasing warning
		union
		{
			float f;
			unsigned u;
		}StartPosX, StartPosY, StartVelX, StartVelY;

		StartPosX.f = StartPos.x;
		StartPosY.f = StartPos.y;
		StartVelX.f = StartVel.x;
		StartVelY.f = StartVel.y;

		char aBuf[256];
		str_format(aBuf, sizeof(aBuf), "STUCK!!! %d %d %d %f %f %f %f %x %x %x %x",
			StuckBefore,
			StuckAfterMove,
			StuckAfterQuant,
			StartPos.x, StartPos.y,
			StartVel.x, StartVel.y,
			StartPosX.u, StartPosY.u,
			StartVelX.u, StartVelY.u);
		GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
	}

	int Events = m_Core.m_TriggeredEvents;
	int Mask = CmaskAllExceptOne(m_pPlayer->GetCID());

	if(Events&COREEVENT_GROUND_JUMP) GameServer()->CreateSound(m_Pos, SOUND_PLAYER_JUMP, Mask);

	if(Events&COREEVENT_HOOK_ATTACH_PLAYER) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_PLAYER, CmaskAll());
	if(Events&COREEVENT_HOOK_ATTACH_GROUND) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_GROUND, Mask);
	if(Events&COREEVENT_HOOK_HIT_NOHOOK) GameServer()->CreateSound(m_Pos, SOUND_HOOK_NOATTACH, Mask);


	if(m_pPlayer->GetTeam() == TEAM_SPECTATORS)
	{
		m_Pos.x = m_Input.m_TargetX;
		m_Pos.y = m_Input.m_TargetY;
	}

	// update the m_SendCore if needed
	{
		CNetObj_Character Predicted;
		CNetObj_Character Current;
		mem_zero(&Predicted, sizeof(Predicted));
		mem_zero(&Current, sizeof(Current));
		m_ReckoningCore.Write(&Predicted);
		m_Core.Write(&Current);

		// only allow dead reackoning for a top of 3 seconds
		if(m_ReckoningTick+Server()->TickSpeed()*3 < Server()->Tick() || mem_comp(&Predicted, &Current, sizeof(CNetObj_Character)) != 0)
		{
			m_ReckoningTick = Server()->Tick();
			m_SendCore = m_Core;
			m_ReckoningCore = m_Core;
		}
	}
}
示例#26
0
// TODO: Ugly but works
bool CUpdater::GetFile(const char *url, const char *path)
{
	NETSOCKET Socket = invalid_socket;
	NETADDR HostAddress, BindAddr;
    mem_zero(&HostAddress, sizeof(HostAddress));
    mem_zero(&BindAddr, sizeof(BindAddr));
	char aNetBuff[1024];

	//Lookup
	if(net_host_lookup(UPDATES_HOST, &HostAddress, NETTYPE_IPV4) != 0)
	{
		dbg_msg("autoupdate", "Error running host lookup");
		return false;
	}
	HostAddress.port = 80;

	//Connect
    BindAddr.type = NETTYPE_IPV4;
	Socket = net_tcp_create(BindAddr);
	if(net_tcp_connect(Socket, &HostAddress) != 0)
	{
		net_tcp_close(Socket);
		dbg_msg("autoupdate","Error connecting to host");
		return false;
	}

	//Send request
	str_format(aNetBuff, sizeof(aNetBuff), "GET "UPDATES_BASE_PATH"%s HTTP/1.0\r\nHost: "UPDATES_HOST"\r\n\r\n", url);
	net_tcp_send(Socket, aNetBuff, str_length(aNetBuff));

	//read data
	IOHANDLE dstFile = 0;

	std::string NetData;
	int TotalRecv = 0, TotalBytes = 0, CurrentRecv = 0, enterCtrl = 0;
	bool isHead = true, isStatusLine = true;
	while ((CurrentRecv = net_tcp_recv(Socket, aNetBuff, sizeof(aNetBuff))) > 0)
	{
		for (int i=0; i<CurrentRecv ; i++)
		{
			if (isHead)
			{
				if (aNetBuff[i]=='\n')
				{
					if (++enterCtrl == 2) // Go To Body Part
					{
                        dstFile = io_open(path, IOFLAG_WRITE);
                        if (!dstFile)
                        {
                            net_tcp_close(Socket);
                            dbg_msg("autoupdate","Error writing to disk");
                            return false;
                        }

                        str_copy(m_CurrentDownloadFileName, url, sizeof(m_CurrentDownloadFileName));

						isHead = false;
						NetData.clear();
						continue;
					}

                    std::transform(NetData.begin(), NetData.end(), NetData.begin(), ::tolower);

                    // Check Status
                    if (isStatusLine)
                    {
                        bool isCodeOk = NetData.find("200") != std::string::npos;
                        bool isStatusOk = NetData.find("ok") != std::string::npos;

                        if (!isCodeOk || !isStatusOk)
                        {
                            net_tcp_close(Socket);
                            dbg_msg("autoupdate","Server Host returns error code");
                            return false;
                        }
                    }
                    isStatusLine = false;

                    // Get File Size
                    std::size_t fpos = std::string::npos;
					if ((fpos=NetData.find("content-length:")) != std::string::npos)
                        sscanf(NetData.substr(fpos+15).c_str(), "%d", &TotalBytes);

					NetData.clear();
					continue;
				}
				else if (aNetBuff[i]!='\r')
					enterCtrl=0;

				NetData+=aNetBuff[i];
			}
			else // Body Part
			{
				if (TotalBytes <= 0)
				{
					io_close(dstFile);
					net_tcp_close(Socket);
					dbg_msg("autoupdate","Error receiving file");
					return false;
				}

                m_CurrentDownloadProgress = (float)TotalRecv/(float)TotalBytes;

				io_write(dstFile, &aNetBuff[i], 1);

				TotalRecv++;
				if (TotalRecv == TotalBytes)
					break;
			}
		}
	}

	//Finish
	io_close(dstFile);
	net_tcp_close(Socket);

	return true;
}
示例#27
0
const char *engine_savepath(const char *filename, char *buffer, int max)
{
	str_format(buffer, max, "%s/%s", application_save_path, filename);
	return buffer;
}
示例#28
0
static opcode_status_ty
spawn(string_list_ty *args, string_ty *input, int *pid_p,
    string_ty *host_binding, opcode_context_ty *ocp)
{
    size_t          j;
    int             fd;
    string_ty       *iname;
    int             pid;
    opcode_status_ty status;
    static char     **argv;
    static size_t   argvlen;
    string_list_ty  cmd;
    sub_context_ty  *scp;
    char            *shell;

    trace(("spawn()\n{\n"));
    assert(args);

    /*
     * build the input file, if required
     */
    status = opcode_status_error;
    fd = -1;
    iname = 0;
    if (input)
    {
        /*
         * He has given a string to be used as input to the command,
         * so write it out to a file, and then redirect the input.
         */
        iname = temporary_filename();
        fd = open(iname->str_text, O_RDWR | O_CREAT | O_TRUNC, 0666);
        if (fd < 0)
            fatal_intl_open(iname->str_text);
        if (unlink(iname->str_text))
        {
            error_intl_unlink(iname->str_text);
            goto done;
        }
        if
        (
            write(fd, input->str_text, input->str_length) < 0
        ||
            lseek(fd, 0L, SEEK_SET)
        )
        {
            error_intl_write(iname->str_text);
            goto done;
        }
    }

    /*
     * See if there is a host_binding in effect.
     */
    if (host_binding)
    {
        static string_ty *key;
        string_list_ty  *slp;
        string_ty       *s;
        string_ty       *rcmd;
        string_ty       *rcmdq;
        string_ty       *result_fn;
        FILE            *result_fp;
        string_ty       *cwd;
        string_ty       *script_fn;
        FILE            *script_fp;

        /*
         * Work out the name of the remote shell command.
         */
        if (!key)
            key = str_from_c("parallel_rsh");
        slp = id_var_search(ocp, key);
        if (slp)
            string_list_copy_constructor(&cmd, slp);
        else
        {
            static string_ty *rsh;

            if (!rsh)
                rsh = str_from_c(CONF_REMOTE_SHELL);
            string_list_constructor(&cmd);
            string_list_append(&cmd, rsh);
        }

        /*
         * Add the name of the host.
         */
        string_list_append(&cmd, host_binding);

        /*
         * The remote end will need to change directory to where
         * we are now, since it is *highly* unlikely that we are
         * in our home directory.
         */
        cwd = os_curdir(); /* do not str_free this */

        /*
         * We are going to create a small shell script contining
         * the command to be executed.  This deals with various
         * weird and obscure $SHELL settings, and it also deals
         * with command lines so long that rsh barfs.
         *
         * Yes, there is a potential race condition here.
         * Between writing the script and executing it, we
         * could be tricked into executing something else.
         * Especially if there is a symlink lying in wait.
         */
        script_fn = dot_temporary_filename();
        script_fp = fopen_and_check(script_fn->str_text, "w");

        /*
         * what shell are we using
         */
        shell = getenv("SHELL");
        if (!shell || !*shell)
            shell = CONF_SHELL;
        fprintf(script_fp, "#!%s\n", shell);

        /*
         * Now write the actual command to the script file.
         */
        rcmd = wl2str(args, 0, args->nstrings, (char *)0);
        fprintf(script_fp, "%s\n", rcmd->str_text);
        str_free(rcmd);

        fflush_and_check(script_fp, script_fn->str_text);
        fclose_and_check(script_fp, script_fn->str_text);
        chmod_and_check(script_fn->str_text, 0755);

        /*
         * This is the result file.  It is where the remote
         * command will stash its exit status.    We seed it with
         * failure in case the rsh fails altogether.
         *
         * And, yes, there is a race conditon and we could be
         * lied to if they are quick.
         */
        result_fn = dot_temporary_filename();
        result_fp = fopen_and_check(result_fn->str_text, "w");
        fprintf(result_fp, "42\n");
        fflush_and_check(result_fp, result_fn->str_text);
        fclose_and_check(result_fp, result_fn->str_text);

        /*
         * Because rsh(1) always returns an exit status of zero,
         * we have to make other arrangements to obtain the exit
         * status.
         *
         * We actually need to be a more devious, so that we can
         * get the exit status back.  Write it to a temporary
         * file server side, then read and remove it client side.
         *
         * This is the server side command.  It gets quoted
         * again to protect it from the client side shell.
         *
         * We use sh explicitly, because the shell at the other
         * end could be csh, tcsh, or something even stranger,
         * and we need to guarantee the command will execute
         * exactly the way we need.
         */
        rcmd =
            str_format
            (
                "sh -c 'cd %s && sh %s %s/%s; echo $? > %s/%s'",
                cwd->str_text,
                (option_test(OPTION_ERROK) ? "-c" : "-ce"),
                cwd->str_text,
                script_fn->str_text,
                cwd->str_text,
                result_fn->str_text
            );
        rcmdq = str_quote_shell(rcmd);
        str_free(rcmd);
        string_list_append(&cmd, rcmdq);
        str_free(rcmdq);

        /*
         * This is the rest of the server side command.
         *
         * On some systems this gives ``Text file busy'' errors,
         * as if the script file has yet to be released by
         * the kernel.    Since we *aren't* executing it when the
         * RM command runs, I have no idea how to avoid this
         * (other than ignoring it with -f).  Maybe this is some
         * kind of NFS latency?
         */
        s =
            str_format
            (
                "&& exit `cat %s;rm -f %s %s`",
                result_fn->str_text,
                result_fn->str_text,
                script_fn->str_text
            );
        string_list_append(&cmd, s);
        str_free(s);
        str_free(result_fn);
        str_free(script_fn);

        /*
         * Because the command has a semicolon and back quotes,
         * we need to hand it to a shell (as alluded to above).
         * Assemble into a single string.
         */
        rcmd = wl2str(&cmd, 0, cmd.nstrings, (char *)0);
        string_list_destructor(&cmd);

        /*
         * Build the final command to be executed.
         * It even cleans up after itself.
         */
        s = str_from_c("sh");
        string_list_append(&cmd, s);
        str_free(s);
        s = str_from_c("-c");
        string_list_append(&cmd, s);
        str_free(s);
        string_list_append(&cmd, rcmd);
        str_free(rcmd);
    }
    else
    {
        /*
         * build the command
         */
        if (os_execute_magic_characters_list(args))
        {
            string_ty       *str;

            /*
             * what shell are we using
             */
            shell = getenv("SHELL");
            if (!shell || !*shell)
                shell = CONF_SHELL;

            string_list_constructor(&cmd);
            str = str_from_c(shell);
            string_list_append(&cmd, str);
            str_free(str);
            if (option_test(OPTION_ERROK))
                str = str_from_c("-c");
            else
                str = str_from_c("-ce");
            string_list_append(&cmd, str);
            str_free(str);
            str = wl2str(args, 0, args->nstrings - 1, (char *)0);
            string_list_append(&cmd, str);
            str_free(str);
        }
        else
            string_list_copy_constructor(&cmd, args);
    }

    /*
     * build the argv array
     */
    if (!argv)
    {
        argvlen = cmd.nstrings + 1;
        argv = mem_alloc(argvlen * sizeof(char *));
    }
    else if (argvlen < cmd.nstrings + 1)
    {
        argvlen = cmd.nstrings + 1;
        argv = mem_change_size(argv, argvlen * sizeof(char *));
    }
    if (cmd.nstrings == 0)
    {
        string_list_destructor(&cmd);
        status = opcode_status_success;
        goto done;
    }
    for (j = 0; j < cmd.nstrings; ++j)
        argv[j] = cmd.string[j]->str_text;
    argv[cmd.nstrings] = 0;

    /*
     * spawn the child process
     */
    switch (pid = fork())
    {
    case -1:
        scp = sub_context_new();
        sub_errno_set(scp);
        error_intl(scp, i18n("fork(): $errno"));
        sub_context_delete(scp);
        break;

    case 0:
        /*
         * child
         */
        if (fd >= 0)
        {
            if (close(0) && errno != EBADF)
            {
                string_ty       *fn0;
                int             err;

                err = errno;
                scp = sub_context_new();
                fn0 = subst_intl(scp, "standard input");
                /* re-use substitution context */
                sub_errno_setx(scp, err);
                sub_var_set_string(scp, "File_Name", fn0);
                fatal_intl
                (
                    scp,
                    i18n("close $filename: $errno")
                );
                /* NOTREACHED */
                sub_context_delete(scp);
                str_free(fn0);
            }
            if (dup(fd) < 0)
            {
                scp = sub_context_new();
                sub_errno_set(scp);
                fatal_intl(scp, i18n("dup(): $errno"));
                /* NOTREACHED */
                sub_context_delete(scp);
            }
            close(fd);
        }
        if (argv[0][0] == '/')
            execv(argv[0], argv);
        else
            execvp(argv[0], argv);
        scp = sub_context_new();
        sub_errno_set(scp);
        sub_var_set_charstar(scp, "File_Name", argv[0]);
        fatal_intl(scp, i18n("exec $filename: $errno"));
        /* NOTREACHED */
        sub_context_delete(scp);

    default:
        /*
         * parent
         */
        if (fd >= 0)
        {
            close(fd);
            fd = -1;
        }
        string_list_destructor(&cmd);
        status = opcode_status_wait;
        trace(("pid = %d;\n", pid));
        *pid_p = pid;
        break;
    }
    done:
    if (fd >= 0)
        close(fd);
    if (iname)
        str_free(iname);
    trace(("return %s;\n", opcode_status_name(status)));
    trace(("}\n"));
    return status;
}
示例#29
0
void IGameController::CycleMap()
{
	if(m_aMapWish[0] != 0)
	{
		char aBuf[256];
		str_format(aBuf, sizeof(aBuf), "rotating map to %s", m_aMapWish);
		GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
		str_copy(g_Config.m_SvMap, m_aMapWish, sizeof(g_Config.m_SvMap));
		m_aMapWish[0] = 0;
		m_RoundCount = 0;
		return;
	}
	if(!str_length(g_Config.m_SvMaprotation))
		return;

	if(m_RoundCount < g_Config.m_SvRoundsPerMap-1)
	{
		if(g_Config.m_SvRoundSwap)
			GameServer()->SwapTeams();
		return;
	}

	// handle maprotation
	const char *pMapRotation = g_Config.m_SvMaprotation;
	const char *pCurrentMap = g_Config.m_SvMap;

	int CurrentMapLen = str_length(pCurrentMap);
	const char *pNextMap = pMapRotation;
	while(*pNextMap)
	{
		int WordLen = 0;
		while(pNextMap[WordLen] && !IsSeparator(pNextMap[WordLen]))
			WordLen++;

		if(WordLen == CurrentMapLen && str_comp_num(pNextMap, pCurrentMap, CurrentMapLen) == 0)
		{
			// map found
			pNextMap += CurrentMapLen;
			while(*pNextMap && IsSeparator(*pNextMap))
				pNextMap++;

			break;
		}

		pNextMap++;
	}

	// restart rotation
	if(pNextMap[0] == 0)
		pNextMap = pMapRotation;

	// cut out the next map
	char aBuf[512] = {0};
	for(int i = 0; i < 511; i++)
	{
		aBuf[i] = pNextMap[i];
		if(IsSeparator(pNextMap[i]) || pNextMap[i] == 0)
		{
			aBuf[i] = 0;
			break;
		}
	}

	// skip spaces
	int i = 0;
	while(IsSeparator(aBuf[i]))
		i++;

	m_RoundCount = 0;

	char aBufMsg[256];
	str_format(aBufMsg, sizeof(aBufMsg), "rotating map to %s", &aBuf[i]);
	GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
	str_copy(g_Config.m_SvMap, &aBuf[i], sizeof(g_Config.m_SvMap));
}
示例#30
0
void CGameClient::OnPredict()
{
    // store the previous values so we can detect prediction errors
    CCharacterCore BeforePrevChar = m_PredictedPrevChar;
    CCharacterCore BeforeChar = m_PredictedChar;

    // we can't predict without our own id or own character
    if(m_Snap.m_LocalClientID == -1 || !m_Snap.m_aCharacters[m_Snap.m_LocalClientID].m_Active)
        return;

    // don't predict anything if we are paused
    if(m_Snap.m_pGameInfoObj && m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)
    {
        if(m_Snap.m_pLocalCharacter)
            m_PredictedChar.Read(m_Snap.m_pLocalCharacter);
        if(m_Snap.m_pLocalPrevCharacter)
            m_PredictedPrevChar.Read(m_Snap.m_pLocalPrevCharacter);
        return;
    }

    // repredict character
    CWorldCore World;
    World.m_Tuning = m_Tuning;

    // search for players
    for(int i = 0; i < MAX_CLIENTS; i++)
    {
        if(!m_Snap.m_aCharacters[i].m_Active || !m_Snap.m_paPlayerInfos[i])
            continue;

        g_GameClient.m_aClients[i].m_Predicted.Init(&World, Collision(), &m_Teams);
        World.m_apCharacters[i] = &g_GameClient.m_aClients[i].m_Predicted;
        World.m_apCharacters[i]->m_Id = m_Snap.m_paPlayerInfos[i]->m_ClientID;
        g_GameClient.m_aClients[i].m_Predicted.Read(&m_Snap.m_aCharacters[i].m_Cur);
    }

    // predict
    for(int Tick = Client()->GameTick()+1; Tick <= Client()->PredGameTick(); Tick++)
    {
        // fetch the local
        if(Tick == Client()->PredGameTick() && World.m_apCharacters[m_Snap.m_LocalClientID])
            m_PredictedPrevChar = *World.m_apCharacters[m_Snap.m_LocalClientID];

        // first calculate where everyone should move
        for(int c = 0; c < MAX_CLIENTS; c++)
        {
            if(!World.m_apCharacters[c])
                continue;

            mem_zero(&World.m_apCharacters[c]->m_Input, sizeof(World.m_apCharacters[c]->m_Input));
            if(m_Snap.m_LocalClientID == c)
            {
                // apply player input
                int *pInput = Client()->GetInput(Tick);
                if(pInput)
                    World.m_apCharacters[c]->m_Input = *((CNetObj_PlayerInput*)pInput);
                World.m_apCharacters[c]->Tick(true);
            }
            else
                World.m_apCharacters[c]->Tick(false);

        }

        // move all players and quantize their data
        for(int c = 0; c < MAX_CLIENTS; c++)
        {
            if(!World.m_apCharacters[c])
                continue;

            World.m_apCharacters[c]->Move();
            World.m_apCharacters[c]->Quantize();
        }

        // check if we want to trigger effects
        if(Tick > m_LastNewPredictedTick)
        {
            m_LastNewPredictedTick = Tick;
            m_NewPredictedTick = true;

            if(m_Snap.m_LocalClientID != -1 && World.m_apCharacters[m_Snap.m_LocalClientID])
            {
                vec2 Pos = World.m_apCharacters[m_Snap.m_LocalClientID]->m_Pos;
                int Events = World.m_apCharacters[m_Snap.m_LocalClientID]->m_TriggeredEvents;
                if(Events&COREEVENT_GROUND_JUMP) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, Pos);

                /*if(events&COREEVENT_AIR_JUMP)
                {
                	GameClient.effects->air_jump(pos);
                	GameClient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, pos);
                }*/

                //if(events&COREEVENT_HOOK_LAUNCH) snd_play_random(CHN_WORLD, SOUND_HOOK_LOOP, 1.0f, pos);
                //if(events&COREEVENT_HOOK_ATTACH_PLAYER) snd_play_random(CHN_WORLD, SOUND_HOOK_ATTACH_PLAYER, 1.0f, pos);
                if(Events&COREEVENT_HOOK_ATTACH_GROUND) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_HOOK_ATTACH_GROUND, 1.0f, Pos);
                if(Events&COREEVENT_HOOK_HIT_NOHOOK) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_HOOK_NOATTACH, 1.0f, Pos);
                //if(events&COREEVENT_HOOK_RETRACT) snd_play_random(CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos);
            }
        }

        if(Tick == Client()->PredGameTick() && World.m_apCharacters[m_Snap.m_LocalClientID])
            m_PredictedChar = *World.m_apCharacters[m_Snap.m_LocalClientID];
    }

    if(g_Config.m_Debug && g_Config.m_ClPredict && m_PredictedTick == Client()->PredGameTick())
    {
        CNetObj_CharacterCore Before = {0}, Now = {0}, BeforePrev = {0}, NowPrev = {0};
        BeforeChar.Write(&Before);
        BeforePrevChar.Write(&BeforePrev);
        m_PredictedChar.Write(&Now);
        m_PredictedPrevChar.Write(&NowPrev);

        if(mem_comp(&Before, &Now, sizeof(CNetObj_CharacterCore)) != 0)
        {
            Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", "prediction error");
            for(unsigned i = 0; i < sizeof(CNetObj_CharacterCore)/sizeof(int); i++)
                if(((int *)&Before)[i] != ((int *)&Now)[i])
                {
                    char aBuf[256];
                    str_format(aBuf, sizeof(aBuf), "	%d %d %d (%d %d)", i, ((int *)&Before)[i], ((int *)&Now)[i], ((int *)&BeforePrev)[i], ((int *)&NowPrev)[i]);
                    Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", aBuf);
                }
        }
    }

    m_PredictedTick = Client()->PredGameTick();
}