mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 18:18:18 +00:00
Add checkpoints. Client undestand that it is a DDRace server fully. Need to rework /top5 /rank. Clean rubbish. I want to sleep(
This commit is contained in:
parent
cf63f18954
commit
6fabca9e10
|
@ -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)
|
||||
{
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
@ -591,50 +595,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)
|
||||
{
|
||||
|
|
|
@ -167,7 +167,7 @@ public:
|
|||
// checkpoints
|
||||
int m_CpTick;
|
||||
int m_CpActive;
|
||||
float m_CpCurrent[149];
|
||||
float m_CpCurrent[25];
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
@ -1738,6 +1762,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;
|
||||
|
|
|
@ -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);
|
||||
|
@ -97,6 +99,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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -15,7 +15,6 @@ public:
|
|||
vec2 *m_pTeleporter;
|
||||
|
||||
void InitTeleporter();
|
||||
CScore m_Score;
|
||||
|
||||
virtual void Tick();
|
||||
};
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -32,7 +32,6 @@ public:
|
|||
void KillCharacter(int Weapon = WEAPON_GAME);
|
||||
CCharacter *GetCharacter();
|
||||
|
||||
CCharacter* m_CharacterCopy;
|
||||
struct PauseInfo {
|
||||
CCharacterCore m_Core;
|
||||
int m_StartTime;
|
||||
|
@ -112,6 +111,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;
|
||||
|
|
|
@ -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
|
||||
|
|
273
src/game/server/score/file_score.cpp
Normal file
273
src/game/server/score/file_score.cpp
Normal 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);
|
||||
}
|
54
src/game/server/score/file_score.h
Normal file
54
src/game/server/score/file_score.h
Normal 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
|
Loading…
Reference in a new issue