1212using System . Globalization ;
1313using System . Threading ;
1414using System . Collections ;
15+ using System . Text ;
1516
1617namespace N__Assistant
1718{
@@ -93,6 +94,7 @@ public Form1()
9394 if ( ! Directory . Exists ( savePath + @"\Maps" ) ) Directory . CreateDirectory ( savePath + @"\Maps" ) ;
9495 if ( ! Directory . Exists ( savePath + @"\Palettes" ) ) Directory . CreateDirectory ( savePath + @"\Palettes" ) ;
9596 if ( ! Directory . Exists ( savePath + @"\MapPacks" ) ) Directory . CreateDirectory ( savePath + @"\MapPacks" ) ;
97+ if ( ! Directory . Exists ( savePath + @"\NPPDLL" ) ) Directory . CreateDirectory ( savePath + @"\NPPDLL" ) ;
9698
9799 MyLoadingThread = new Thread ( new ThreadStart ( DownloadStuff ) ) ;
98100 MyLoadingThread . IsBackground = true ;
@@ -101,6 +103,9 @@ public Form1()
101103 // create palettes directory in steam game dir if it doesnt exist (it's needed to install the custom palettes)
102104 if ( ! Directory . Exists ( steamGamePath + @"\NPP\Palettes" ) ) Directory . CreateDirectory ( steamGamePath + @"\NPP\Palettes" ) ;
103105
106+ // copy npp.dll into \NPPDLL if it doesn't exist
107+ if ( ! File . Exists ( savePath + @"\NPPDLL\npp.dll" ) ) File . Copy ( steamGamePath + @"\npp.dll" , savePath + @"\NPPDLL\npp.dll" ) ;
108+
104109 MyReadingTextThread = new Thread ( new ThreadStart ( ReadNPPTextLogs ) ) ;
105110 MyReadingTextThread . IsBackground = true ;
106111 MyReadingTextThread . Start ( ) ;
@@ -119,8 +124,6 @@ public Form1()
119124
120125 tabControl1 . Selecting += new TabControlCancelEventHandler ( tabControl1_Selecting ) ;
121126
122- loadProfile . Enabled = false ;
123- deleteProfile . Enabled = false ;
124127 }
125128 catch ( Exception exc ) {
126129 MessageBox . Show ( "Coulnd't initialize because: " + exc . Message ) ;
@@ -199,6 +202,7 @@ private void DownloadStuff()
199202 //communityMapPacksList.Items.Clear();
200203 PopulateListBoxWithSpreadsheetData ( communityMapPacksList , 2 , COMMUNITY_MAPPACKS , new APIKey ( ) . key , "Map Packs" ) ;
201204 installCommunityMapPack . Enabled = false ;
205+ patchLeaderboardsForMapPack . Enabled = false ;
202206 statusLabel . Text = "Getting community map packs spreadsheet data ..." ;
203207 }
204208 }
@@ -1025,7 +1029,7 @@ private void backupSoundpack_Click(object sender, EventArgs e)
10251029 PopulateListBoxWithFileType ( soundpackBackups , savePath + @"\Sounds" , "*.zip" ) ;
10261030 installSoundpackButton . Enabled = false ;
10271031 deleteSoundpackBackupButton . Enabled = false ;
1028- statusLabel . Text = "Done Backup Current Sound Pack !" ;
1032+ statusLabel . Text = "Done backup of current sound pack !" ;
10291033 }
10301034
10311035 private void soundpackBackups_SelectedIndexChanged ( object sender , EventArgs e )
@@ -1176,7 +1180,7 @@ private void backupSelectedMaps_Click(object sender, EventArgs e)
11761180 // disable the button to avoid duplicate backups
11771181 backupSelectedMaps . Enabled = false ;
11781182
1179- statusLabel . Text = "Done Backup of Selected Maps !" ;
1183+ statusLabel . Text = "Done backup of selected maps !" ;
11801184 }
11811185 catch ( Exception exc )
11821186 {
@@ -1493,7 +1497,66 @@ private void backupCurrentMapPack_Click(object sender, EventArgs e)
14931497
14941498 private void communityMapPacksList_SelectedIndexChanged ( object sender , EventArgs e )
14951499 {
1496- installCommunityMapPack . Enabled = true ;
1500+ // check if map has a download url, allow installing if it does
1501+ try
1502+ {
1503+ string myStringWebResource = null ;
1504+ WebClient myWebClient = new WebClient ( ) ;
1505+
1506+ // get the url
1507+ foreach ( var mapSheet in sheetMapList )
1508+ {
1509+ if ( mapSheet . sheetId . Equals ( COMMUNITY_MAPPACKS ) == true )
1510+ {
1511+ Cell [ , ] data = mapSheet . sheetData . Data ;
1512+ myStringWebResource = data [ 3 , communityMapPacksList . SelectedIndex + 1 ] . Value ;
1513+ }
1514+ }
1515+
1516+ if ( myStringWebResource != null && ! myStringWebResource . Equals ( "" ) )
1517+ {
1518+ installCommunityMapPack . Enabled = true ;
1519+ }
1520+ else
1521+ {
1522+ installCommunityMapPack . Enabled = false ;
1523+ }
1524+
1525+ }
1526+ catch ( Exception exc )
1527+ {
1528+ MessageBox . Show ( "Error: " + exc . Message ) ;
1529+ }
1530+
1531+
1532+ // check if map has a custom leaderboard url, allow patching if it does
1533+ try
1534+ {
1535+ string myStringWebResource = null ;
1536+ WebClient myWebClient = new WebClient ( ) ;
1537+
1538+ // get the url
1539+ foreach ( var mapSheet in sheetMapList )
1540+ {
1541+ if ( mapSheet . sheetId . Equals ( COMMUNITY_MAPPACKS ) == true )
1542+ {
1543+ Cell [ , ] data = mapSheet . sheetData . Data ;
1544+ myStringWebResource = data [ 5 , communityMapPacksList . SelectedIndex + 1 ] . Value ;
1545+ }
1546+ }
1547+
1548+ if ( myStringWebResource != null && ! myStringWebResource . Equals ( "" ) )
1549+ {
1550+ patchLeaderboardsForMapPack . Enabled = true ;
1551+ } else {
1552+ patchLeaderboardsForMapPack . Enabled = false ;
1553+ }
1554+
1555+ }
1556+ catch ( Exception exc )
1557+ {
1558+ MessageBox . Show ( "Error: " + exc . Message ) ;
1559+ }
14971560 }
14981561
14991562 private void backupActiveProfile_Click ( object sender , EventArgs e )
@@ -1722,7 +1785,7 @@ private void installCommunityMapPack_Click(object sender, EventArgs e)
17221785 return ;
17231786 }
17241787
1725- DialogResult dialogResult = MessageBox . Show ( "Are you sure you wish to replace your current game levels map pack with this one? This process is irreversible if you haven't done a recent backup." , "Replace Existing Sounds ?" , MessageBoxButtons . YesNo ) ;
1788+ DialogResult dialogResult = MessageBox . Show ( "Are you sure you wish to replace your current game levels map pack with this one? This process is irreversible if you haven't done a recent backup." , "Install Map Pack ?" , MessageBoxButtons . YesNo ) ;
17261789 if ( dialogResult == DialogResult . Yes )
17271790 {
17281791 try
@@ -1762,7 +1825,7 @@ private void installCommunityMapPack_Click(object sender, EventArgs e)
17621825 }
17631826 }
17641827
1765- private void resetProfile_Click ( object sender , EventArgs e )
1828+ private void ResetProfile ( )
17661829 {
17671830 if ( DetectNPPRunning ( ) == true )
17681831 {
@@ -1785,6 +1848,11 @@ private void resetProfile_Click(object sender, EventArgs e)
17851848 }
17861849 }
17871850
1851+ private void resetProfile_Click ( object sender , EventArgs e )
1852+ {
1853+ ResetProfile ( ) ;
1854+ }
1855+
17881856 private void searchMapName_KeyPress ( object sender , KeyPressEventArgs e )
17891857 {
17901858 if ( e . KeyChar == 13 )
@@ -1825,6 +1893,206 @@ private void searchTextInMetanetMaps_Click(object sender, EventArgs e)
18251893 {
18261894 SearchRecursive ( metanetMapsList , metanetMapsList . Nodes , searchMapName . Text ) ;
18271895 }
1896+
1897+ private void backupPalettes_Click ( object sender , EventArgs e )
1898+ {
1899+ try
1900+ {
1901+ string [ ] dirs = Directory . GetDirectories ( steamGamePath + @"\NPP\Palettes" ) ;
1902+ foreach ( string dir in dirs )
1903+ {
1904+ string [ ] splits = dir . Split ( '\\ ' ) ;
1905+ string palName = splits [ splits . Length - 1 ] ;
1906+ ZipFile . CreateFromDirectory ( dir , savePath + @"\Palettes\" + palName + DateTime . Now . ToString ( "yyMMddHHmm" ) + ".zip" ) ;
1907+ }
1908+ localBackupPalettesList . Items . Clear ( ) ;
1909+ PopulateListBoxWithFileType ( localBackupPalettesList , savePath + @"\Palettes" , "*.zip" ) ;
1910+ installBackupPalette . Enabled = false ;
1911+ deleteBackupPalette . Enabled = false ;
1912+ statusLabel . Text = "Done with Backup of Installed Palettes!" ;
1913+ }
1914+ catch ( Exception exc )
1915+ {
1916+ MessageBox . Show ( "Failed to zip palettes: {0}" , exc . ToString ( ) ) ;
1917+ }
1918+ }
1919+
1920+ private void linkSoundpackSpreadsheet_LinkClicked ( object sender , LinkLabelLinkClickedEventArgs e )
1921+ {
1922+ System . Diagnostics . Process . Start ( "https://docs.google.com/spreadsheets/d/18PshamVuDNyH396a7U3YDFQmCw18s4gIVZ_WrFODRd4/edit#gid=0" ) ;
1923+ }
1924+
1925+ private void linkPalettesSpreadsheet_LinkClicked ( object sender , LinkLabelLinkClickedEventArgs e )
1926+ {
1927+ System . Diagnostics . Process . Start ( "https://docs.google.com/spreadsheets/d/1I2f87Qhfs6rxzZq5dQRDbLKYyaGLqTdCkLqfNfrw1Mk/edit#gid=0" ) ;
1928+ }
1929+
1930+ private void linkMappacksSpreadsheet_LinkClicked ( object sender , LinkLabelLinkClickedEventArgs e )
1931+ {
1932+ System . Diagnostics . Process . Start ( "https://docs.google.com/spreadsheets/d/18PshamVuDNyH396a7U3YDFQmCw18s4gIVZ_WrFODRd4/edit#gid=1470738075" ) ;
1933+ }
1934+
1935+ void ReplaceTextInFile ( string fileName , string oldText , string newText , bool padwithNull )
1936+ {
1937+ byte [ ] fileBytes = File . ReadAllBytes ( fileName ) ,
1938+ oldBytes = Encoding . UTF8 . GetBytes ( oldText ) ;
1939+
1940+ byte [ ] newBytes = new byte [ oldBytes . Length ] ;
1941+ byte [ ] newStringBytes = Encoding . UTF8 . GetBytes ( newText ) ;
1942+ for ( int i = 0 ; i < newStringBytes . Length ; i ++ )
1943+ {
1944+ newBytes [ i ] = newStringBytes [ i ] ;
1945+ }
1946+
1947+ int index = IndexOfBytes ( fileBytes , oldBytes ) ;
1948+
1949+ if ( index < 0 )
1950+ {
1951+ // Text was not found
1952+ return ;
1953+ }
1954+
1955+ /*if (padwithNull && (oldBytes.Length > newBytes.Length))
1956+ {
1957+ for (int i = newBytes.Length; i < oldBytes.Length; i++)
1958+ {
1959+ newBytes[i] = 0;
1960+ }
1961+ }*/
1962+
1963+ byte [ ] newFileBytes =
1964+ new byte [ fileBytes . Length + newBytes . Length - oldBytes . Length ] ;
1965+
1966+ Buffer . BlockCopy ( fileBytes , 0 , newFileBytes , 0 , index ) ;
1967+ Buffer . BlockCopy ( newBytes , 0 , newFileBytes , index , newBytes . Length ) ;
1968+ Buffer . BlockCopy ( fileBytes , index + oldBytes . Length ,
1969+ newFileBytes , index + newBytes . Length ,
1970+ fileBytes . Length - index - oldBytes . Length ) ;
1971+
1972+ File . WriteAllBytes ( fileName , newFileBytes ) ;
1973+ }
1974+
1975+ int IndexOfBytes ( byte [ ] searchBuffer , byte [ ] bytesToFind )
1976+ {
1977+ for ( int i = 0 ; i < searchBuffer . Length - bytesToFind . Length ; i ++ )
1978+ {
1979+ bool success = true ;
1980+
1981+ for ( int j = 0 ; j < bytesToFind . Length ; j ++ )
1982+ {
1983+ if ( searchBuffer [ i + j ] != bytesToFind [ j ] )
1984+ {
1985+ success = false ;
1986+ break ;
1987+ }
1988+ }
1989+
1990+ if ( success )
1991+ {
1992+ return i ;
1993+ }
1994+ }
1995+
1996+ return - 1 ;
1997+ }
1998+
1999+ private void patchLeaderboardsForMapPack_Click ( object sender , EventArgs e )
2000+ {
2001+
2002+ if ( DetectNPPRunning ( ) == true )
2003+ {
2004+ MessageBox . Show ( "Please close N++ before installing map pack" ) ;
2005+ return ;
2006+ }
2007+
2008+ DialogResult dialogResult = MessageBox . Show ( "Are you sure you wish to patch your N++ for this leaderboard?" , "Patch N++?" , MessageBoxButtons . YesNo ) ;
2009+ if ( dialogResult == DialogResult . Yes )
2010+ {
2011+ try
2012+ {
2013+ string myStringWebResource = null ;
2014+ WebClient myWebClient = new WebClient ( ) ;
2015+
2016+ // get the url
2017+ foreach ( var mapSheet in sheetMapList )
2018+ {
2019+ if ( mapSheet . sheetId . Equals ( COMMUNITY_MAPPACKS ) == true )
2020+ {
2021+ Cell [ , ] data = mapSheet . sheetData . Data ;
2022+ myStringWebResource = data [ 5 , communityMapPacksList . SelectedIndex + 1 ] . Value ;
2023+ }
2024+ }
2025+
2026+ // check myStringWebResource is not null and has a string with correct length
2027+ if ( myStringWebResource != null && myStringWebResource . Length > 0 )
2028+ {
2029+ // copy npp.dll into \NPPDLL if it doesn't exist
2030+ if ( ! File . Exists ( savePath + @"\NPPDLL\npp.dll" ) ) File . Copy ( steamGamePath + @"\npp.dll" , savePath + @"\NPPDLL\npp.dll" ) ;
2031+
2032+ File . Copy ( savePath + @"\NPPDLL\npp.dll" , savePath + @"\NPPDLL\npp_topatch.dll" ) ;
2033+
2034+ // replace "https://dojo.nplusplus.ninja" with myStringWebResource
2035+ ReplaceTextInFile ( savePath + @"\NPPDLL\npp_topatch.dll" , "https://dojo.nplusplus.ninja" , myStringWebResource , true ) ;
2036+
2037+ File . Delete ( steamGamePath + @"\npp.dll" ) ;
2038+
2039+ File . Copy ( savePath + @"\NPPDLL\npp_topatch.dll" , steamGamePath + @"\npp.dll" ) ;
2040+
2041+ File . Delete ( savePath + @"\NPPDLL\npp_topatch.dll" ) ;
2042+
2043+ patchLeaderboardsForMapPack . Enabled = false ;
2044+ statusLabel . Text = "Done patching leaderboards on N++ for map pack " + communityMapPacksList . SelectedItem . ToString ( ) ;
2045+ }
2046+ else
2047+ {
2048+ MessageBox . Show ( "Could not retrieve a valid patch string: " + myStringWebResource . ToString ( ) + " (" + myStringWebResource . Length + ")" ) ;
2049+ }
2050+
2051+ }
2052+ catch ( Exception exc )
2053+ {
2054+ MessageBox . Show ( "Couldn't install map pack because: " + exc . Message ) ;
2055+ }
2056+ }
2057+
2058+ }
2059+
2060+ private void resetGameProfile_Click ( object sender , EventArgs e )
2061+ {
2062+ ResetProfile ( ) ;
2063+ }
2064+
2065+ private void originalMapPack_Click ( object sender , EventArgs e )
2066+ {
2067+ // TODO: revert to original metanet maps
2068+ }
2069+
2070+ private void metanetLeaderboards_Click ( object sender , EventArgs e )
2071+ {
2072+ if ( DetectNPPRunning ( ) == true )
2073+ {
2074+ MessageBox . Show ( "Please close N++ before installing map pack" ) ;
2075+ return ;
2076+ }
2077+
2078+ DialogResult dialogResult = MessageBox . Show ( "Are you sure you wish to revert to the original Metanet leaderboards?" , "Revert?" , MessageBoxButtons . YesNo ) ;
2079+ if ( dialogResult == DialogResult . Yes )
2080+ {
2081+ try
2082+ {
2083+ if ( File . Exists ( savePath + @"\NPPDLL\npp.dll" ) ) {
2084+ File . Delete ( steamGamePath + @"\npp.dll" ) ;
2085+ File . Copy ( savePath + @"\NPPDLL\npp.dll" , steamGamePath + @"\npp.dll" ) ;
2086+ }
2087+ statusLabel . Text = "Done reverting to the original Metanet leaderboards!" ;
2088+ }
2089+ catch ( Exception exc )
2090+ {
2091+ MessageBox . Show ( "Couldn't revert to original Metanet leaderboards because: " + exc . Message ) ;
2092+ }
2093+ }
2094+
2095+ }
18282096 }
18292097 public class sheetMap
18302098 {
0 commit comments