Online protocol improvements (#1393)
* Chartkey generation * Simfile filehash generation * Read filehash on NSCRSG. Add FLU packets and friendlist vectors. Add getserverversion method. Send chartkey, filehash and rate on start request. * Use filehash to find the selected song if it is not empty. * Friendlist update broadcast. * Send note row size if it's bigger than 1 * Used for chartkey generation * Define the ReportScore function with numNotes when WITHOUT_NETWORKING is defined
This commit is contained in:
@@ -21,6 +21,7 @@ bool NetworkSyncManager::Connect( const RString& addy, unsigned short port ) { r
|
|||||||
RString NetworkSyncManager::GetServerName() { return RString(); }
|
RString NetworkSyncManager::GetServerName() { return RString(); }
|
||||||
void NetworkSyncManager::ReportNSSOnOff( int i ) { }
|
void NetworkSyncManager::ReportNSSOnOff( int i ) { }
|
||||||
void NetworkSyncManager::ReportScore( int playerID, int step, int score, int combo, float offset ) { }
|
void NetworkSyncManager::ReportScore( int playerID, int step, int score, int combo, float offset ) { }
|
||||||
|
void NetworkSyncManager::ReportScore(int playerID, int step, int score, int combo, float offset, int numNotes) { }
|
||||||
void NetworkSyncManager::ReportSongOver() { }
|
void NetworkSyncManager::ReportSongOver() { }
|
||||||
void NetworkSyncManager::ReportStyle() {}
|
void NetworkSyncManager::ReportStyle() {}
|
||||||
void NetworkSyncManager::StartRequest( short position ) { }
|
void NetworkSyncManager::StartRequest( short position ) { }
|
||||||
@@ -55,6 +56,7 @@ AutoScreenMessage( SM_AddToChat );
|
|||||||
AutoScreenMessage( SM_ChangeSong );
|
AutoScreenMessage( SM_ChangeSong );
|
||||||
AutoScreenMessage( SM_GotEval );
|
AutoScreenMessage( SM_GotEval );
|
||||||
AutoScreenMessage( SM_UsersUpdate );
|
AutoScreenMessage( SM_UsersUpdate );
|
||||||
|
AutoScreenMessage( SM_FriendsUpdate );
|
||||||
AutoScreenMessage( SM_SMOnlinePack );
|
AutoScreenMessage( SM_SMOnlinePack );
|
||||||
|
|
||||||
int NetworkSyncManager::GetSMOnlineSalt()
|
int NetworkSyncManager::GetSMOnlineSalt()
|
||||||
@@ -240,6 +242,53 @@ RString NetworkSyncManager::GetServerName()
|
|||||||
return m_ServerName;
|
return m_ServerName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Same as the one below except for ctr = uint8_t(STATSMAN->m_CurStageStats.m_player[playerID].GetGrade() * 16 + numNotes);
|
||||||
|
//Im keeping the old one because it's used for single tap notes
|
||||||
|
void NetworkSyncManager::ReportScore(int playerID, int step, int score, int combo, float offset, int numNotes)
|
||||||
|
{
|
||||||
|
if (!useSMserver) //Make sure that we are using the network
|
||||||
|
return;
|
||||||
|
|
||||||
|
LOG->Trace("Player ID %i combo = %i", playerID, combo);
|
||||||
|
m_packet.ClearPacket();
|
||||||
|
|
||||||
|
m_packet.Write1(NSCGSU);
|
||||||
|
step = TranslateStepType(step);
|
||||||
|
uint8_t ctr = (uint8_t)(playerID * 16 + step - (SMOST_HITMINE - 1));
|
||||||
|
m_packet.Write1(ctr);
|
||||||
|
|
||||||
|
ctr = uint8_t(STATSMAN->m_CurStageStats.m_player[playerID].GetGrade() * 16 + numNotes);
|
||||||
|
|
||||||
|
if (STATSMAN->m_CurStageStats.m_player[playerID].m_bFailed)
|
||||||
|
ctr = uint8_t(112); //Code for failed (failed constant seems not to work)
|
||||||
|
|
||||||
|
m_packet.Write1(ctr);
|
||||||
|
m_packet.Write4(score);
|
||||||
|
m_packet.Write2((uint16_t)combo);
|
||||||
|
m_packet.Write2((uint16_t)m_playerLife[playerID]);
|
||||||
|
|
||||||
|
// Offset Info
|
||||||
|
// Note: if a 0 is sent, then disregard data.
|
||||||
|
|
||||||
|
// ASSUMED: No step will be more than 16 seconds off center.
|
||||||
|
// If this assumption is false, read 16 seconds in either direction.
|
||||||
|
int iOffset = int((offset + 16.384)*2000.0f);
|
||||||
|
|
||||||
|
if (iOffset>65535)
|
||||||
|
iOffset = 65535;
|
||||||
|
if (iOffset<1)
|
||||||
|
iOffset = 1;
|
||||||
|
|
||||||
|
// Report 0 if hold, or miss (don't forget mines should report)
|
||||||
|
if (step == SMOST_HITMINE || step > SMOST_W1)
|
||||||
|
iOffset = 0;
|
||||||
|
|
||||||
|
m_packet.Write2((uint16_t)iOffset);
|
||||||
|
|
||||||
|
NetPlayerClient->SendPack((char*)m_packet.Data, m_packet.Position);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void NetworkSyncManager::ReportScore(int playerID, int step, int score, int combo, float offset)
|
void NetworkSyncManager::ReportScore(int playerID, int step, int score, int combo, float offset)
|
||||||
{
|
{
|
||||||
if( !useSMserver ) //Make sure that we are using the network
|
if( !useSMserver ) //Make sure that we are using the network
|
||||||
@@ -390,6 +439,31 @@ void NetworkSyncManager::StartRequest( short position )
|
|||||||
for (int i=0; i<2-players; ++i)
|
for (int i=0; i<2-players; ++i)
|
||||||
m_packet.WriteNT(""); //Write a NULL if no player
|
m_packet.WriteNT(""); //Write a NULL if no player
|
||||||
|
|
||||||
|
//Send song hash/chartkey
|
||||||
|
if (m_ServerVersion >= 129) {
|
||||||
|
tSteps = GAMESTATE->m_pCurSteps[PLAYER_1];
|
||||||
|
if (tSteps != NULL && GAMESTATE->IsPlayerEnabled(PLAYER_1)) {
|
||||||
|
m_packet.WriteNT(tSteps->GetChartKey());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_packet.WriteNT("");
|
||||||
|
}
|
||||||
|
|
||||||
|
tSteps = GAMESTATE->m_pCurSteps[PLAYER_2];
|
||||||
|
if (tSteps != NULL && GAMESTATE->IsPlayerEnabled(PLAYER_2)) {
|
||||||
|
m_packet.WriteNT(tSteps->GetChartKey());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_packet.WriteNT("");
|
||||||
|
}
|
||||||
|
|
||||||
|
int rate = (int)(GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate * 100);
|
||||||
|
m_packet.Write1(rate);
|
||||||
|
m_packet.WriteNT(GAMESTATE->m_pCurSong->GetFileHash());
|
||||||
|
}
|
||||||
|
|
||||||
//This needs to be reset before ScreenEvaluation could possibly be called
|
//This needs to be reset before ScreenEvaluation could possibly be called
|
||||||
m_EvalPlayerData.clear();
|
m_EvalPlayerData.clear();
|
||||||
|
|
||||||
@@ -607,6 +681,12 @@ void NetworkSyncManager::ProcessInput()
|
|||||||
m_sMainTitle = m_packet.ReadNT();
|
m_sMainTitle = m_packet.ReadNT();
|
||||||
m_sArtist = m_packet.ReadNT();
|
m_sArtist = m_packet.ReadNT();
|
||||||
m_sSubTitle = m_packet.ReadNT();
|
m_sSubTitle = m_packet.ReadNT();
|
||||||
|
//Read songhash
|
||||||
|
if (m_ServerVersion >= 129) {
|
||||||
|
m_sFileHash = m_packet.ReadNT();
|
||||||
|
} else {
|
||||||
|
m_sFileHash = "" ;
|
||||||
|
}
|
||||||
SCREENMAN->SendMessageToTopScreen( SM_ChangeSong );
|
SCREENMAN->SendMessageToTopScreen( SM_ChangeSong );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -668,6 +748,20 @@ void NetworkSyncManager::ProcessInput()
|
|||||||
m_packet.ClearPacket();
|
m_packet.ClearPacket();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case FLU:
|
||||||
|
{
|
||||||
|
int PlayersInThisPacket = m_packet.Read1();
|
||||||
|
fl_PlayerNames.clear();
|
||||||
|
fl_PlayerStates.clear();
|
||||||
|
for (int i = 0; i<PlayersInThisPacket; ++i)
|
||||||
|
{
|
||||||
|
int PStatus = m_packet.Read1();
|
||||||
|
fl_PlayerStates.push_back(PStatus);
|
||||||
|
fl_PlayerNames.push_back(m_packet.ReadNT());
|
||||||
|
}
|
||||||
|
SCREENMAN->SendMessageToTopScreen(SM_FriendsUpdate);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
m_packet.ClearPacket();
|
m_packet.ClearPacket();
|
||||||
}
|
}
|
||||||
@@ -698,6 +792,10 @@ void NetworkSyncManager::ReportPlayerOptions()
|
|||||||
NetPlayerClient->SendPack((char*)&m_packet.Data, m_packet.Position);
|
NetPlayerClient->SendPack((char*)&m_packet.Data, m_packet.Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int NetworkSyncManager::GetServerVersion()
|
||||||
|
{
|
||||||
|
return m_ServerVersion;
|
||||||
|
}
|
||||||
void NetworkSyncManager::SelectUserSong()
|
void NetworkSyncManager::SelectUserSong()
|
||||||
{
|
{
|
||||||
m_packet.ClearPacket();
|
m_packet.ClearPacket();
|
||||||
@@ -706,6 +804,10 @@ void NetworkSyncManager::SelectUserSong()
|
|||||||
m_packet.WriteNT( m_sMainTitle );
|
m_packet.WriteNT( m_sMainTitle );
|
||||||
m_packet.WriteNT( m_sArtist );
|
m_packet.WriteNT( m_sArtist );
|
||||||
m_packet.WriteNT( m_sSubTitle );
|
m_packet.WriteNT( m_sSubTitle );
|
||||||
|
//Send songhash
|
||||||
|
if (m_ServerVersion >= 129) {
|
||||||
|
m_packet.WriteNT(GAMESTATE->m_pCurSong->GetFileHash());
|
||||||
|
}
|
||||||
NetPlayerClient->SendPack( (char*)&m_packet.Data, m_packet.Position );
|
NetPlayerClient->SendPack( (char*)&m_packet.Data, m_packet.Position );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
class LoadingWindow;
|
class LoadingWindow;
|
||||||
|
|
||||||
const int NETPROTOCOLVERSION=3;
|
const int NETPROTOCOLVERSION=4;
|
||||||
const int NETMAXBUFFERSIZE=1020; //1024 - 4 bytes for EzSockets
|
const int NETMAXBUFFERSIZE=1020; //1024 - 4 bytes for EzSockets
|
||||||
const int NETNUMTAPSCORES=8;
|
const int NETNUMTAPSCORES=8;
|
||||||
|
|
||||||
@@ -29,6 +29,8 @@ enum NSCommand
|
|||||||
NSCSMOnline, // 12 [SMLC_SMO]
|
NSCSMOnline, // 12 [SMLC_SMO]
|
||||||
NSCFormatted, // 13 [SMLC_RESERVED1]
|
NSCFormatted, // 13 [SMLC_RESERVED1]
|
||||||
NSCAttack, // 14 [SMLC_RESERVED2]
|
NSCAttack, // 14 [SMLC_RESERVED2]
|
||||||
|
XML, // 15 [SMLC_RESERVED3]
|
||||||
|
FLU, // 15 [SMLC_FriendListUpdate]
|
||||||
NUM_NS_COMMANDS
|
NUM_NS_COMMANDS
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,6 +116,7 @@ public:
|
|||||||
|
|
||||||
// If "useSMserver" then send score to server
|
// If "useSMserver" then send score to server
|
||||||
void ReportScore( int playerID, int step, int score, int combo, float offset );
|
void ReportScore( int playerID, int step, int score, int combo, float offset );
|
||||||
|
void ReportScore(int playerID, int step, int score, int combo, float offset, int numNotes);
|
||||||
void ReportSongOver();
|
void ReportSongOver();
|
||||||
void ReportStyle(); // Report style, players, and names
|
void ReportStyle(); // Report style, players, and names
|
||||||
void ReportNSSOnOff( int i ); // Report song selection screen on/off
|
void ReportNSSOnOff( int i ); // Report song selection screen on/off
|
||||||
@@ -145,6 +148,10 @@ public:
|
|||||||
vector<int> m_ActivePlayer;
|
vector<int> m_ActivePlayer;
|
||||||
vector<RString> m_PlayerNames;
|
vector<RString> m_PlayerNames;
|
||||||
|
|
||||||
|
//friendlist
|
||||||
|
std::vector<RString> fl_PlayerNames;
|
||||||
|
std::vector<int> fl_PlayerStates;
|
||||||
|
|
||||||
// Used for ScreenNetEvaluation
|
// Used for ScreenNetEvaluation
|
||||||
vector<EndOfGame_PlayerData> m_EvalPlayerData;
|
vector<EndOfGame_PlayerData> m_EvalPlayerData;
|
||||||
|
|
||||||
@@ -163,9 +170,12 @@ public:
|
|||||||
RString m_sMainTitle;
|
RString m_sMainTitle;
|
||||||
RString m_sArtist;
|
RString m_sArtist;
|
||||||
RString m_sSubTitle;
|
RString m_sSubTitle;
|
||||||
|
RString m_sFileHash;
|
||||||
int m_iSelectMode;
|
int m_iSelectMode;
|
||||||
void SelectUserSong();
|
void SelectUserSong();
|
||||||
|
|
||||||
|
int GetServerVersion();
|
||||||
|
|
||||||
RString m_sChatText;
|
RString m_sChatText;
|
||||||
|
|
||||||
// FIXME: This should NOT be public. PERIOD. It probably shouldn't be a member at all.
|
// FIXME: This should NOT be public. PERIOD. It probably shouldn't be a member at all.
|
||||||
|
|||||||
@@ -269,6 +269,12 @@ int NoteData::GetNumTracksWithTapOrHoldHead( int row ) const
|
|||||||
return iNum;
|
return iNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NoteData::LogNonEmptyRows() {
|
||||||
|
NonEmptyRowVector.clear();
|
||||||
|
FOREACH_NONEMPTY_ROW_ALL_TRACKS(*this, row)
|
||||||
|
NonEmptyRowVector.push_back(row);
|
||||||
|
}
|
||||||
|
|
||||||
int NoteData::GetFirstTrackWithTap( int row ) const
|
int NoteData::GetFirstTrackWithTap( int row ) const
|
||||||
{
|
{
|
||||||
for( int t=0; t<GetNumTracks(); t++ )
|
for( int t=0; t<GetNumTracks(); t++ )
|
||||||
|
|||||||
@@ -157,9 +157,16 @@ private:
|
|||||||
void RemoveATIFromList(all_tracks_iterator* iter) const;
|
void RemoveATIFromList(all_tracks_iterator* iter) const;
|
||||||
void RemoveATIFromList(all_tracks_const_iterator* iter) const;
|
void RemoveATIFromList(all_tracks_const_iterator* iter) const;
|
||||||
|
|
||||||
|
// Mina stuf (Used for chartkey hashing)
|
||||||
|
std::vector<int> NonEmptyRowVector;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
|
// Mina stuf (Used for chartkey hashing)
|
||||||
|
void LogNonEmptyRows();
|
||||||
|
std::vector<int>& GetNonEmptyRowVector() { return NonEmptyRowVector; };
|
||||||
|
|
||||||
int GetNumTracks() const { return m_TapNotes.size(); }
|
int GetNumTracks() const { return m_TapNotes.size(); }
|
||||||
void SetNumTracks( int iNewNumTracks );
|
void SetNumTracks( int iNewNumTracks );
|
||||||
bool IsComposite() const;
|
bool IsComposite() const;
|
||||||
|
|||||||
@@ -605,7 +605,7 @@ void ScoreKeeperNormal::HandleTapRowScore( const NoteData &nd, int iRow )
|
|||||||
float offset = NoteDataWithScoring::LastTapNoteWithResult( nd, iRow ).result.fTapNoteOffset;
|
float offset = NoteDataWithScoring::LastTapNoteWithResult( nd, iRow ).result.fTapNoteOffset;
|
||||||
NSMAN->ReportScore( pn, scoreOfLastTap,
|
NSMAN->ReportScore( pn, scoreOfLastTap,
|
||||||
m_pPlayerStageStats->m_iScore,
|
m_pPlayerStageStats->m_iScore,
|
||||||
m_pPlayerStageStats->m_iCurCombo, offset );
|
m_pPlayerStageStats->m_iCurCombo, offset, m_iNumNotesHitThisRow);
|
||||||
Message msg( "ScoreChanged" );
|
Message msg( "ScoreChanged" );
|
||||||
msg.SetParam( "PlayerNumber", m_pPlayerState->m_PlayerNumber );
|
msg.SetParam( "PlayerNumber", m_pPlayerState->m_PlayerNumber );
|
||||||
msg.SetParam( "MultiPlayer", m_pPlayerState->m_mp );
|
msg.SetParam( "MultiPlayer", m_pPlayerState->m_mp );
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
AutoScreenMessage( SM_AddToChat );
|
AutoScreenMessage( SM_AddToChat );
|
||||||
AutoScreenMessage( SM_UsersUpdate );
|
AutoScreenMessage( SM_UsersUpdate );
|
||||||
|
AutoScreenMessage( SM_FriendsUpdate );
|
||||||
AutoScreenMessage( SM_SMOnlinePack );
|
AutoScreenMessage( SM_SMOnlinePack );
|
||||||
|
|
||||||
REGISTER_SCREEN_CLASS( ScreenNetSelectBase );
|
REGISTER_SCREEN_CLASS( ScreenNetSelectBase );
|
||||||
@@ -135,6 +136,10 @@ void ScreenNetSelectBase::HandleScreenMessage( const ScreenMessage SM )
|
|||||||
{
|
{
|
||||||
UpdateUsers();
|
UpdateUsers();
|
||||||
}
|
}
|
||||||
|
else if (SM == SM_FriendsUpdate)
|
||||||
|
{
|
||||||
|
MESSAGEMAN->Broadcast("FriendsUpdate");
|
||||||
|
}
|
||||||
|
|
||||||
ScreenWithMenuElements::HandleScreenMessage( SM );
|
ScreenWithMenuElements::HandleScreenMessage( SM );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,14 +181,37 @@ void ScreenNetSelectMusic::HandleScreenMessage( const ScreenMessage SM )
|
|||||||
|
|
||||||
vector <Song *> AllSongs = SONGMAN->GetAllSongs();
|
vector <Song *> AllSongs = SONGMAN->GetAllSongs();
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for( i=0; i < AllSongs.size(); i++ )
|
bool found = false;
|
||||||
|
if (NSMAN->GetServerVersion() >= 129)
|
||||||
|
{
|
||||||
|
//Dont earch by filehash if none was sent
|
||||||
|
if(!NSMAN->m_sFileHash.empty())
|
||||||
|
for (i = 0; i < AllSongs.size(); i++)
|
||||||
{
|
{
|
||||||
m_cSong = AllSongs[i];
|
m_cSong = AllSongs[i];
|
||||||
if( ( !m_cSong->GetTranslitArtist().CompareNoCase( NSMAN->m_sArtist ) ) &&
|
if (NSMAN->m_sArtist == m_cSong->GetTranslitArtist() &&
|
||||||
( !m_cSong->GetTranslitMainTitle().CompareNoCase( NSMAN->m_sMainTitle ) ) &&
|
NSMAN->m_sMainTitle == m_cSong->GetTranslitMainTitle() &&
|
||||||
( !m_cSong->GetTranslitSubTitle().CompareNoCase( NSMAN->m_sSubTitle ) ) )
|
NSMAN->m_sSubTitle == m_cSong->GetTranslitSubTitle() &&
|
||||||
|
NSMAN->m_sFileHash == m_cSong->GetFileHash())
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//If we couldnt find it using file hash search for it without using it, if using SMSERVER < 129 it will go here
|
||||||
|
if(!found)
|
||||||
|
for (i = 0; i < AllSongs.size(); i++)
|
||||||
|
{
|
||||||
|
m_cSong = AllSongs[i];
|
||||||
|
if (NSMAN->m_sArtist == m_cSong->GetTranslitArtist() &&
|
||||||
|
NSMAN->m_sMainTitle == m_cSong->GetTranslitMainTitle() &&
|
||||||
|
NSMAN->m_sSubTitle == m_cSong->GetTranslitSubTitle())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool haveSong = i != AllSongs.size();
|
bool haveSong = i != AllSongs.size();
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,8 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
|
//-Nick12 Used for song file hashing
|
||||||
|
#include <CryptManager.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The internal version of the cache for StepMania.
|
* @brief The internal version of the cache for StepMania.
|
||||||
@@ -1592,6 +1594,32 @@ vector<RString> Song::GetFGChanges1ToVectorString() const
|
|||||||
return this->GetChangesToVectorString(this->GetForegroundChanges());
|
return this->GetChangesToVectorString(this->GetForegroundChanges());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RString Song::GetFileHash()
|
||||||
|
{
|
||||||
|
if (m_sFileHash.empty()) {
|
||||||
|
RString sPath = SetExtension(GetSongFilePath(), "sm");
|
||||||
|
if (!IsAFile(sPath))
|
||||||
|
sPath = SetExtension(GetSongFilePath(), "dwi");
|
||||||
|
if (!IsAFile(sPath))
|
||||||
|
sPath = SetExtension(GetSongFilePath(), "sma");
|
||||||
|
if (!IsAFile(sPath))
|
||||||
|
sPath = SetExtension(GetSongFilePath(), "bms");
|
||||||
|
if (!IsAFile(sPath))
|
||||||
|
sPath = SetExtension(GetSongFilePath(), "ksf");
|
||||||
|
if (!IsAFile(sPath))
|
||||||
|
sPath = SetExtension(GetSongFilePath(), "json");
|
||||||
|
if (!IsAFile(sPath))
|
||||||
|
sPath = SetExtension(GetSongFilePath(), "jso");
|
||||||
|
if (!IsAFile(sPath))
|
||||||
|
sPath = SetExtension(GetSongFilePath(), "ssc");
|
||||||
|
if (IsAFile(sPath))
|
||||||
|
m_sFileHash = BinaryToHex(CRYPTMAN->GetSHA1ForFile(sPath));
|
||||||
|
else
|
||||||
|
m_sFileHash = "";
|
||||||
|
}
|
||||||
|
return m_sFileHash;
|
||||||
|
}
|
||||||
|
|
||||||
vector<RString> Song::GetInstrumentTracksToVectorString() const
|
vector<RString> Song::GetInstrumentTracksToVectorString() const
|
||||||
{
|
{
|
||||||
vector<RString> ret;
|
vector<RString> ret;
|
||||||
|
|||||||
@@ -188,6 +188,9 @@ public:
|
|||||||
/** @brief The transliterated artist of the Song, if it exists. */
|
/** @brief The transliterated artist of the Song, if it exists. */
|
||||||
RString m_sArtistTranslit;
|
RString m_sArtistTranslit;
|
||||||
|
|
||||||
|
RString m_sFileHash;
|
||||||
|
RString GetFileHash();
|
||||||
|
|
||||||
/* If PREFSMAN->m_bShowNative is off, these are the same as GetTranslit*
|
/* If PREFSMAN->m_bShowNative is off, these are the same as GetTranslit*
|
||||||
* below. Otherwise, they return the main titles. */
|
* below. Otherwise, they return the main titles. */
|
||||||
RString GetDisplayMainTitle() const;
|
RString GetDisplayMainTitle() const;
|
||||||
|
|||||||
@@ -33,6 +33,9 @@
|
|||||||
/* register DisplayBPM with StringConversion */
|
/* register DisplayBPM with StringConversion */
|
||||||
#include "EnumHelper.h"
|
#include "EnumHelper.h"
|
||||||
|
|
||||||
|
// For hashing hart keys - Mina
|
||||||
|
#include "CryptManager.h"
|
||||||
|
|
||||||
static const char *DisplayBPMNames[] =
|
static const char *DisplayBPMNames[] =
|
||||||
{
|
{
|
||||||
"Actual",
|
"Actual",
|
||||||
@@ -614,6 +617,77 @@ void Steps::SetCachedRadarValues( const RadarValues v[NUM_PLAYERS] )
|
|||||||
m_bAreCachedRadarValuesJustLoaded = true;
|
m_bAreCachedRadarValuesJustLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RString Steps::GenerateChartKey()
|
||||||
|
{
|
||||||
|
ChartKey = this->GenerateChartKey(*m_pNoteData, this->GetTimingData());
|
||||||
|
return ChartKey;
|
||||||
|
}
|
||||||
|
RString Steps::GetChartKey()
|
||||||
|
{
|
||||||
|
if (ChartKey.empty()) {
|
||||||
|
this->Decompress();
|
||||||
|
ChartKey = this->GenerateChartKey(*m_pNoteData, this->GetTimingData());
|
||||||
|
this->Compress();
|
||||||
|
}
|
||||||
|
return ChartKey;
|
||||||
|
}
|
||||||
|
RString Steps::GenerateChartKey(NoteData &nd, TimingData *td)
|
||||||
|
{
|
||||||
|
RString k = "";
|
||||||
|
RString o = "";
|
||||||
|
float bpm;
|
||||||
|
nd.LogNonEmptyRows();
|
||||||
|
std::vector<int>& nerv = nd.GetNonEmptyRowVector();
|
||||||
|
|
||||||
|
|
||||||
|
RString firstHalf = "";
|
||||||
|
RString secondHalf = "";
|
||||||
|
|
||||||
|
#pragma omp parallel sections
|
||||||
|
{
|
||||||
|
#pragma omp section
|
||||||
|
{
|
||||||
|
for (size_t r = 0; r < nerv.size() / 2; r++) {
|
||||||
|
int row = nerv[r];
|
||||||
|
for (int t = 0; t < nd.GetNumTracks(); ++t) {
|
||||||
|
const TapNote &tn = nd.GetTapNote(t, row);
|
||||||
|
std::ostringstream os;
|
||||||
|
os << tn.type;
|
||||||
|
firstHalf.append(os.str());
|
||||||
|
}
|
||||||
|
bpm = td->GetBPMAtRow(row);
|
||||||
|
std::ostringstream os;
|
||||||
|
os << static_cast<int>(bpm + 0.374643f);
|
||||||
|
firstHalf.append(os.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma omp section
|
||||||
|
{
|
||||||
|
for (size_t r = nerv.size() / 2; r < nerv.size(); r++) {
|
||||||
|
int row = nerv[r];
|
||||||
|
for (int t = 0; t < nd.GetNumTracks(); ++t) {
|
||||||
|
const TapNote &tn = nd.GetTapNote(t, row);
|
||||||
|
std::ostringstream os;
|
||||||
|
os << tn.type;
|
||||||
|
secondHalf.append(os.str());
|
||||||
|
}
|
||||||
|
bpm = td->GetBPMAtRow(row);
|
||||||
|
std::ostringstream os;
|
||||||
|
os << static_cast<int>(bpm + 0.374643f);
|
||||||
|
firstHalf.append(os.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
k = firstHalf + secondHalf;
|
||||||
|
|
||||||
|
//ChartKeyRecord = k;
|
||||||
|
o.append("X"); // I was thinking of using "C" to indicate chart.. however.. X is cooler... - Mina
|
||||||
|
o.append(BinaryToHex(CryptManager::GetSHA1ForString(k)));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// lua start
|
// lua start
|
||||||
#include "LuaBinding.h"
|
#include "LuaBinding.h"
|
||||||
/** @brief Allow Lua to have access to the Steps. */
|
/** @brief Allow Lua to have access to the Steps. */
|
||||||
|
|||||||
@@ -124,6 +124,14 @@ public:
|
|||||||
void SetChartStyle( RString sChartStyle );
|
void SetChartStyle( RString sChartStyle );
|
||||||
static bool MakeValidEditDescription( RString &sPreferredDescription ); // return true if was modified
|
static bool MakeValidEditDescription( RString &sPreferredDescription ); // return true if was modified
|
||||||
|
|
||||||
|
/* This is a reimplementation of the lua version of the script to generate chart keys, except this time
|
||||||
|
using the notedata stored in game memory immediately after reading it than parsing it using lua. - Mina */
|
||||||
|
RString GenerateChartKey(NoteData &nd, TimingData *td);
|
||||||
|
RString GenerateChartKey();
|
||||||
|
RString ChartKey;
|
||||||
|
RString GetChartKey();
|
||||||
|
void SetChartKey(const RString &k) { ChartKey = k; }
|
||||||
|
|
||||||
void SetLoadedFromProfile( ProfileSlot slot ) { m_LoadedFromProfile = slot; }
|
void SetLoadedFromProfile( ProfileSlot slot ) { m_LoadedFromProfile = slot; }
|
||||||
void SetMeter( int meter );
|
void SetMeter( int meter );
|
||||||
void SetCachedRadarValues( const RadarValues v[NUM_PLAYERS] );
|
void SetCachedRadarValues( const RadarValues v[NUM_PLAYERS] );
|
||||||
|
|||||||
Reference in New Issue
Block a user