This commit is contained in:
GreYFoXGTi 2010-08-24 03:38:33 +02:00
commit 0325c59aa9
13 changed files with 584 additions and 68 deletions

View file

@ -574,6 +574,17 @@ int CCollision::IsCp(int x, int y)
return 0;
}
int CCollision::IsCheckpoint(int Index)
{
if(Index < 0)
return -1;
int z = m_pTiles[Index].m_Index;
if(z >= 35 && z <= 59)
return z-35;
return -1;
}
vec2 CCollision::CpSpeed(int Index)
{

View file

@ -55,6 +55,9 @@ public:
int IsThrough(int x, int y);
int IsNoLaser(int x, int y);
int IsFNoLaser(int x, int y);
int IsCheckpoint(int Index);
int IsCp(int x, int y);
vec2 CpSpeed(int index);

View file

@ -1,10 +1,14 @@
#include <new>
#include <stdio.h>
#include <string.h>
#include <engine/shared/config.h>
#include <engine/server/server.h>
#include <game/server/gamecontext.h>
#include <game/mapitems.h>
#include <game/server/gamemodes/DDRace.h>
#include <game/server/score.h>
#include "character.h"
#include "laser.h"
#include "light.h"
@ -596,50 +600,142 @@ void CCharacter::Tick()
//DDRace
char aBuftime[128];
float time = (float)(Server()->Tick() - m_StartTime) / ((float)Server()->TickSpeed());
int z = GameServer()->Collision()->IsTeleport(m_Pos.x, m_Pos.y);
CPlayerData *pData = GameServer()->Score()->PlayerData(m_pPlayer->GetCID());
if(Server()->Tick() - m_RefreshTime >= Server()->TickSpeed())
{
//GameServer()->SendBroadcast("FIRST_IF", m_pPlayer->GetCID());
if (m_RaceState == RACE_STARTED) {
//GameServer()->SendBroadcast("SECOND_IF", m_pPlayer->GetCID());
int int_time = (int)time;
str_format(aBuftime, sizeof(aBuftime), "%d m %d s\n%s", int_time/60,(int_time%60), ( g_Config.m_SvBroadcast[0] == 0) ? "" : g_Config.m_SvBroadcast);
GameServer()->SendBroadcast(aBuftime, m_pPlayer->GetCID());
int IntTime = (int)time;
if(m_pPlayer->m_IsUsingRaceClient)
{
CNetMsg_Sv_RaceTime Msg;
Msg.m_Time = IntTime;
Msg.m_Check = 0;
if(m_CpActive != -1 && m_CpTick > Server()->Tick())
{
if(pData->m_BestTime && pData->m_aBestCpTime[m_CpActive] != 0)
{
float Diff = (m_CpCurrent[m_CpActive] - pData->m_aBestCpTime[m_CpActive])*100;
Msg.m_Check = (int)Diff;
}
}
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, m_pPlayer->GetCID());
} else {
str_format(aBuftime, sizeof(aBuftime), "Current Time: %d min %d sec", IntTime/60, IntTime%60);
if(m_CpActive != -1 && m_CpTick > Server()->Tick())
{
if(pData->m_BestTime && pData->m_aBestCpTime[m_CpActive] != 0)
{
char aTmp[128];
float Diff = m_CpCurrent[m_CpActive] - pData->m_aBestCpTime[m_CpActive];
str_format(aTmp, sizeof(aTmp), "\nCheckpoint | Diff : %+5.2f", Diff);
strcat(aBuftime, aTmp);
}
}
if( g_Config.m_SvBroadcast[0] != 0) {
char aTmp[128];
str_format(aTmp, sizeof(aTmp), "\n%s\n", g_Config.m_SvBroadcast);
strcat(aBuftime, aTmp);
}
GameServer()->SendBroadcast(aBuftime, m_pPlayer->GetCID());
}
} else {
if (g_Config.m_SvBroadcast[0] != 0)
if( g_Config.m_SvBroadcast[0] != 0) {
char aTmp[128];
str_format(aTmp, sizeof(aTmp), "%s\n", g_Config.m_SvBroadcast);
strcat(aBuftime, aTmp);
GameServer()->SendBroadcast(g_Config.m_SvBroadcast, m_pPlayer->GetCID());
}
}
m_RefreshTime = Server()->Tick();
}
int cp = GameServer()->Collision()->IsCheckpoint(MapIndex);
if(cp != -1 && m_RaceState == RACE_STARTED)
{
m_CpActive = cp;
m_CpCurrent[cp] = time;
m_CpTick = Server()->Tick() + Server()->TickSpeed()*2;
}
if(((TileIndex1 == TILE_BEGIN) || (TileIndex2 == TILE_BEGIN)) && (m_RaceState == RACE_NONE || m_RaceState == RACE_STARTED))
{
m_StartTime = Server()->Tick();
m_RefreshTime = Server()->Tick();
m_RaceState = RACE_STARTED;
}
int z = GameServer()->Collision()->IsTeleport(m_Pos.x, m_Pos.y);
if(((TileIndex1 == TILE_END) || (TileIndex2 == TILE_END)) && m_RaceState == RACE_STARTED)
{
char aBuf[128];
if ((int)time / 60 != 0)
str_format(aBuf, sizeof(aBuf), "%s finished in: %d minute(s) %5.3f second(s)", (!g_Config.m_SvHideScore)?Server()->ClientName(m_pPlayer->GetCID()):"You", (int)time/60, time - ((int)time/60*60));
else
str_format(aBuf, sizeof(aBuf), "%s finished in: %5.3f second(s)", (!g_Config.m_SvHideScore) ? Server()->ClientName(m_pPlayer->GetCID()):"You", time - ((int)time/60*60));
if (!g_Config.m_SvHideScore)
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
else
str_format(aBuf, sizeof(aBuf), "%s finished in: %d minute(s) %5.2f second(s)", Server()->ClientName(m_pPlayer->GetCID()), (int)time/60, time-((int)time/60*60));
if(!g_Config.m_SvHideScore)
GameServer()->SendChatTarget(m_pPlayer->GetCID(), aBuf);
CPlayerScore *pPScore = ((CGameControllerDDRace*) GameServer()->m_pController)->m_Score.SearchName(Server()->ClientName(m_pPlayer->GetCID()));
if(pPScore && time - pPScore->m_Score < 0)
else
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
if(time - pData->m_BestTime < 0)
{
str_format(aBuf, sizeof(aBuf), "New record: %5.3f second(s) better", time - pPScore->m_Score);
if (!g_Config.m_SvHideScore)
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
else
// new record \o/
str_format(aBuf, sizeof(aBuf), "New record: %5.2f second(s) better", time - pData->m_BestTime);
if(!g_Config.m_SvHideScore)
GameServer()->SendChatTarget(m_pPlayer->GetCID(), aBuf);
else
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
}
if(!pData->m_BestTime || time < pData->m_BestTime)
{
// update the score
pData->Set(time, m_CpCurrent);
if(str_comp_num(Server()->ClientName(m_pPlayer->GetCID()), "nameless tee", 12) != 0)
GameServer()->Score()->SaveScore(m_pPlayer->GetCID(), time, this);
}
// update server best time
if(!GameServer()->m_pController->m_CurrentRecord || time < GameServer()->m_pController->m_CurrentRecord)
{
// check for nameless
if(str_comp_num(Server()->ClientName(m_pPlayer->GetCID()), "nameless tee", 12) != 0)
GameServer()->m_pController->m_CurrentRecord = time;
}
m_RaceState = RACE_NONE;
if(strncmp(Server()->ClientName(m_pPlayer->GetCID()), "nameless tee", 12) != 0)
((CGameControllerDDRace*)GameServer()->m_pController)->m_Score.ParsePlayer(Server()->ClientName(m_pPlayer->GetCID()), (float)time);
// set player score
if(!GameServer()->Score()->PlayerData(m_pPlayer->GetCID())->m_CurrentTime || GameServer()->Score()->PlayerData(m_pPlayer->GetCID())->m_CurrentTime > time)
{
GameServer()->Score()->PlayerData(m_pPlayer->GetCID())->m_CurrentTime = time;
// send it to all players
for(int i = 0; i < MAX_CLIENTS; i++)
{
if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->m_IsUsingRaceClient)
{
if(g_Config.m_SvHideScore || i == m_pPlayer->GetCID())
{
CNetMsg_Sv_PlayerTime Msg;
char aBuf[16];
str_format(aBuf, sizeof(aBuf), "%.0f", time*100.0f); // damn ugly but the only way i know to do it
int TimeToSend;
sscanf(aBuf, "%d", &TimeToSend);
Msg.m_Time = TimeToSend;
Msg.m_Cid = m_pPlayer->GetCID();
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, i);
}
}
}
}
int TTime = 0-(int)time;
if(m_pPlayer->m_Score < TTime)
m_pPlayer->m_Score = TTime;
}
if(((TileIndex1 == TILE_FREEZE) || (TileIndex2 == TILE_FREEZE)) && !m_Super)
{

View file

@ -168,7 +168,7 @@ public:
// checkpoints
int m_CpTick;
int m_CpActive;
float m_CpCurrent[149];
float m_CpCurrent[25];

View file

@ -1,4 +1,5 @@
#include <new>
#include <stdio.h>
#include <string.h>
#include <base/math.h>
#include <engine/shared/config.h>
@ -11,6 +12,9 @@
#include <game/gamecore.h>
#include "gamemodes/DDRace.h"
#include "score.h"
#include "score/file_score.h"
enum
{
RESET,
@ -32,7 +36,7 @@ void CGameContext::Construct(int Resetting)
if(Resetting==NO_RESET)
m_pVoteOptionHeap = new CHeap();
//m_Cheats = g_Config.m_SvCheats;
m_pScore = 0;
}
CGameContext::CGameContext(int Resetting)
@ -705,7 +709,7 @@ void CGameContext::OnMessage(int MsgId, CUnpacker *pUnpacker, int ClientId)
str_format(buf, sizeof(buf), "/Info /Credits %s",g_Config.m_SvPauseable?"/pause":"");
SendChatTarget(ClientId, buf);
SendChatTarget(ClientId, "/rank /top5 /top5 5 or any number");
}
}/*
else if(!strncmp(pMsg->m_pMessage, "/top5", 5) && !g_Config.m_SvHideScore)
{
const char *pt = pMsg->m_pMessage;
@ -751,7 +755,7 @@ void CGameContext::OnMessage(int MsgId, CUnpacker *pUnpacker, int ClientId)
str_format(buf, sizeof(buf), "%s is not ranked", Server()->ClientName(ClientId));
SendChatTarget(ClientId, buf);
}
} finish this later */
else if (!str_comp_nocase(pMsg->m_pMessage, "/emotepain")&&g_Config.m_SvEmotionalTees)
{
CCharacter* pChr = p->GetCharacter();
@ -853,6 +857,25 @@ void CGameContext::OnMessage(int MsgId, CUnpacker *pUnpacker, int ClientId)
}
}
else if(MsgId == NETMSGTYPE_CL_ISRACE)
{
p->m_IsUsingRaceClient = true;
// send time of all players
for(int i = 0; i < MAX_CLIENTS; i++)
{
if(m_apPlayers[i] && Score()->PlayerData(i)->m_CurrentTime > 0)
{
char aBuf[16];
str_format(aBuf, sizeof(aBuf), "%.0f", Score()->PlayerData(i)->m_CurrentTime*100.0f); // damn ugly but the only way i know to do it
int TimeToSend;
sscanf(aBuf, "%d", &TimeToSend);
CNetMsg_Sv_PlayerTime Msg;
Msg.m_Time = TimeToSend;
Msg.m_Cid = i;
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientId);
}
}
}
else if(MsgId == NETMSGTYPE_CL_CALLVOTE)
{
@ -1134,6 +1157,7 @@ void CGameContext::OnMessage(int MsgId, CUnpacker *pUnpacker, int ClientId)
pChr->m_EmoteStop = Server()->Tick() + 2 * Server()->TickSpeed();
}
}
else if (MsgId == NETMSGTYPE_CL_KILL && !m_World.m_Paused)
{
if(p->m_Last_Kill && p->m_Last_Kill+Server()->TickSpeed()*3 > Server()->Tick())
@ -1800,6 +1824,16 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/)
Server()->SetBrowseInfo(m_pController->m_pGameType, -1);
// delete old score object
if(m_pScore)
delete m_pScore;
// create score object (add sql later)
//if(g_Config.m_SvUseSQL)
// m_pScore = new CSqlScore(this);
//else
m_pScore = new CFileScore(this);
// setup core world
//for(int i = 0; i < MAX_CLIENTS; i++)
// game.players[i].core.world = &game.world.core;

