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 + "\"),");
replaceOne(/(\(22,"logo",8,")[^"]+"\)/g, "$1" + assets.smallLogo + "\")");
// Add FX Client version info to the game version window
replaceRawCode(`ar.oa(4,1,new s8(__L(),gameVersion+"
"+ah.aC5+"",`,
`ar.oa(4,1,new s8(__L(),gameVersion+"
"+ah.aC5+""
+ "
" + "FX Client v" + __fx.version + "
FX Client Discord server"
+ "
Github repository",`);
// 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."
+ "
FX Client is not yet compatible with the latest version of the game.
Updates should normally be available within a few hours.
You can still use FX to play in singleplayer mode.
",!0,[`
);
// 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
const { valuesArray } = replaceRawCode(`,labels[5]=__L(),labels[6]=__L(),labels[7]=__L(),(valuesArray=new Array(labels.length))[0]=game.io?`,
`,labels[5]=__L(),labels[6]=__L(),labels[7]=__L(),
labels.push("Max Troops", "Density"), // add labels
(valuesArray=new Array(labels.length))[0]=game.io?`);
replaceOne(new RegExp(/(:(?\w+)<7\?\w+\.\w+\.\w+\(valuesArray\[\2\]\)):(\w+\.\w+\(valuesArray\[7\]\))}/
.source.replace(/valuesArray/g, valuesArray), "g"),
'$1 : $ === 7 ? $3 '
+ `: $ === 8 ? __fx.utils.getMaxTroops(${dict.playerData}.${dict.playerTerritories}, ${playerId}) `
+ `: __fx.utils.getDensity(${playerId}) }`);
// 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
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)`,
`=function(sE){
if (${playerId} === sE && !${gIsSingleplayer})
__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);
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)`);
{ // Add settings button, custom lobby button and win count
// add buttons
replaceRawCode(`,new nQ("☰
"+__L(),function(){aD6(3)},aa.ks),new nQ("",function(){at.d5(12)},aa.kg,!1)]`,
`,new nQ("☰
"+__L(),function(){aD6(3)},aa.ks),new nQ("",function(){at.d5(12)},aa.kg,!1),
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
replaceRawCode(`aZ.g5.vO(aD3[3].button,x+a0S+gap,a3X+h+gap,a0S,h);`,
`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);`);
// render win count
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()){
if (__fx.settings.displayWinCounter) {
const size = Math.floor(aD4.gA * 0.03);
ctx.font = ${dict.fontGeneratorFunction}(1, size);
ctx.fillStyle = "#ffffff";
const text = "Win count: " + __fx.wins.count;
const textLength = ctx.measureText(text).width;
ctx.textAlign = "left";
ctx.textBaseline = "middle";
ctx.fillText(text, ctx.canvas.width - textLength - size / 2, size);
};
ctx.imageSmoothingEnabled=!1;var iQ=a0.a4o("territorial.io"),kL=.84*aD4.gA/iQ.width;`)
/*// render gear icon and win count
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= gap - q6 / 0.7 && mouseY < jd + q6 && WindowManager.openWindow("settings"))
)`);*/
}
{ // Keybinds
// match required variables
const { 0: match, groups: { attackBarObject, setRelative } } = matchOne(/:"."===(\w+\.key)\?(?\w+)\.(?\w+)\(31\/32\):"."===\1\?\2\.\3\(32\/31\):/g,);
// 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===(?\w+)\|\|\(1<\2&&\2\*\3-\3<1\/1024\?\2=\(\3\+1\/1024\)\/\3:\2<1)/g,
"} this.setAbsolutePercentage = function(newPercentage) { $ = newPercentage; }; "
+ "__fx.keybindFunctions.setAbsolute = this.setAbsolutePercentage; "
+ `__fx.keybindFunctions.setRelative = (arg1) => ${attackBarObject}.${setRelative}(arg1); $1`);
// insert keybind handling code into the keyDown handler function
replaceOne(new RegExp(/(function \w+\((?\w+)\){)([^}]+matched)/g.source.replace(/matched/g, escapeRegExp(match)), "g"),
"$1 if (__fx.keybindHandler($.key)) return; $3");
}
// 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])
replaceOne(/(((\w+)\[\w+\])=\2\.replace\(\w+(\[\w+\]),\w+\4\))/g, "$1; if (__fx.settings.realisticNames) $3 = realisticNames;")
// Hide all links in main menu depending on settings
//replaceOne(/(this\.\w+=function\(\){)((\w+\.\w+)\[2\]=\3\[3\]=\3\[4\]=(?!this\.\w+\.\w+),)/g,
//"$1 if (settings.hideAllLinks) $3[0] = $3[1] = $; else $3[0] = $3[1] = true; $2")
// Make the main canvas context have an alpha channel if a custom background is being used
replaceOne(/(document\.getElementById\("canvasA"\),\(\w+=\w+\.getContext\("2d",){alpha:!1}/g, "$1 {alpha: __fx.makeMainMenuTransparent}")
// Clear canvas background if a custom background is being used
replaceRawCode(`,this.qk=function(){var a4n,a4m;aq.pd?(a4m=aL.gA/aq.eE,a4n=aL.gF/aq.eF,canvas.setTransform(a4m=a4n\w+)\(\){[^}]+?(?