2024-06-11 12:14:16 -07:00
import assets from './assets.js' ;
export default ( { replace , replaceOne , replaceRawCode , dictionary , matchOne , matchRawCode , escapeRegExp } ) => {
// Constants for easy usage of otherwise long variable access expressions
const dict = dictionary ;
const playerId = ` ${ dict . game } . ${ dict . playerId } ` ;
const rawPlayerNames = ` ${ dict . playerData } . ${ dict . rawPlayerNames } ` ;
const gIsSingleplayer = ` ${ dict . game } . ${ dict . gIsSingleplayer } ` ;
// Replace assets
replaceOne ( /(\(4,"crown",4,")[^"]+"\),/g , "$1" + assets . crownIcon + "\")," ) ;
replaceOne ( /(\(6,"territorial\.io",6,")[^"]+"\),/g , "$1" + assets . fxClientLogo + "\")," ) ;
2024-07-05 00:55:49 -07:00
replaceOne ( /(\(22,"logo",8,")[^"]+"\)/g , "$1" + assets . smallLogo + "\")" ) ;
2024-06-11 12:14:16 -07:00
// Add FX Client version info to the game version window
2024-08-26 04:31:24 -07:00
replaceRawCode ( ` ar.oa(4,1,new s8(__L(),gameVersion+"<br><a href='"+ah.aC5+"' target='_blank'>"+ah.aC5+"</a>", ` ,
` ar.oa(4,1,new s8(__L(),gameVersion+"<br><a href='"+ah.aC5+"' target='_blank'>"+ah.aC5+"</a>"
2024-10-03 07:27:39 -07:00
+ "<br><br><b>" + "FX Client v" + _ _fx . version + "<br><a href='https://discord.gg/dyxcwdNKwK' target='_blank'>FX Client Discord server</a>"
2024-06-11 12:14:16 -07:00
+ "<br><a href='https://github.com/fxclient/FXclient' target='_blank'>Github repository</a></b>" , ` );
2024-08-24 07:04:39 -07:00
// Add update information
replaceRawCode ( ` new k("🚀 New Game Update","The game has been updated! Please reload the game.",!0,[ ` ,
` new k("🚀 New Game Update","The game has been updated! Please reload the game."
+ "<div style='border: white; border-width: 1px; border-style: solid; margin: 10px; padding: 5px;'><h2>FX Client is not yet compatible with the latest version of the game.</h2><p>Updates should normally be available within a few hours.<br>You can still use FX to play in singleplayer mode.</p></div>" , ! 0 , [ `
) ;
2024-06-11 12:14:16 -07:00
// Max size for custom maps: from 4096x4096 to 8192x8192
// TODO: test this; it might cause issues with new boat mechanics?
{ // Add Troop Density and Maximum Troops in side panel
2024-11-14 07:49:48 -08:00
const { valuesArray } = replaceRawCode ( ` ,labels[5]=__L(0,"Interest"),labels[6]=__L(),labels[7]=__L(),(truncatedLabels=new Array(labels.length)).fill(""),(valuesArray=new Array(labels.length))[0]=game.io? ` ,
` ,labels[5]=__L(0,"Interest"),labels[6]=__L(),labels[7]=__L(),
2024-06-11 12:14:16 -07:00
labels . push ( "Max Troops" , "Density" ) , // add labels
2024-11-14 07:49:48 -08:00
( truncatedLabels = new Array ( labels . length ) ) . fill ( "" ) , ( valuesArray = new Array ( labels . length ) ) [ 0 ] = game . io ? ` );
2024-06-11 12:14:16 -07:00
replaceOne ( new RegExp ( /(:(?<valueIndex>\w+)<7\?\w+\.\w+\.\w+\(valuesArray\[\2\]\)):(\w+\.\w+\(valuesArray\[7\]\))}/
. source . replace ( /valuesArray/g , valuesArray ) , "g" ) ,
'$1 : $<valueIndex> === 7 ? $3 '
2024-10-03 07:27:39 -07:00
+ ` : $ <valueIndex> === 8 ? __fx.utils.getMaxTroops( ${ dict . playerData } . ${ dict . playerTerritories } , ${ playerId } ) `
+ ` : __fx.utils.getDensity( ${ playerId } ) } ` ) ;
2024-06-11 12:14:16 -07:00
// increase the size of the side panel by 25% to make the text easier to read
replaceOne ( /(this\.\w+=Math\.floor\(\(\w+\.\w+\.\w+\(\)\?\.1646:\.126\))\*(\w+\.\w+\),)/g , "$1 * 1.25 * $2" ) ;
}
// Increment win counter on wins
2024-08-26 04:31:24 -07:00
replaceRawCode ( ` =function(sE){o.ha(sE,2),b.h9<100?xD(0,__L([a8.jx[sE]]),3,sE,ad.gN,ad.kl,-1,!0):xD(0,__L([a8.jx[sE]]),3,sE,ad.gN,ad.kl,-1,!0) ` ,
2024-06-11 12:14:16 -07:00
` =function(sE){
if ( $ { playerId } === sE && ! $ { gIsSingleplayer } )
2024-10-03 07:27:39 -07:00
_ _fx . wins . count ++ , window . localStorage . setItem ( "fx_winCount" , _ _fx . wins . count ) ,
xD ( 0 , "Your Win Count is now " + _ _fx . wins . count , 3 , sE , ad . gN , ad . kl , - 1 , ! 0 ) ;
2024-08-26 04:31:24 -07:00
o . ha ( sE , 2 ) , b . h9 < 100 ? xD ( 0 , _ _L ( [ a8 . jx [ sE ] ] ) , 3 , sE , ad . gN , ad . kl , - 1 , ! 0 ) : xD ( 0 , _ _L ( [ a8 . jx [ sE ] ] ) , 3 , sE , ad . gN , ad . kl , - 1 , ! 0 ) ` );
2024-06-11 12:14:16 -07:00
2024-10-14 10:29:43 -07:00
{ // Add settings button, custom lobby button and win count
// add buttons
2024-08-26 04:31:24 -07:00
replaceRawCode ( ` ,new nQ("☰<br>"+__L(),function(){aD6(3)},aa.ks),new nQ("",function(){at.d5(12)},aa.kg,!1)] ` ,
` ,new nQ("☰<br>"+__L(),function(){aD6(3)},aa.ks),new nQ("",function(){at.d5(12)},aa.kg,!1),
2024-10-14 10:29:43 -07:00
new nQ ( "FX Client settings" , function ( ) { _ _fx . WindowManager . openWindow ( "settings" ) ; } , "rgba(0, 0, 20, 0.5)" ) ,
new nQ ( "Join/Create custom lobby" , function ( ) { _ _fx . customLobby . showJoinPrompt ( ) ; } , "rgba(20, 9, 77, 0.5)" ) ] ` )
// set position
2024-06-20 06:22:27 -07:00
replaceRawCode ( ` aZ.g5.vO(aD3[3].button,x+a0S+gap,a3X+h+gap,a0S,h); ` ,
2024-10-14 10:29:43 -07:00
` aZ.g5.vO(aD3[3].button,x+a0S+gap,a3X+h+gap,a0S,h);
aZ . g5 . vO ( aD3 [ 5 ] . button , x , a3X + h * 2 + gap * 2 , a0S * 2 + gap , h / 3 ) ;
aZ . g5 . vO ( aD3 [ 6 ] . button , x , a3X + h * 2.33 + gap * 3 , a0S * 2 + gap , h / 3 ) ; ` );
2024-06-20 06:22:27 -07:00
// render win count
2024-07-27 09:59:59 -07:00
replaceRawCode ( ` if(_y.a4l(),_r.gI(),_m.gI(),aw.gI(),a0.g8()){ctx.imageSmoothingEnabled=!1;var iQ=a0.a4o("territorial.io"),kL=.84*aD4.gA/iQ.width; ` ,
` if(_y.a4l(),_r.gI(),_m.gI(),aw.gI(),a0.g8()){
2024-10-03 07:27:39 -07:00
if ( _ _fx . settings . displayWinCounter ) {
2024-06-20 06:22:27 -07:00
const size = Math . floor ( aD4 . gA * 0.03 ) ;
ctx . font = $ { dict . fontGeneratorFunction } ( 1 , size ) ;
ctx . fillStyle = "#ffffff" ;
2024-10-03 07:27:39 -07:00
const text = "Win count: " + _ _fx . wins . count ;
2024-06-20 06:22:27 -07:00
const textLength = ctx . measureText ( text ) . width ;
ctx . textAlign = "left" ;
ctx . textBaseline = "middle" ;
ctx . fillText ( text , ctx . canvas . width - textLength - size / 2 , size ) ;
} ;
2024-06-26 05:31:22 -07:00
ctx . imageSmoothingEnabled = ! 1 ; var iQ = a0 . a4o ( "territorial.io" ) , kL = . 84 * aD4 . gA / iQ . width ; ` )
2024-06-20 06:22:27 -07:00
/*/ / render gear icon and win count
2024-06-11 12:14:16 -07:00
replaceRawCode ( ` ,fy=aV.nU[80],fontSize=.65*height,canvas.font=aY.g0.g1(1,fontSize),canvas.fillStyle="rgba("+gR+","+tD+","+hj+",0.6)",canvas.fillRect(x,y,width,height), ` ,
` ,fy=aV.nU[80],fontSize=.65*height,
canvas . imageSmoothingEnabled = true ,
canvas . drawImage ( settingsGearIcon , x - width / 2 , y , height , height ) ,
canvas . imageSmoothingEnabled = false ,
( settings . displayWinCounter && (
canvas . font = aY . g0 . g1 ( 1 , Math . floor ( height * 0.4 ) ) ,
canvas . fillStyle = "#ffffff" ,
canvas . fillText ( "Win count: " + wins _counter , Math . floor ( x + width / 2 ) , Math . floor ( ( y + height / 2 ) * 2 ) )
) ) ,
canvas . font = aY . g0 . g1 ( 1 , fontSize ) , canvas . fillStyle = "rgba(" + gR + "," + tD + "," + hj + ",0.6)" , canvas . fillRect ( x , y , width , height ) , ` );
// handle settings button click
replaceRawCode ( ` (q6=Math.floor((b7.cv.fv()?.145:.09)*aK.fw),gap=Math.floor(.065*(b7.cv.fv()?.53:.36)*aK.fw),gap=aK.g5-q6-gap,jd=b0.gap,q6=Math.floor(.35*q6),gap<=mouseX&&mouseY<jd+q6&&ar.v2(1)) ` ,
` (q6=Math.floor((b7.cv.fv()?.145:.09)*aK.fw),gap=Math.floor(.065*(b7.cv.fv()?.53:.36)*aK.fw),gap=aK.g5-q6-gap,jd=b0.gap,q6=Math.floor(.35*q6),
( gap <= mouseX && mouseY < jd + q6 && ( ar . v2 ( 1 ) , true ) ) || ( mouseX >= gap - q6 / 0.7 && mouseY < jd + q6 && WindowManager . openWindow ( "settings" ) )
2024-06-20 06:22:27 -07:00
) ` );*/
2024-06-11 12:14:16 -07:00
}
{ // Keybinds
// match required variables
2024-11-14 07:49:48 -08:00
const { 0 : match , groups : { attackBarObject , setRelative } } = matchOne ( /:\w+\.\w+\(\w+,8\)\?(?<attackBarObject>\w+)\.(?<setRelative>\w+)\(16\/15\):/g ) ;
2024-06-11 12:14:16 -07:00
// create a setAbsolutePercentage function on the attack percentage bar object,
// and also register the keybind handler functions
replaceOne ( /}(function \w+\((\w+)\){return!\(1<\2&&1===(?<attackPercentage>\w+)\|\|\(1<\2&&\2\*\3-\3<1\/1024\?\2=\(\3\+1\/1024\)\/\3:\2<1)/g ,
"} this.setAbsolutePercentage = function(newPercentage) { $<attackPercentage> = newPercentage; }; "
2024-10-03 07:27:39 -07:00
+ "__fx.keybindFunctions.setAbsolute = this.setAbsolutePercentage; "
+ ` __fx.keybindFunctions.setRelative = (arg1) => ${ attackBarObject } . ${ setRelative } (arg1); $ 1 ` ) ;
2024-06-11 12:14:16 -07:00
// insert keybind handling code into the keyDown handler function
replaceOne ( new RegExp ( /(function \w+\((?<event>\w+)\){)([^}]+matched)/g . source . replace ( /matched/g , escapeRegExp ( match ) ) , "g" ) ,
2024-10-03 07:27:39 -07:00
"$1 if (__fx.keybindHandler($<event>.key)) return; $3" ) ;
2024-06-11 12:14:16 -07:00
}
// Set the default font to Trebuchet MS
replace ( /sans-serif"/g , 'Trebuchet MS"' ) ;
// Realistic bot names setting
// matches c4[i] = c4[i].replace(a6U[dx], a6V[dx])
2024-10-03 07:27:39 -07:00
replaceOne ( /(((\w+)\[\w+\])=\2\.replace\(\w+(\[\w+\]),\w+\4\))/g , "$1; if (__fx.settings.realisticNames) $3 = realisticNames;" )
2024-06-11 12:14:16 -07:00
// Hide all links in main menu depending on settings
//replaceOne(/(this\.\w+=function\(\){)((\w+\.\w+)\[2\]=\3\[3\]=\3\[4\]=(?<linksHidden>!this\.\w+\.\w+),)/g,
//"$1 if (settings.hideAllLinks) $3[0] = $3[1] = $<linksHidden>; else $3[0] = $3[1] = true; $2")
// Make the main canvas context have an alpha channel if a custom background is being used
2024-10-03 07:27:39 -07:00
replaceOne ( /(document\.getElementById\("canvasA"\),\(\w+=\w+\.getContext\("2d",){alpha:!1}/g , "$1 {alpha: __fx.makeMainMenuTransparent}" )
2024-06-11 12:14:16 -07:00
// Clear canvas background if a custom background is being used
2024-06-20 06:22:27 -07:00
replaceRawCode ( ` ,this.qk=function(){var a4n,a4m;aq.pd?(a4m=aL.gA/aq.eE,a4n=aL.gF/aq.eF,canvas.setTransform(a4m=a4n<a4m?a4m:a4n,0,0,a4m, ` ,
` ,this.qk=function(){var a4n,a4m;
2024-10-03 07:27:39 -07:00
if ( _ _fx . makeMainMenuTransparent ) canvas . clearRect ( 0 , 0 , aL . gA , aL . gF ) ;
2024-06-20 06:22:27 -07:00
else aq . pd ? ( a4m = aL . gA / aq . eE , a4n = aL . gF / aq . eF , canvas . setTransform ( a4m = a4n < a4m ? a4m : a4n , 0 , 0 , a4m , ` );
2024-06-11 12:14:16 -07:00
// Track donations
replaceOne ( /(this\.\w+=function\((\w+),(\w+)\)\{)(\2===\w+\.\w+&&\(\w+\.\w+\((\w+\.\w+)\[0\],\5\[1\],\3\),this\.(\w+)\[12\]\+=\5\[1\],this\.\6\[16\]\+=\5\[0\]\),\3===\w+\.\w+&&\()/g ,
2024-10-03 07:27:39 -07:00
"$1 __fx.donationsTracker.logDonation($2, $3, $5[0]); $4" )
2024-06-11 12:14:16 -07:00
// Display donations for a player when clicking on them in the leaderboard
// and skip handling clicks when clicking on an empty space (see the isEmptySpace
// variable in the modified leaderboard click handler from the leaderboard filter)
// match , 0 !== dG[x]) && fq.hB(x, 800, false, 0),
replaceOne ( /,(0!==\w+\.\w+\[(\w+)\])(\)&&\w+\.\w+\(\2,800,!1,0\),)/g ,
2024-10-03 07:27:39 -07:00
` , ${ dict . game } . ${ dict . gIsTeamGame } && __fx.donationsTracker.displayHistory( $ 2, ${ rawPlayerNames } , ${ gIsSingleplayer } ), $ 1 && !isEmptySpace $ 3 ` ) ;
2024-06-11 12:14:16 -07:00
// Reset donation history and leaderboard filter when a new game is started
2024-11-25 07:27:09 -08:00
replaceOne ( new RegExp ( ` ,this \\ . ${ dictionary . playerBalances } .fill \\ (0 \\ ), ` , "g" ) , "$& __fx.donationsTracker.reset(), __fx.leaderboardFilter.reset(), __fx.customLobby.isActive() && __fx.customLobby.hideWindow(), " ) ;
2024-06-11 12:14:16 -07:00
{ // Player list and leaderboard filter tabs
// Draw player list button
const uiOffset = dictionary . uiSizes + "." + dictionary . gap ;
2024-11-14 07:49:48 -08:00
const { groups : { drawFunction , topBarHeight } } = replaceOne ( /(="";function (?<drawFunction>\w+)\(\){[^}]+?(?<canvas>\w+)\.fillRect\(0,(?<topBarHeight>\w+),\w+,1\),(?:\3\.fillRect\([^()]+\),)+\3\.font=\w+,(\w+\.\w+)\.textBaseline\(\3,1\),\5\.textAlign\(\3,1\),\3\.fillText\(\w+,Math\.floor\()(\w+)\/2\),(Math\.floor\(\w+\+\w+\/2\)\));/g ,
2024-10-03 07:27:39 -07:00
"$1($6 + $<topBarHeight> - 22) / 2), $7; __fx.playerList.drawButton($<canvas>, 12, 12, $<topBarHeight> - 22);" ) ;
const buttonBoundsCheck = ` __fx.utils.isPointInRectangle( $ <x>, $ <y>, ${ uiOffset } + 12, ${ uiOffset } + 12, ${ topBarHeight } - 22, ${ topBarHeight } - 22) `
2024-06-11 12:14:16 -07:00
// Handle player list button and leaderboard tabs mouseDown
// and create a function for scrolling the leaderboard to the top
replaceOne ( /(this\.\w+=function\((?<x>\w+),(?<y>\w+)\){return!!\w+\(\2,\3\))&&(\(\w+=\w+\.\w+,[^}]+),!0\)/g ,
2024-10-03 07:27:39 -07:00
` __fx.leaderboardFilter.scrollToTop = function(){position = 0;}, $ 1 && (( ${ buttonBoundsCheck } && __fx.playerList.display( ${ rawPlayerNames } ), true)
&& ! ( $ < y > - $ { uiOffset } > _ _fx . leaderboardFilter . verticalClickThreshold && _ _fx . leaderboardFilter . handleMouseDown ( $ < x > - $ { uiOffset } ) ) && $4 ) , ! 0 ) ` );
2024-06-11 12:14:16 -07:00
// Handle player list button and leaderboard tabs hover
// and create a function for repainting the leaderboard
replaceOne ( /(this\.\w+=function\((?<x>\w+),(?<y>\w+)\){)(var \w+,\w+=\w+\(\3\);return \w+\?\(\w+=(\w+),\(\5=\w+\(0,\5\+=(?:[^}]+,(?<setRepaintNeeded>\w+\.\w+=!0)){2})/g ,
2024-10-03 07:27:39 -07:00
` __fx.leaderboardFilter.repaintLeaderboard = function() { ${ drawFunction } (), $ <setRepaintNeeded>; },
$1 if ( $ { buttonBoundsCheck } ) { _ _fx . playerList . hoveringOverButton === false && ( _ _fx . playerList . hoveringOverButton = true , $ { drawFunction } ( ) , $ < setRepaintNeeded > ) ; }
else { _ _fx . playerList . hoveringOverButton === true && ( _ _fx . playerList . hoveringOverButton = false , $ { drawFunction } ( ) , $ < setRepaintNeeded > ) ; }
if ( _ _fx . leaderboardFilter . setHovering (
_ _fx . utils . isPointInRectangle ( $ < x > , $ < y > , $ { uiOffset } , $ { uiOffset } + _ _fx . leaderboardFilter . verticalClickThreshold , _ _fx . leaderboardFilter . windowWidth , _ _fx . leaderboardFilter . tabBarOffset ) , $ < x > - $ { uiOffset }
2024-06-11 12:14:16 -07:00
) ) return ; $4 ` );
}
2024-11-25 07:27:09 -08:00
{ // Name rendering patches - Display density of other players & Hide bot names features
2024-06-11 12:14:16 -07:00
const r = matchRawCode ( ` bD.dO.data[7].value?a9W(i,jm,jk,jl,ctx):a9V(ctx,i,jm,jk,jl,a9S))) ` ) ;
const settingsSwitchNameAndBalance = ` ${ r . bD } . ${ r . dO } . ${ r . data } [7]. ${ r . value } ` ;
2024-11-25 07:27:09 -08:00
// Balance rendering; Renders density when the "Reverse Name/Balance" setting is off
2024-06-11 12:14:16 -07:00
replaceRawCode ( "function a9V(ctx,i,fontSize,x,y,a9S){i=ac.jv.formatNumber(playerData.playerBalances[i]);a9S>>1&1?(ctx.lineWidth=.05*fontSize,ctx.strokeStyle=a9U(fontSize,a9S%2),ctx.strokeText(i,x,y)):(1<a9S&&(ctx.lineWidth=.12*fontSize,ctx.strokeStyle=a9U(fontSize,a9S),ctx.strokeText(i,x,y)),ctx.fillText(i,x,y))}" ,
` function a9V(ctx,i,fontSize,x,y,a9S){
var _ _ _id = i ;
i = ac . jv . formatNumber ( playerData . playerBalances [ i ] ) ; a9S >> 1 & 1 ? ( ctx . lineWidth = . 05 * fontSize , ctx . strokeStyle = a9U ( fontSize , a9S % 2 ) , ctx . strokeText ( i , x , y ) ) : ( 1 < a9S && ( ctx . lineWidth = . 12 * fontSize , ctx . strokeStyle = a9U ( fontSize , a9S ) , ctx . strokeText ( i , x , y ) ) , ctx . fillText ( i , x , y ) ) ;
2024-10-03 07:27:39 -07:00
$ { settingsSwitchNameAndBalance } || _ _fx . settings . showPlayerDensity && ( _ _fx . settings . coloredDensity && ( ctx . fillStyle = _ _fx . utils . textStyleBasedOnDensity ( _ _ _id ) ) , ctx . fillText ( _ _fx . utils . getDensity ( _ _ _id ) , x , y + fontSize ) ) } ` )
2024-11-25 07:27:09 -08:00
// Name rendering; Renders density when the "Reverse Name/Balance" setting is on (default)
replaceOne ( /(function \w+\((?<i>\w+),(?<fontSize>\w+),(?<x>\w+),(?<y>\w+),(?<canvas>\w+)\){)(\6\.fillText\((?<playerData>\w+)\.(?<playerNames>\w+)\[\2\],\4,\5\)),(\2<(?<game>\w+)\.(?<gHumans>\w+)&&2!==\8\.(?<playerStates>\w+)\[[^}]+)}/g ,
` $ 1 var ___id = $ 2;
var showName = $ < i > < $ < game > . $ < gHumans > || ! _ _fx . settings . hideBotNames ;
if ( showName ) $7 , $10 ;
$ { settingsSwitchNameAndBalance } && _ _fx . settings . showPlayerDensity && (
_ _fx . settings . coloredDensity && ( $ < canvas > . fillStyle = _ _fx . utils . textStyleBasedOnDensity ( _ _ _id ) ) ,
$ < canvas > . fillText ( _ _fx . utils . getDensity ( _ _ _id ) , $ < x > , showName ? $ < y > + $ < fontSize > : $ < y > )
) ; } ` );
2024-06-11 12:14:16 -07:00
}
{ // Leaderboard filter
// for the leaderboard draw function:
replaceRawCode ( "function drawFunction(){a0A.clearRect(0,0,a04,y9),a0A.fillStyle=aZ.lE,a0A.fillRect(0,0,a04,a0F),a0A.fillStyle=aZ.kZ,a0A.fillRect(0,a0F,a04,y9-a0F),leaderboardPositionsById[game.playerId]>=position&&a0Z(leaderboardPositionsById[game.playerId]-position,aZ.kw),0!==leaderboardPositionsById[game.playerId]&&0===position&&a0Z(0,aZ.lJ),-1!==a0P&&a0Z(a0P,aZ.kd),a0A.fillStyle=aZ.gF,a0A.fillRect(0,a0F,a04,1),a0A.fillRect(0,0,a04,b0.ur),a0A.fillRect(0,0,b0.ur,y9),a0A.fillRect(a04-b0.ur,0,b0.ur,y9),a0A.fillRect(0,y9-b0.ur,a04,b0.ur)," ,
` var leaderboardHasChanged = true;
this . playerPos = game . playerId ;
2024-10-03 07:27:39 -07:00
_ _fx . leaderboardFilter . setUpdateFlag = ( ) => leaderboardHasChanged = true ;
2024-06-11 12:14:16 -07:00
function updateFilteredLb ( ) {
if ( ! leaderboardHasChanged ) return ;
2024-10-03 07:27:39 -07:00
_ _fx . leaderboardFilter . filteredLeaderboard = _ _fx . leaderboardFilter . playersToInclude
2024-06-11 12:14:16 -07:00
. map ( id => leaderboardPositionsById [ id ] ) . sort ( ( a , b ) => a - b ) ;
leaderboardHasChanged = false ;
2024-10-03 07:27:39 -07:00
this . playerPos = _ _fx . leaderboardFilter . filteredLeaderboard . indexOf ( leaderboardPositionsById [ game . playerId ] ) ;
2024-06-11 12:14:16 -07:00
}
function drawFunction ( ) {
a0A . clearRect ( 0 , 0 , a04 , y9 ) ,
a0A . fillStyle = aZ . lE ,
a0A . fillRect ( 0 , 0 , a04 , a0F ) ,
a0A . fillStyle = aZ . kZ ,
a0A . fillRect ( 0 , a0F , a04 , y9 - a0F ) ;
2024-10-03 07:27:39 -07:00
if ( _ _fx . leaderboardFilter . enabled ) updateFilteredLb ( ) ;
var playerPos = ( _ _fx . leaderboardFilter . enabled
2024-06-11 12:14:16 -07:00
? this . playerPos
: leaderboardPositionsById [ game . playerId ]
) ;
2024-10-03 07:27:39 -07:00
if ( _ _fx . leaderboardFilter . hoveringOverTabs ) a0P = - 1 ;
if ( _ _fx . leaderboardFilter . enabled && a0P >= _ _fx . leaderboardFilter . filteredLeaderboard . length ) a0P = - 1 ;
2024-06-11 12:14:16 -07:00
playerPos >= position && a0Z ( playerPos - position , aZ . kw ) ,
0 !== leaderboardPositionsById [ game . playerId ] && 0 === position && a0Z ( 0 , aZ . lJ ) ,
- 1 !== a0P && a0Z ( a0P , aZ . kd ) ,
a0A . fillStyle = aZ . kZ ,
//console.log("drawing", a0P),
2024-10-03 07:27:39 -07:00
a0A . clearRect ( 0 , y9 - _ _fx . leaderboardFilter . tabBarOffset , a04 , _ _fx . leaderboardFilter . tabBarOffset ) ;
a0A . fillRect ( 0 , y9 - _ _fx . leaderboardFilter . tabBarOffset , a04 , _ _fx . leaderboardFilter . tabBarOffset ) ;
2024-06-11 12:14:16 -07:00
a0A . fillStyle = aZ . gF ,
a0A . fillRect ( 0 , a0F , a04 , 1 ) ,
2024-10-03 07:27:39 -07:00
a0A . fillRect ( 0 , y9 - _ _fx . leaderboardFilter . tabBarOffset , a04 , 1 ) ,
_ _fx . leaderboardFilter . drawTabs ( a0A , a04 , y9 - _ _fx . leaderboardFilter . tabBarOffset , aZ . kw ) ,
2024-06-11 12:14:16 -07:00
a0A . fillRect ( 0 , 0 , a04 , b0 . ur ) ,
a0A . fillRect ( 0 , 0 , b0 . ur , y9 ) ,
a0A . fillRect ( a04 - b0 . ur , 0 , b0 . ur , y9 ) ,
a0A . fillRect ( 0 , y9 - b0 . ur , a04 , b0 . ur ) , ` )
replaceRawCode ( "var hZ,eh=leaderboardPositionsById[game.playerId]<position+windowHeight-1?1:2;for(a0A.font=a07,aY.g0.textAlign(a0A,0),hZ=windowHeight-eh;0<=hZ;hZ--)a0a(leaderboardArray[hZ+position]),a0b(hZ,hZ+position,leaderboardArray[hZ+position]);for(aY.g0.textAlign(a0A,2),hZ=windowHeight-eh;0<=hZ;hZ--)a0a(leaderboardArray[hZ+position]),a0c(hZ,leaderboardArray[hZ+position]);" ,
` var hZ, eh = playerPos < position + windowHeight - 1 ? 1 : 2;
2024-10-03 07:27:39 -07:00
if ( _ _fx . leaderboardFilter . enabled ) {
let result = _ _fx . leaderboardFilter . filteredLeaderboard ;
2024-06-11 12:14:16 -07:00
if ( position !== 0 && position >= result . length - windowHeight )
position = ( result . length > windowHeight ? result . length : windowHeight ) - windowHeight ;
//if (position >= result.length) position = result.length - 1;
for ( a0A . font = a07 , aY . g0 . textAlign ( a0A , 0 ) , hZ = windowHeight - eh ; 0 <= hZ ; hZ -- ) {
const pos = result [ hZ + position ] ;
if ( pos !== undefined )
a0a ( leaderboardArray [ pos ] ) , a0b ( hZ , pos , leaderboardArray [ pos ] ) ;
}
for ( aY . g0 . textAlign ( a0A , 2 ) , hZ = windowHeight - eh ; 0 <= hZ ; hZ -- ) {
const pos = result [ hZ + position ] ;
if ( pos !== undefined )
a0a ( leaderboardArray [ pos ] ) , a0c ( hZ , leaderboardArray [ pos ] ) ;
}
} else {
for ( a0A . font = a07 , aY . g0 . textAlign ( a0A , 0 ) , hZ = windowHeight - eh ; 0 <= hZ ; hZ -- )
a0a ( leaderboardArray [ hZ + position ] ) , a0b ( hZ , hZ + position , leaderboardArray [ hZ + position ] ) ;
for ( aY . g0 . textAlign ( a0A , 2 ) , hZ = windowHeight - eh ; 0 <= hZ ; hZ -- )
a0a ( leaderboardArray [ hZ + position ] ) , a0c ( hZ , leaderboardArray [ hZ + position ] ) ;
} ` )
// in the leaderboard resize handler: make space for the tab buttons at the bottom of the leaderboard
replaceRawCode ( ",a09.height=y9,a09_ctx=a09.getContext(\"2d\",{alpha:!0}),a0D=.025*a04,a06=.16*a04,a0E=0*a04,a0F=Math.floor(.45*a0D+a06),a0G=(y9-a06-2*a0D-a0E)/a08,a05=aY.g0.g1(1,Math.floor(.55*a06))," ,
` ,a09.height=y9,a09_ctx=a09.getContext("2d",{alpha:!0}),a0D=.025*a04,a06=.16*a04,a0E=0*a04,a0F=Math.floor(.45*a0D+a06),a0G=(y9-a06-2*a0D-a0E)/a08,
2024-10-03 07:27:39 -07:00
a09 . height = y9 += a0G , _ _fx . leaderboardFilter . tabBarOffset = Math . floor ( a0G * 1.3 ) , _ _fx . leaderboardFilter . verticalClickThreshold = y9 - _ _fx . leaderboardFilter . tabBarOffset , _ _fx . leaderboardFilter . windowWidth = a04 ,
2024-06-11 12:14:16 -07:00
a05 = aY . g0 . g1 ( 1 , Math . floor ( . 55 * a06 ) ) , ` )
// Set the leaderboardHasChanged flag on leaderboard updates
replaceRawCode ( "for(var eM=a0q-1;0<=eM;eM--)a14[eM]=jR[eM],a15[eM]=a8.f8[jR[eM]];a14[a0q]=a0l[b.ed],a15[a0q]=a8.f8[b.ed]" ,
` for(var eM=a0q-1;0<=eM;eM--)a14[eM]=jR[eM],a15[eM]=a8.f8[jR[eM]];a14[a0q]=a0l[b.ed],a15[a0q]=a8.f8[b.ed]; leaderboardHasChanged = true; ` ) ;
// handle clicking on a player in the leaderboard
replaceRawCode ( "var a0p=a0q(fJ);return ag.tQ()&&-1!==a0P&&(a0P=-1,a0Y(),b3.d1=!0),b3.dY-a0Q<350&&a0T===a0p&&-1!==(a0p=(a0p=yr(-1,a0p,windowHeight))!==windowHeight&&vU(x,y)?a0p:-1)&&(x=leaderboardArray[a0p+position],a0p===windowHeight-1&&leaderboardPositionsById[game.playerId]>=position+windowHeight-1&&(x=game.playerId)," ,
` var a0p = a0q(fJ);
var isEmptySpace = false ;
2024-10-03 07:27:39 -07:00
return ag . tQ ( ) && - 1 !== a0P && ( a0P = - 1 , a0Y ( ) , b3 . d1 = ! 0 ) , b3 . dY - a0Q < 350 && a0T === a0p && - 1 !== ( a0p = ( a0p = yr ( - 1 , a0p , windowHeight ) ) !== windowHeight && vU ( x , y ) ? a0p : - 1 ) && ( x = ( _ _fx . leaderboardFilter . enabled ? ( updateFilteredLb ( ) , leaderboardArray [ _ _fx . leaderboardFilter . filteredLeaderboard [ a0p + position ] ? ? ( isEmptySpace = true , leaderboardPositionsById [ game . playerId ] ) ] ) : leaderboardArray [ a0p + position ] ) , a0p === windowHeight - 1 && ( _ _fx . leaderboardFilter . enabled ? this . playerPos : leaderboardPositionsById [ game . playerId ] ) >=
2024-06-11 12:14:16 -07:00
position + windowHeight - 1 && ( x = game . playerId ) , ! isEmptySpace && ` );
// Get clan parsing function
replaceRawCode ( ` this.uI=function(username){var uK,uJ=username.indexOf("[");return!(uJ<0)&&1<(uK=username.indexOf("]"))-uJ&&uK-uJ<=8?username.substring(uJ+1,uK).toUpperCase().trim():null}, ` ,
2024-10-03 07:27:39 -07:00
` this.uI=function(username){var uK,uJ=username.indexOf("[");return!(uJ<0)&&1<(uK=username.indexOf("]"))-uJ&&uK-uJ<=8?username.substring(uJ+1,uK).toUpperCase().trim():null}, __fx.leaderboardFilter.parseClanFromPlayerName = this.uI; ` ) ;
2024-06-11 12:14:16 -07:00
}
{ // Hovering tooltip
2024-09-16 03:03:05 -07:00
replaceRawCode ( "this.click=function(gG,gH,uH){var fd=an.fe(gG),ff=an.fg(gH),fh=an.fi(fd,ff),fj=an.fk(fh);if(!an.fl(fd,ff))return!1;var fd=(bB.d3.isUIZoomEnabled()?.025:.0144)*aO.g4,ff=performance.now();if(Math.abs(gG-wK)>fd||Math.abs(gH-wL)>fd||dg+500<ff)return!1;if(dg=ff,uH&&!function(gG,gH,fj){a3.ek(fj)||-1===(gG=ao.fr.wq(gG,gH))?l.wp(fj):l.wr(gG)}(gG,gH,fj)," ,
2024-10-03 07:27:39 -07:00
` __fx.hoveringTooltip.display = function(mouseX, mouseY) {
2024-06-11 12:14:16 -07:00
var coordX = an . fe ( mouseX ) , coordY = an . fg ( mouseY ) ,
coord = an . fi ( coordX , coordY ) , point = an . fk ( coord ) ;
if ( coordX < 0 || coordY < 0 ) return ;
( function ( gG , gH , fj ) {
a3 . ek ( fj ) || - 1 === ( gG = ao . fr . wq ( gG , gH ) ) ? l . wp ( fj ) : l . wr ( gG )
} ( mouseX , mouseY , point ) )
}
2024-08-16 05:56:58 -07:00
this . click = function ( gG , gH , uH ) { var fd = an . fe ( gG ) , ff = an . fg ( gH ) , fh = an . fi ( fd , ff ) , fj = an . fk ( fh ) ; if ( ! an . fl ( fd , ff ) ) return ! 1 ; fd = ( bB . d3 . isUIZoomEnabled ( ) ? . 025 : . 0144 ) * aO . g4 , ff = performance . now ( ) ; if ( Math . abs ( gG - wK ) > fd || Math . abs ( gH - wL ) > fd || dg + 500 < ff ) return ! 1 ; if ( dg = ff , uH && ! function ( gG , gH , fj ) { a3 . ek ( fj ) || - 1 === ( gG = ao . fr . wq ( gG , gH ) ) ? l . wp ( fj ) : l . wr ( gG ) } ( gG , gH , fj ) , ` )
2024-07-21 04:20:43 -07:00
replaceRawCode ( "aK.nH=(window.devicePixelRatio||1)*aEr," ,
2024-10-03 07:27:39 -07:00
` aK.nH = (window.devicePixelRatio || 1) * aEr, __fx.hoveringTooltip.canvasPixelScale = aK.nH, ` )
2024-06-11 12:14:16 -07:00
}
2024-07-12 10:15:19 -07:00
{ // Highlight clan spawnpoints
// when rendered on game start
replaceRawCode ( "var x;0!==playerData.eg[i]&&0!==playerData.playerTerritories[i]&&(x=playerData.nu[i]+playerData.nw[i]+1-gv-2>>1,gv=playerData.nv[i]+playerData.nx[i]+1-gv-2>>1,ctx.drawImage(km[game.gIsTeamGame?lV.i6[i]:i<game.gHumans?1:0],x,gv))" ,
2024-10-03 07:27:39 -07:00
` var x, y, highlight = __fx.settings.highlightClanSpawns && __fx.clanFilter.inOwnClan[i];
2024-07-12 10:15:19 -07:00
if ( highlight ) gv *= 2 ;
0 !== playerData . eg [ i ] && 0 !== playerData . playerTerritories [ i ] && ( x = playerData . nu [ i ] + playerData . nw [ i ] + 1 - gv - 2 >> 1 , y = playerData . nv [ i ] + playerData . nx [ i ] + 1 - gv - 2 >> 1 ,
highlight ? ctx . drawImage ( km [ game . gIsTeamGame ? lV . i6 [ i ] : i < game . gHumans ? 1 : 0 ] , x , y , gv , gv )
: ctx . drawImage ( km [ game . gIsTeamGame ? lV . i6 [ i ] : i < game . gHumans ? 1 : 0 ] , x , y ) ) ` )
// when rendered during spawn selection
replaceRawCode ( "function(a6,es,bK,hP,hQ,hR,ov){0===dV.eg[a6]||0===dV.ev[a6]||(hQ=ay.ak*((dV.nu[a6]+dV.nw[a6]+1)/2-bK)/(hQ-bK)-.5*es,bK=ay.al*((dV.nv[a6]+dV.nx[a6]+1)/2-hP)/(hR-hP)-.5*es,hQ>ay.ak)||bK>ay.al||hQ<-es||bK<-es||(bI.setTransform(cz,0,0,cz,hQ,bK)," ,
` function(a6,es,bK,hP,hQ,hR,ov){
2024-10-03 07:27:39 -07:00
var highlight = _ _fx . settings . highlightClanSpawns && _ _fx . clanFilter . inOwnClan [ a6 ] ;
2024-07-12 10:15:19 -07:00
if ( highlight ) es *= 2 ;
0 === dV . eg [ a6 ] || 0 === dV . ev [ a6 ] || ( hQ = ay . ak * ( ( dV . nu [ a6 ] + dV . nw [ a6 ] + 1 ) / 2 - bK ) / ( hQ - bK ) - . 5 * es , bK = ay . al * ( ( dV . nv [ a6 ] + dV . nx [ a6 ] + 1 ) / 2 - hP ) / ( hR - hP ) - . 5 * es , hQ > ay . ak ) || bK > ay . al || hQ < - es || bK < - es || ( bI . setTransform ( highlight ? cz * 2 : cz , 0 , 0 , highlight ? cz * 2 : cz , hQ , bK ) , `
)
}
2024-10-14 10:29:43 -07:00
{ // Custom lobbies
replaceRawCode ( "this.aHm=function(){i___.rX(),aM.a7U(bY.dZ.data[10].value),aM.init()}" ,
` this.aHm=function(){i___.rX(),aM.a7U(bY.dZ.data[10].value),aM.init()},
_ _fx . customLobby . setJoinFunction ( ( ) => { i _ _ _ . rX ( ) ; aM . a7U ( 0 ) ; aM . init ( ) ; } ) `
)
replaceRawCode ( ` (socketId-aq.kt.a82)+"/",(socket=new WebSocket(url) ` ,
` (socketId-aq.kt.a82)+"/",(socket=new WebSocket(__fx.customLobby.isActive() && socketId === 1 ? __fx.customLobby.getSocketURL() : url) ` )
replaceRawCode ( "this.send=function(socketId,data){aJE(socketId),aJ4[socketId].send(data)}" ,
"this.send=function(socketId,data){aJE(socketId),aJ4[socketId].send(data)},__fx.customLobby.setSendFunction(this.send)" )
replaceRawCode ( "b7.dH(a0),0===b7.size?aq.kt.aJJ(wR,3205):" ,
"b7.dH(a0),0===b7.size?aq.kt.aJJ(wR,3205):__fx.customLobby.isCustomMessage(a0)||" )
// set the custom lobby to inactive when clicking the "Back" button on the connection screen or leaving the lobby
replaceRawCode ( "this.xZ=function(){Sockets.kt.wf(3260),i___.kt.we()}" ,
"this.xZ=function(){Sockets.kt.wf(3260),__fx.customLobby.setActive(false),i___.kt.we()}" )
replaceRawCode ( "this.xY=function(){this.wg(),Sockets.kt.wf(3240),aN.setState(0),i___.j(5,5)}" ,
` this.xY=function(){this.wg(),Sockets.kt.wf(3240),__fx.customLobby.setActive(false),aN.setState(0),i___.j(5,5)},
_ _fx . customLobby . setLeaveFunction ( ( ) => this . xY ( ) ) ` )
replaceRawCode ( "this.wQ=function(wR,d){if(8===i.pz&&0===wR)if(4211===d)wS(d);" ,
2024-10-28 08:22:52 -07:00
"this.wQ=function(wR,d){ wR===1&&__fx.customLobby.isActive()&&__fx.customLobby.setActive(false); if(8===i.pz&&0===wR)if(4211===d)wS(d);" )
2024-11-25 07:27:09 -08:00
// when leaving a game
replaceRawCode ( "this.wl=function(zs){ap.ky.zt(),this.vH=0,bU.zu(),m.n.setState(0),zs||bJ.df.show(),aN.setState(0),i.j(5,5)}" ,
"this.wl=function(zs){__fx.customLobby.setActive(false); ap.ky.zt(),this.vH=0,bU.zu(),m.n.setState(0),zs||bJ.df.show(),aN.setState(0),i.j(5,5)}" )
2024-10-14 10:29:43 -07:00
// if the server is unreachable
replaceRawCode ( "0===a7Q?g.wc(3249):" , "0===a7Q?g.wc(3249):1===a7Q&&__fx.customLobby.isActive()?(g.wc(3249),__fx.customLobby.setActive(false)):" )
// error descriptions
2024-10-28 08:22:52 -07:00
const errors = { 3249 : "No servers found" , 4705 : "Lobby not found" , 4730 : "Kicked from lobby" } ;
2024-10-14 10:29:43 -07:00
replaceRawCode ( ` i___.j(4,5,new k("⚠️ "+title,w3__,!0)) ` ,
` i___.j(4,5,new k("⚠️ "+title, ${ JSON . stringify ( errors ) } [w3__] || w3__,!0)) ` )
// map info (for the map selection menu)
replaceRawCode ( "this.info=new Array(Maps.totalMapCount+1),this.info[0]={name:__L()," ,
"this.info=new Array(Maps.totalMapCount+1),__fx.customLobby.setMapInfo(this.info),this.info[0]={name:__L()," )
2024-11-25 07:27:09 -08:00
// custom difficulty
replaceRawCode ( "if(ax.jm){if(ax.jn.jo)for(i=game.jp-1;0<=i;i--)this.strength[i+jl]=ax.jn.jo[i+1]}else if(9===game.jq)this.jr();" ,
` if(ax.jm){if(ax.jn.jo)for(i=game.jp-1;0<=i;i--)this.strength[i+jl]=ax.jn.jo[i+1]}else if(9===game.jq)this.jr();
else if ( _ _fx . customLobby . isActive ( ) ) for ( i = game . jp - 1 ; 0 <= i ; i -- ) this . strength [ i + jl ] = _ _fx . customLobby . gameInfo . difficulty ; `
)
2024-10-14 10:29:43 -07:00
}
2024-06-24 09:01:14 -07:00
// Invalid hostname detection avoidance
replaceRawCode ( ` ,hostnameIsValid=0<=window.location.hostname.toLowerCase().indexOf("territorial.io"), ` ,
2024-07-21 04:21:46 -07:00
` ,hostnameIsValid=true, ` )
2024-06-24 09:01:14 -07:00
2024-06-11 12:14:16 -07:00
// Disable built-in Territorial.io error reporting
replaceOne ( /window\.addEventListener\("error",function (\w+)\((\w+)\){/g ,
'$& window.removeEventListener("error", $1); return alert("Error:\\n" + $2.filename + " " + $2.lineno + " " + $2.colno + " " + $2.message);' ) ;
console . log ( 'Removing ads...' ) ;
// Remove ads
replace ( '//api.adinplay.com/libs/aiptag/pub/TRT/territorial.io/tag.min.js' , '' ) ;
2024-07-13 04:04:56 -07:00
}