View file

@ -11,6 +11,7 @@
#include "gamecontroller.h"
#include "gameworld.h"
#include "player.h"
#include "score.h"
/*
Tick
@ -41,6 +42,7 @@ class CGameContext : public IGameServer
CCollision m_Collision;
CNetObjHandler m_NetObjHandler;
CTuningParams m_Tuning;
class IScore *m_pScore;
static void ConMute(IConsole::IResult *pResult, void *pUserData, int cid);
static void ConSetlvl(IConsole::IResult *pResult, void *pUserData, int cid);
@ -99,6 +101,8 @@ public:
class IConsole *Console() { return m_pConsole; }
CCollision *Collision() { return &m_Collision; }
CTuningParams *Tuning() { return &m_Tuning; }
class IScore *Score() { return m_pScore; }
CGameContext();
~CGameContext();

View file

@ -46,6 +46,7 @@ protected:
char m_aMapWish[128];
int m_RoundStartTick;
int m_GameOverTick;
@ -63,6 +64,8 @@ protected:
public:
const char *m_pGameType;
float m_CurrentRecord;
//bool IsTeamplay() const;
IGameController(class CGameContext *pGameServer);

View file

@ -15,7 +15,6 @@ public:
vec2 *m_pTeleporter;
void InitTeleporter();
CScore m_Score;
virtual void Tick();
};

View file

@ -20,7 +20,6 @@ CPlayer::CPlayer(CGameContext *pGameServer, int CID, int Team)
m_DieTick = Server()->Tick();
m_ScoreStartTick = Server()->Tick();
Character = 0;
m_CharacterCopy = 0;
m_Muted = 0;
this->m_ClientID = CID;
m_Team = GameServer()->m_pController->ClampTeam(Team);
@ -32,6 +31,11 @@ CPlayer::CPlayer(CGameContext *pGameServer, int CID, int Team)
m_SentAfkWarning2 = 0;
m_PauseInfo.m_Respawn = false;
m_IsUsingRaceClient = false;
m_LastSentTime = 0;
GameServer()->Score()->PlayerData(CID)->Reset();
}
CPlayer::~CPlayer()
@ -42,17 +46,6 @@ CPlayer::~CPlayer()
void CPlayer::Tick()
{
int pos=0;
CPlayerScore *pscore = ((CGameControllerDDRace*)GameServer()->m_pController)->m_Score.SearchName(Server()->ClientName(m_ClientID), pos);
if(pscore && pos > -1 && pscore->m_Score != -1)
{
float time = pscore->m_Score;
//if (!config.sv_hide_score)
m_Score = time * 100;
//else
// score=authed;
} else
m_Score = 0.0f;
Server()->SetClientAuthed(m_ClientID, m_Authed);
Server()->SetClientScore(m_ClientID, m_Score);
@ -95,6 +88,23 @@ void CPlayer::Tick()
}
else if(m_Spawning && m_RespawnTick <= Server()->Tick())
TryRespawn();
// send best time
if(m_IsUsingRaceClient)
{
if(m_LastSentTime > GameServer()->m_pController->m_CurrentRecord || (!m_LastSentTime && GameServer()->m_pController->m_CurrentRecord))
{
char aBuf[16];
str_format(aBuf, sizeof(aBuf), "%.0f", GameServer()->m_pController->m_CurrentRecord*100.0f); // damn ugly but the only way i know to do it
int TimeToSend;
sscanf(aBuf, "%d", &TimeToSend);
CNetMsg_Sv_Record Msg;
Msg.m_Time = TimeToSend;
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, m_ClientID);
m_LastSentTime = GameServer()->m_pController->m_CurrentRecord;
}
}
}
void CPlayer::Snap(int SnappingClient)
@ -112,11 +122,18 @@ void CPlayer::Snap(int SnappingClient)
Info->m_LatencyFlux = m_Latency.m_Max-m_Latency.m_Min;
Info->m_Local = 0;
Info->m_ClientId = m_ClientID;
Info->m_Score = m_Score;
Info->m_Team = m_Team;
if(m_ClientID == SnappingClient)
Info->m_Local = 1;
// send 0 if times of otheres are not shown
if(SnappingClient != m_ClientID)
Info->m_Score = 0;
else
Info->m_Score = m_Score;
Info->m_Team = m_Team;
}
void CPlayer::OnDisconnect()

View file

@ -32,7 +32,6 @@ public:
void KillCharacter(int Weapon = WEAPON_GAME);
CCharacter *GetCharacter();
CCharacter* m_CharacterCopy;
struct PauseInfo {
CCharacterCore m_Core;
int m_StartTime;
@ -111,6 +110,14 @@ public:
int m_ScoreStartTick;
bool m_ForceBalanced;
float m_BestTime;
float m_aBestCpTime[25];
bool m_ResetPickups;
bool m_IsUsingRaceClient;
float m_LastSentTime;
// afk timer
void AfkTimer(int new_target_x, int new_target_y);
int64 m_LastPlaytime;

View file

@ -1,38 +1,53 @@
/* copyright (c) 2008 rajh and gregwar. Score stuff */
#ifndef GAME_SERVER_INTERFACE_SCORE_H
#define GAME_SERVER_INTERFACE_SCORE_H
#ifndef SCORE_H_RACE
#define SCORE_H_RACE
#include <engine/server.h>
#include <engine/shared/protocol.h>
#include <string>
#include <list>
#include "entities/character.h"
#include "gamecontext.h"
#define NUM_TELEPORT 25
class CPlayerScore
class CPlayerData
{
public:
char name[MAX_NAME_LENGTH];
float m_Score;
CPlayerScore(const char *name, float score);
bool operator==(const CPlayerScore& other) { return (this->m_Score == other.m_Score); }
bool operator<(const CPlayerScore& other) { return (this->m_Score < other.m_Score); }
CPlayerData()
{
Reset();
}
void Reset()
{
m_BestTime = 0;
m_CurrentTime = 0;
for(int i = 0; i < NUM_TELEPORT; i++)
m_aBestCpTime[i] = 0;
}
void Set(float Time, float CpTime[NUM_TELEPORT])
{
m_BestTime = Time;
for(int i = 0; i < NUM_TELEPORT; i++)
m_aBestCpTime[i] = CpTime[i];
}
float m_BestTime;
float m_CurrentTime;
float m_aBestCpTime[NUM_TELEPORT];
};
class CScore
class IScore
{
class CGameContext *m_pGameServer;
std::string SaveFile();
CPlayerData m_aPlayerData[MAX_CLIENTS];
public:
CScore(class CGameContext *pGameServer);
CScore();
void Save();
void Load();
CPlayerScore *SearchName(const char *name, int &pos);
CPlayerScore *SearchName(const char *name);
void ParsePlayer(const char *name, float score);
std::list<std::string> Top5Draw(int id, int debut);
virtual ~IScore() {}
CPlayerData *PlayerData(int ID) { return &m_aPlayerData[ID]; }
virtual void LoadScore(int ClientID) = 0;
virtual void SaveScore(int ClientID, float Time, CCharacter *pChar) = 0;
virtual void ShowTop5(int ClientID, int Debut=1) = 0;
virtual void ShowRank(int ClientID, const char* pName, bool Search=false) = 0;
};
#endif

View file

@ -0,0 +1,273 @@
/* copyright (c) 2008 rajh and gregwar. Score stuff */
#include <engine/shared/config.h>
#include <sstream>
#include <fstream>
#include <string.h>
#include "../gamemodes/DDRace.h"
#include "file_score.h"
static LOCK gs_ScoreLock = 0;
CFileScore::CPlayerScore::CPlayerScore(const char *pName, float Score, const char *pIP, float aCpTime[NUM_TELEPORT])
{
str_copy(m_aName, pName, sizeof(m_aName));
m_Score = Score;
str_copy(m_aIP, pIP, sizeof(m_aIP));
for(int i = 0; i < NUM_TELEPORT; i++)
m_aCpTime[i] = aCpTime[i];
}
CFileScore::CFileScore(CGameContext *pGameServer) : m_pGameServer(pGameServer), m_pServer(pGameServer->Server())
{
if(gs_ScoreLock == 0)
gs_ScoreLock = lock_create();
Init();
}
CFileScore::~CFileScore()
{
lock_wait(gs_ScoreLock);
// clear list
m_Top.clear();
lock_release(gs_ScoreLock);
}
std::string SaveFile()
{
std::ostringstream oss;
//if(g_Config.m_SvScoreFolder[0])
// oss << g_Config.m_SvScoreFolder << "/" << g_Config.m_SvMap << "_record.dtb";
//else
oss << g_Config.m_SvMap << "_record.dtb";
return oss.str();
}
void CFileScore::SaveScoreThread(void *pUser)
{
CFileScore *pSelf = (CFileScore *)pUser;
lock_wait(gs_ScoreLock);
std::fstream f;
f.open(SaveFile().c_str(), std::ios::out);
if(!f.fail())
{
int t = 0;
for(sorted_array<CPlayerScore>::range r = pSelf->m_Top.all(); !r.empty(); r.pop_front())
{
f << r.front().m_aName << std::endl << r.front().m_Score << std::endl << r.front().m_aIP << std::endl;
//if(g_Config.m_SvCheckpointSave)
//{
for(int c = 0; c < NUM_TELEPORT; c++)
f << r.front().m_aCpTime[c] << " ";
f << std::endl;
//}
t++;
if(t%50 == 0)
thread_sleep(1);
}
}
f.close();
lock_release(gs_ScoreLock);
}
void CFileScore::Save()
{
void *pSaveThread = thread_create(SaveScoreThread, this);
#if defined(CONF_FAMILY_UNIX)
pthread_detach((pthread_t)pSaveThread);
#endif
}
void CFileScore::Init()
{
lock_wait(gs_ScoreLock);
// create folder if not exist
//if(g_Config.m_SvScoreFolder[0])
// fs_makedir(g_Config.m_SvScoreFolder);
std::fstream f;
f.open(SaveFile().c_str(), std::ios::in);
while(!f.eof() && !f.fail())
{
std::string TmpName, TmpScore, TmpIP, TmpCpLine;
std::getline(f, TmpName);
if(!f.eof() && TmpName != "")
{
std::getline(f, TmpScore);
std::getline(f, TmpIP);
float aTmpCpTime[NUM_TELEPORT] = {0};
//if(g_Config.m_SvCheckpointSave)
//{
std::getline(f, TmpCpLine);
char *pTime = strtok((char*)TmpCpLine.c_str(), " ");
int i = 0;
while(pTime != NULL && i < NUM_TELEPORT)
{
aTmpCpTime[i] = atof(pTime);
pTime = strtok(NULL, " ");
i++;
}
//}
m_Top.add(*new CPlayerScore(TmpName.c_str(), atof(TmpScore.c_str()), TmpIP.c_str(), aTmpCpTime));
}
}
f.close();
lock_release(gs_ScoreLock);
// save the current best score
if(m_Top.size())
((CGameControllerDDRace*)GameServer()->m_pController)->m_CurrentRecord = m_Top[0].m_Score;
}
CFileScore::CPlayerScore *CFileScore::SearchScore(int ID, bool ScoreIP, int *pPosition)
{
char aIP[16];
Server()->GetClientIP(ID, aIP, sizeof(aIP));
int Pos = 1;
for(sorted_array<CPlayerScore>::range r = m_Top.all(); !r.empty(); r.pop_front())
{
if(!strcmp(r.front().m_aIP, aIP) /*&& g_Config.m_SvScoreIP*/ && ScoreIP)
{
if(pPosition)
*pPosition = Pos;
return &r.front();
}
Pos++;
}
return SearchName(Server()->ClientName(ID), pPosition, 0);
}
CFileScore::CPlayerScore *CFileScore::SearchName(const char *pName, int *pPosition, bool NoCase)
{
CPlayerScore *pPlayer = 0;
int Pos = 1;
int Found = 0;
for(sorted_array<CPlayerScore>::range r = m_Top.all(); !r.empty(); r.pop_front())
{
if(str_find_nocase(r.front().m_aName, pName))
{
if(pPosition)
*pPosition = Pos;
if(NoCase)
{
Found++;
pPlayer = &r.front();
}
if(!strcmp(r.front().m_aName, pName))
return &r.front();
}
Pos++;
}
if(Found > 1)
{
if(pPosition)
*pPosition = -1;
return 0;
}
return pPlayer;
}
void CFileScore::UpdatePlayer(int ID, float Score, float aCpTime[NUM_TELEPORT])
{
const char *pName = Server()->ClientName(ID);
char aIP[16];
Server()->GetClientIP(ID, aIP, sizeof(aIP));
lock_wait(gs_ScoreLock);
CPlayerScore *pPlayer = SearchScore(ID, 1, 0);
if(pPlayer)
{
for(int c = 0; c < NUM_TELEPORT; c++)
pPlayer->m_aCpTime[c] = aCpTime[c];
pPlayer->m_Score = Score;
str_copy(pPlayer->m_aName, pName, sizeof(pPlayer->m_aName));
sort(m_Top.all());
}
else
m_Top.add(*new CPlayerScore(pName, Score, aIP, aCpTime));
lock_release(gs_ScoreLock);
Save();
}
void CFileScore::LoadScore(int ClientID)
{
char aIP[16];
Server()->GetClientIP(ClientID, aIP, sizeof(aIP));
CPlayerScore *pPlayer = SearchScore(ClientID, 0, 0);
if(pPlayer && strcmp(pPlayer->m_aIP, aIP) != 0)
{
lock_wait(gs_ScoreLock);
str_copy(pPlayer->m_aIP, aIP, sizeof(pPlayer->m_aIP));
lock_release(gs_ScoreLock);
Save();
}
// set score
if(pPlayer)
PlayerData(ClientID)->Set(pPlayer->m_Score, pPlayer->m_aCpTime);
}
void CFileScore::SaveScore(int ClientID, float Time, CCharacter *pChar)
{
UpdatePlayer(ClientID, Time, pChar->m_CpCurrent);
}
void CFileScore::ShowTop5(int ClientID, int Debut)
{
char aBuf[512];
GameServer()->SendChatTarget(ClientID, "----------- Top 5 -----------");
for(int i = 0; i < 5; i++)
{
if(i+Debut > m_Top.size())
break;
CPlayerScore *r = &m_Top[i+Debut-1];
str_format(aBuf, sizeof(aBuf), "%d. %s Time: %d minute(s) %5.2f second(s)",
i+Debut, r->m_aName, (int) r->m_Score/60, r->m_Score-((int)r->m_Score/60*60));
GameServer()->SendChatTarget(ClientID, aBuf);
}
GameServer()->SendChatTarget(ClientID, "------------------------------");
}
void CFileScore::ShowRank(int ClientID, const char* pName, bool Search)
{
CPlayerScore *pScore;
int Pos;
char aBuf[512];
if(!Search)
pScore = SearchScore(ClientID, 1, &Pos);
else
pScore = SearchName(pName, &Pos, 1);
if(pScore && Pos > -1)
{
float Time = pScore->m_Score;
char aClientName[128];
str_format(aClientName, sizeof(aClientName), " (%s)", Server()->ClientName(ClientID));
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)", Pos, pScore->m_aName, (int)Time/60, Time-((int)Time/60*60));
if(Search)
strcat(aBuf, aClientName);
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
return;
}
else if(Pos == -1)
str_format(aBuf, sizeof(aBuf), "Several players were found.");
else
str_format(aBuf, sizeof(aBuf), "%s is not ranked", Search?pName:Server()->ClientName(ClientID));
GameServer()->SendChatTarget(ClientID, aBuf);
}

View file

@ -0,0 +1,54 @@
/* copyright (c) 2008 rajh and gregwar. Score stuff */
#ifndef GAME_SERVER_FILESCORE_H
#define GAME_SERVER_FILESCORE_H
#include <base/tl/sorted_array.h>
#include "../score.h"
class CFileScore : public IScore
{
CGameContext *m_pGameServer;
IServer *m_pServer;
class CPlayerScore
{
public:
char m_aName[MAX_NAME_LENGTH];
float m_Score;
char m_aIP[16];
float m_aCpTime[NUM_TELEPORT];
CPlayerScore() {};
CPlayerScore(const char *pName, float Score, const char *pIP, float aCpTime[NUM_TELEPORT]);
bool operator<(const CPlayerScore& other) { return (this->m_Score < other.m_Score); }
};
sorted_array<CPlayerScore> m_Top;
CGameContext *GameServer() { return m_pGameServer; }
IServer *Server() { return m_pServer; }
CPlayerScore *SearchScore(int ID, bool ScoreIP, int *pPosition);
CPlayerScore *SearchName(const char *pName, int *pPosition, bool MatchCase);
void UpdatePlayer(int ID, float Score, float aCpTime[NUM_TELEPORT]);
void Init();
void Save();
static void SaveScoreThread(void *pUser);
public:
CFileScore(CGameContext *pGameServer);
~CFileScore();
virtual void LoadScore(int ClientID);
virtual void SaveScore(int ClientID, float Time, CCharacter *pChar);
virtual void ShowTop5(int ClientID, int Debut=1);
virtual void ShowRank(int ClientID, const char* pName, bool Search=false);
};
#endif