FXclient-mirror/fx.bundle.js

2 lines
27 KiB
JavaScript

const buildTimestamp = "1752485839738"; const dictionary = {"gIsTeamGame":"he","game":"aD","playerId":"eT","playerData":"ag","playerNames":"a0N","gameState":"zo","fontSize":"fontSize","x":"eq","y":"es","canvas":"hm","gHumans":"k7","playerStates":"a39","fontGeneratorFunction":"b9.qV.sJ","rawPlayerNames":"a0S","playerBalances":"gl","playerTerritories":"gX","gLobbyMaxJoin":"wx","data":"data","playerCount":"playerCount","gBots":"kT","strs":"aAV","gIsSingleplayer":"kR","uiSizes":"bb","gap":"gap","gMaxPlayers":"eg","i":"aB","MenuManager":"aa","getState":"a10"};
(()=>{"use strict";const e=JSON.parse('{"rE":"0.6.11","_e":"Jul 14","Ao":["Fix for game update 2.09.0","Error reporting improvements"]}'),t=e=>parseFloat(e.toFixed(12));function n(e){const n=document.createElement("p");n.innerText="Attack Percentage Keybinds";const o=document.createElement("div");o.className="arrayinput";const a=document.createElement("button");a.innerText="Add",e.append(n,o,a),e.className="keybinds-input",this.container=o,this.objectKeys=["key","type","value"],this.objectArray=[],this.addObject=function(){this.objectArray.push({key:"",type:"absolute",value:.8}),this.container.appendChild(i(this.objectArray.length-1)),a.scrollIntoView(!1)},a.addEventListener("click",this.addObject.bind(this)),this.update=function(e){this.objectArray=e.attackPercentageKeybinds,this.displayObjects()},this.displayObjects=function(){if(this.container.innerHTML="",0===this.objectArray.length)return this.container.innerText="No custom attack percentage keybinds added";for(var e=0;e<this.objectArray.length;e++)this.container.appendChild(i(e))};const i=e=>{var t=document.createElement("div");this.objectKeys.forEach((n=>{t.appendChild(this.createInputField(e,n))}));var n=document.createElement("button");return n.textContent="Delete",n.addEventListener("click",this.deleteObject.bind(this,e)),t.appendChild(n),t};return this.createInputField=function(e,n){let o=document.createElement("type"===n?"select":"input");if("type"===n)o.innerHTML='<option value="absolute">Absolute</option><option value="relative">Relative</option>',o.addEventListener("change",this.updateObject.bind(this,e,n));else if("key"===n)o.type="text",o.setAttribute("readonly",""),o.setAttribute("placeholder","No key set"),o.addEventListener("click",this.startKeyInput.bind(this,e,n));else{const t="absolute"===this.objectArray[e].type;o.type=t?"text":"number",t?o.addEventListener("click",this.convertIntoNumberInput.bind(this,e,n),{once:!0}):o.setAttribute("step","0.1"),o.addEventListener("input",this.updateObject.bind(this,e,n))}return"value"===n&&"absolute"===this.objectArray[e].type?o.value=t(100*this.objectArray[e][n])+"%":o.value=this.objectArray[e][n],o},this.recreateInputField=function(e,t){this.container.children[e].children[this.objectKeys.indexOf(t)].replaceWith(this.createInputField(e,t))},this.startKeyInput=function(e,t,n){n.target.value="Press any key";const o=this.updateObject.bind(this,e,t);n.target.addEventListener("keydown",o,{once:!0}),n.target.addEventListener("blur",(()=>{n.target.removeEventListener("keydown",o),n.target.value=this.objectArray[e][t]}),{once:!0})},this.convertIntoNumberInput=function(e,t,n){n.target.value=n.target.value.slice(0,-1),n.target.type="number",n.target.addEventListener("blur",(()=>{this.recreateInputField(e,t)}),{once:!0})},this.updateObject=function(e,n,o){if(e>=this.objectArray.length)return;const a="value"===n?"absolute"===this.objectArray[e].type?t(parseFloat(o.target.value)/100):parseFloat(o.target.value):"key"===n?o.key:o.target.value;this.objectArray[e][n]=a,"key"===n?this.recreateInputField(e,n):"type"===n&&this.recreateInputField(e,"value")},this.deleteObject=function(e){this.objectArray.splice(e,1),this.displayObjects()},this}const o={count:0,removeWins:function(){confirm("Do you really want to reset your wins?")&&(o.count=0,localStorage.removeItem("fx_winCount"),alert("Successfully reset wins"))}};null!==localStorage.getItem("fx_winCount")&&(o.count=localStorage.getItem("fx_winCount"));const a=o;var i={};const s=document.getElementById("windowContainer");function l(e){i[e.name]=e,i[e.name].isOpen=!1}function r(e){!1!==i[e].isOpen&&(i[e].isOpen=!1,i[e].element.style.display="none",void 0!==i[e].onClose&&i[e].onClose())}function c(){Object.values(i).forEach((function(e){!1!==e.closable&&r(e.name)}))}document.addEventListener("mousedown",(e=>{s.contains(e.target)||c(),T().useFullscreenMode&&k()}),{passive:!0,capture:!0}),document.getElementById("canvasA").addEventListener("touchstart",c,{passive:!0}),document.addEventListener("keydown",(e=>{"Escape"===e.key&&c()}));const d={create:function(e){const t=document.createElement("div");if(e.element=t,t.className="window"+(void 0!==e.classes?" "+e.classes:" scrollable selectable"),t.style.display="none",!0===e.closeWithButton){const n=document.createElement("button");n.addEventListener("click",(()=>r(e.name))),n.textContent="Close",setTimeout((()=>t.appendChild(n)))}return s.appendChild(t),l(e),t},add:l,openWindow:function(e,...t){!0!==i[e].isOpen&&(void 0!==i[e].beforeOpen&&i[e].beforeOpen(...t),i[e].isOpen=!0,i[e].element.style.display=null)},closeWindow:r,closeAll:c},{Ao:u,rE:p}=e,h=d.create({name:"changelog",closeWithButton:!0}),m=document.createElement("h1");m.textContent="What's new";const y=document.createElement("p");y.textContent=`in FX Client v${p}`;const b=document.createElement("ul");function f(){d.openWindow("changelog")}u.forEach((e=>{const t=document.createElement("li");t.textContent=e,b.appendChild(t)})),h.append(m,y,b),window.__fx=window.__fx||{};const g=window.__fx;var v={displayWinCounter:!0,useFullscreenMode:!1,hoveringTooltip:!0,realisticNames:!1,showPlayerDensity:!0,coloredDensity:!0,densityDisplayStyle:"absoluteQuotient",hideBotNames:!1,highlightClanSpawns:!1,detailedTeamPercentage:!1,openDonationHistoryFromLb:!0,customBackgroundUrl:"",keybindButtons:!1,attackPercentageKeybinds:[]};g.settings=v;const w=["hideAllLinks","fontName"];g.makeMainMenuTransparent=!1;const E=new function(){const t=[{for:"displayWinCounter",type:"checkbox",label:"Display win counter",note:"The win counter tracks multiplayer solo wins (not in team games)"},{type:"button",text:"Reset win counter",action:a.removeWins},{for:"useFullscreenMode",type:"checkbox",label:"Use fullscreen mode",note:"Note: fullscreen mode will trigger after you click anywhere on the page due to browser policy restrictions."},{for:"hoveringTooltip",type:"checkbox",label:"Hovering tooltip",note:"Display map territory info constantly (on mouse hover) instead of only when right clicking on the map"},{for:"realisticNames",type:"checkbox",label:"Realistic Bot Names"},{for:"showPlayerDensity",type:"checkbox",label:"Show player density"},{for:"coloredDensity",type:"checkbox",label:"Colored density",note:"Display the density with a color between red and green depending on the density value"},{for:"densityDisplayStyle",type:"selectMenu",label:"Density value display style:",tooltip:"Controls how the territorial density value should be rendered",options:[{value:"percentage",label:"Percentage"},{value:"absoluteQuotient",label:"Value from 0 to 150 (BetterTT style)"}]},{for:"hideBotNames",type:"checkbox",label:"Hide bot names"},{for:"highlightClanSpawns",type:"checkbox",label:"Highlight clan spawnpoints",note:"Increases the spawnpoint glow size for members of your clan"},{for:"detailedTeamPercentage",type:"checkbox",label:"Detailed team pie chart percentage",note:"For example: this would show 25.82% instead of 26% on the pie chart in team games"},{for:"openDonationHistoryFromLb",type:"checkbox",label:"Open donation history from the leaderboard",note:"Changes whether or not clicking on a player's name in the in-game leaderboard in team games will open their donation history"},{for:"customBackgroundUrl",type:"textInput",label:"Custom main menu background:",placeholder:"Enter an image URL here",tooltip:"A custom image to be shown as the main menu background instead of the currently selected map."},n,{for:"keybindButtons",type:"checkbox",label:"Keybind buttons",note:"Show keybind buttons above the troop selector (max 6)"},function(t){const n=document.createElement("p");n.innerText=`FX Client v${e.rE}`;const o=document.createElement("p");o.innerHTML='<a href="https://discord.gg/dyxcwdNKwK" target="_blank">Discord server</a> |\n <a href="https://github.com/fxclient/FXclient#readme">Github repository</a>';const a=document.createElement("button");a.innerText="Changelog",a.addEventListener("click",f),t.append(n,o,a)}],o=document.querySelector(".settings .scrollable");var i={},s={},l=[];t.forEach((e=>{if("function"==typeof e){const t=document.createElement("div");return l.push(new e(t)),o.append(t)}const t=document.createElement("label");e.tooltip&&(t.title=e.tooltip);const n=e.type.endsWith("Input"),a=document.createElement(n||"checkbox"===e.type?"input":"selectMenu"===e.type?"select":"button");if("textInput"===e.type&&(a.type="text"),e.placeholder&&(a.placeholder=e.placeholder),(n||"selectMenu"===e.type)&&(i[e.for]=a),e.text&&(a.innerText=e.text),e.action&&a.addEventListener("click",e.action),e.label&&t.append(e.label+" "),e.note){const n=document.createElement("small");n.innerText=e.note,t.append(document.createElement("br"),n)}if(e.options&&e.options.forEach((e=>{const t=document.createElement("option");t.setAttribute("value",e.value),t.innerText=e.label,a.append(t)})),t.append(a),"checkbox"===e.type){a.type="checkbox";const n=document.createElement("span");n.className="checkmark",t.className="checkbox",t.append(n),s[e.for]=a}else t.append(document.createElement("br"));o.append(t,document.createElement("br"))})),this.save=function(){Object.keys(i).forEach((function(e){v[e]=i[e].value.trim()})),Object.keys(s).forEach((function(e){v[e]=s[e].checked})),this.applySettings(),d.closeWindow("settings"),w.forEach((e=>delete v[e])),localStorage.setItem("fx_settings",JSON.stringify(v)),window.location.reload()};const r=document.createElement("input");function c(e){const t=e.target,n=t.files[0];if(!n)return;if(t.removeEventListener("change",c),t.value="",!n.name.endsWith(".json"))return alert("Invalid file format");const o=new FileReader;o.onload=function(){let e;try{e=JSON.parse(o.result),confirm('Warning: This will override all current settings, click "OK" to confirm')&&(g.settings=v=e),localStorage.setItem("fx_settings",JSON.stringify(v)),window.location.reload()}catch(e){alert("Error\n"+e)}},o.readAsText(n)}r.type="file",this.importFromFile=function(){r.click(),r.addEventListener("change",c)},this.exportToFile=function(){var e,t,n;e=JSON.stringify(v),t=document.createElement("a"),n=new Blob([e],{type:"application/json"}),t.href=URL.createObjectURL(n),t.download="FX_client_settings.json",t.click(),URL.revokeObjectURL(t.href)},this.syncFields=function(){Object.keys(i).forEach((function(e){i[e].value=v[e]})),Object.keys(s).forEach((function(e){s[e].checked=v[e]})),l.forEach((e=>e.update?.(v)))},this.resetAll=function(){confirm("Are you Really SURE you want to RESET ALL SETTINGS back to the default?")&&(localStorage.removeItem("fx_settings"),window.location.reload())},this.applySettings=function(){""!==v.customBackgroundUrl&&(document.body.style.backgroundImage="url("+v.customBackgroundUrl+")",document.body.style.backgroundSize="cover",document.body.style.backgroundPosition="center"),g.makeMainMenuTransparent=""!==v.customBackgroundUrl},v.useFullscreenMode&&k()};function k(){null===document.fullscreenElement&&document.fullscreenEnabled&&document.documentElement.requestFullscreen({navigationUI:"hide"}).then((()=>{console.log("Fullscreen mode activated")})).catch((e=>{console.warn("Could not enter fullscreen mode:",e)}))}d.add({name:"settings",element:document.querySelector(".settings"),beforeOpen:function(){E.syncFields()}}),null!==localStorage.getItem("fx_settings")&&(g.settings=v={...v,...JSON.parse(localStorage.getItem("fx_settings"))}),E.applySettings();const x=E;function T(){return v}const L=["playerTerritories","playerBalances","rawPlayerNames"],I=["playerId","gIsTeamGame","gHumans","gLobbyMaxJoin","gameState","gIsSingleplayer"],S=e=>L.includes(e)?window[dictionary.playerData]?.[dictionary[e]]:I.includes(e)?window[dictionary.game]?.[dictionary[e]]:window[dictionary[e]],C=()=>Math.floor(window[dictionary.uiSizes]?.[dictionary.gap]??10),O=new function(){this.playersToInclude=[],this.tabLabels=["ALL","CLAN"],this.filteredLeaderboard=[],this.tabBarOffset=0,this.windowWidth=0,this.verticalClickThreshold=1e3,this.hoveringOverTabs=!1,this.scrollToTop=()=>{},this.repaintLeaderboard=()=>{},this.setUpdateFlag=()=>{},this.parseClanFromPlayerName=()=>{console.warn("parse function not set")},this.selectedTab=0,this.tabHovering=-1,this.enabled=!1,this.drawTabs=function(e,t,n,o){e.textBaseline="middle",e.textAlign="center";const a=t/this.tabLabels.length,i=n+this.tabBarOffset/2;this.tabLabels.forEach(((t,s)=>{0!==s&&e.fillRect(a*s,n,1,this.tabBarOffset),this.selectedTab===s&&(e.fillStyle=o,e.fillRect(a*s,n,a,this.tabBarOffset),e.fillStyle="rgb(255,255,255)"),this.tabHovering===s&&(e.fillStyle="rgba(255,255,255,0.3)",e.fillRect(a*s,n,a,this.tabBarOffset),e.fillStyle="rgb(255,255,255)"),e.fillText(t,a*s+a/2,i)}))},this.setHovering=(e,t)=>{let n=!1;if(e){const e=Math.floor(t/(this.windowWidth/this.tabLabels.length));this.tabHovering!==e&&(this.tabHovering=e,n=!0)}return e!==this.hoveringOverTabs&&(this.hoveringOverTabs=e,!1===e&&(this.tabHovering=-1),e||(n=!0)),n&&this.repaintLeaderboard(),e},this.handleMouseDown=e=>{const t=Math.floor(e/(this.windowWidth/this.tabLabels.length));return this.selectedTab!==t&&(this.selectedTab=t,0===this.selectedTab?this.clearFilter():1===this.selectedTab&&(this.filterByOwnClan(),this.setUpdateFlag()),this.repaintLeaderboard()),!0},this.filterByOwnClan=()=>{this.playersToInclude=[];const e=S("playerId"),t=this.parseClanFromPlayerName(S("rawPlayerNames")[e]);S("rawPlayerNames").forEach(((n,o)=>{o!==e&&this.parseClanFromPlayerName(n)!==t||this.playersToInclude.push(o)})),this.enabled=!0,this.scrollToTop()},this.clearFilter=()=>{this.enabled=!1},this.reset=()=>{this.enabled=!1,this.selectedTab=0,A.refresh()}},A=new function(){this.inOwnClan=new Array(512),this.inOwnClan.fill(!1),this.refresh=()=>{const e=S("gHumans"),t=O.parseClanFromPlayerName(S("rawPlayerNames")[S("playerId")]);null===t?this.inOwnClan.fill(!1):S("rawPlayerNames").forEach(((n,o)=>{this.inOwnClan[o]=o<e&&O.parseClanFromPlayerName(n)===t}))}};function B(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}let N=null;d.add({name:"donationHistory",element:document.querySelector("#donationhistory"),beforeOpen:function(e){document.getElementById("donationhistory_note").style.display="none"},onClose:function(){F.openedWindowPlayerID=null}});const F=new function(){this.openedWindowPlayerID=null,this.contentElement=document.querySelector("#donationhistory_content"),this.donationHistory=Array(512);let e=!1;function t(e,t,n,o){const a=S("rawPlayerNames"),i=document.createElement("tr");o&&i.setAttribute("class","new");let s=`<td><span class="color-light-gray">${t}.</span> `;return n===e[1]?s+=`Received <span class="color-green">${e[2]}</span> resources from ${B(a[e[0]])}`:s+=`Sent <span class="color-red">${e[2]}</span> resources to ${B(a[e[1]])}`,s+="</td>",i.innerHTML=s,i}this.getHistoryOf=function(t){return function(e,t){try{return e()}catch(e){throw N=t,setTimeout((()=>{null!==N&&(N=null)})),e}}((()=>this.donationHistory[t].toReversed()),{playerID:t,resetCalled:e,type:typeof this.donationHistory[t],isArray:Array.isArray(this.donationHistory[t])})},this.reset=function(){e=!0;for(var t=0;t<512;t++)this.donationHistory[t]=[]},this.logDonation=function(e,n,o){const a=[e,n,o];if(this.donationHistory[n].push(a),this.donationHistory[e].push(a),this.openedWindowPlayerID===e||this.openedWindowPlayerID===n){const o=this.donationHistory[this.openedWindowPlayerID===e?e:n].length;this.contentElement.prepend(t(a,o,this.openedWindowPlayerID,!0))}},this.displayHistory=function(e,n=S("rawPlayerNames"),o=S("gIsSingleplayer")){var a=F.getHistoryOf(e);console.log("History for "+n[e]+":"),console.log(a),document.querySelector("#donationhistory h1").innerHTML="Donation history for "+B(n[e]),this.contentElement.innerHTML="",a.length>0?a.forEach(((n,o)=>{this.contentElement.appendChild(t(n,a.length-o,e))})):this.contentElement.innerText="Nothing to display",this.openedWindowPlayerID=e,d.openWindow("donationHistory",o)}},H=F,M=new function(){const e=document.createElement("img");e.setAttribute("src","assets/players_icon.png"),document.getElementById("playerlist_content").addEventListener("click",(e=>{const t=e.target.closest("tr[data-player-id]")?.getAttribute("data-player-id");t&&S("gIsTeamGame")&&(d.closeWindow("playerList"),H.displayHistory(t))})),this.display=function(e){const t=S("gHumans"),n=S("gLobbyMaxJoin");let o=`<h3>Players (${t})</h3>`;for(let a=0;a<n;a++)a===t&&(o+=`<h3>Bots (${n-t})</h3>`),o+=`<tr data-player-id="${a}"><td><span class="color-light-gray">${a+1}.</span> ${B(e[a])}</td></tr>`;document.getElementById("playerlist_content").innerHTML=o,document.getElementById("playerlist_content").setAttribute("class",S("gIsTeamGame")?"clickable":""),d.openWindow("playerList")},this.hoveringOverButton=!1,this.drawButton=(t,n,o,a)=>{t.fillRect(n,o,a,a),t.fillStyle=this.hoveringOverButton?"#aaaaaaaa":"#000000aa",t.clearRect(n+1,o+1,a-2,a-2),t.fillRect(n+1,o+1,a-2,a-2),t.fillStyle="#ffffff",t.imageSmoothingEnabled=!0,t.drawImage(e,n+2,o+2,a-4,a-4),t.imageSmoothingEnabled=!1}};d.add({name:"playerList",element:document.getElementById("playerlist")});const P=M,W={getMaxTroops:function(e,t){return(150*e[t]).toString()},getDensity:function(e,t=S("playerBalances"),n=S("playerTerritories")){return"percentage"===T().densityDisplayStyle?(t[e]/(150*(0===n[e]?1:n[e]))*100).toFixed(1)+"%":(t[e]/(0===n[e]?1:n[e])).toFixed(1)},isPointInRectangle:function(e,t,n,o,a,i){return e>=n&&e<=n+a&&t>=o&&t<=o+i},fillTextMultiline:function(e,t,n,o,a){const i=parseInt(e.font.split(" ").find((e=>e.endsWith("px"))).slice(0,-2));t.split("\n").forEach(((t,s)=>e.fillText(t,n,o+s*i,a)))},textStyleBasedOnDensity:function(e){const t=S("playerBalances"),n=S("playerTerritories");return`hsl(${t[e]/(1.5*n[e])}, 100%, 50%, 1)`}},j=new function(){let e=!1;function t(t){if(!T().hoveringTooltip||!S("gameState")||e)return;let n,o;if(t.type.includes("touch")){const{touches:e,changedTouches:a}=t.originalEvent??t,i=e[0]??a[0];n=i.pageX,o=i.pageY}else t.type.includes("mouse")&&(n=t.clientX,o=t.clientY);e=!0;try{this.display(this.canvasPixelScale*n,this.canvasPixelScale*o)}catch(t){console.error(t)}setTimeout((()=>e=!1),100)}this.display=()=>{},this.canvasPixelScale=1,document.getElementById("canvasA").addEventListener("mousemove",t.bind(this)),document.getElementById("canvasA").addEventListener("touchstart",t.bind(this))},D={setAbsolute:()=>{},setRelative:()=>{},repaintAttackPercentageBar:()=>{}};function _(e){"absolute"===e.type?D.setAbsolute(e.value):D.setRelative(e.value),D.repaintAttackPercentageBar()}let R,U=0,J=0;const K={setSize:(e,t,n)=>{if(!0!==T().keybindButtons)return;U=e,J=t,R=document.createElement("canvas"),R.width=e,R.height=t;const o=R.getContext("2d"),a=n.font.split("px ",2)[1];o.font="bold "+t/2+"px "+a,o.textAlign="center",o.textBaseline="middle";const i=T().attackPercentageKeybinds.slice(0,6),s=C()/4,l=(e-5*s)/6;i.forEach(((e,n)=>{o.fillStyle="rgba(0, 0, 0, 0.8)",o.fillRect(n*(l+s),0,l,t),o.fillStyle="white";const a="absolute"===e.type?(100*e.value).toFixed()+"%":"x "+Math.round(100*e.value)/100;o.fillText(a,(n+.5)*(l+s),t/2)}))},click:e=>{if(e<0||e>U)return!1;const t=T().attackPercentageKeybinds,n=Math.floor(e/U*6);return!(n>=t.length||(_(t[n]),0))},draw:(e,t,n)=>{e.drawImage(R,t,n-(J+C()/4))}};let $=!1,G="",X=()=>{},q=()=>{},V=(e,t)=>{};const z=new TextEncoder,Q=new TextDecoder;d.add({name:"lobbyJoinMenu",element:document.getElementById("customLobbyJoinMenu")}),d.create({name:"customLobbiesUnavailable",closeWithButton:!0}).innerHTML='<p>The latest version of FX Client doesn\'t support custom lobbies yet. Use the stable version at <a href="https://fxclient.github.io/custom-lobbies/">https://fxclient.github.io/custom-lobbies</a></p>';const Y=d.create({name:"customLobby",classes:"scrollable selectable flex-column text-align-center",closable:!1}),Z=document.createElement("h2");Z.textContent="Custom Lobby";const ee=document.createElement("div");ee.className="customlobby-main";const te=document.createElement("div"),ne=document.createElement("p");ne.textContent="0 Players";const oe=document.createElement("div");te.append(ne,oe);const ae=document.createElement("div");ae.className="text-align-left";const ie={mode:{label:"Mode:",type:"selectMenu",options:[{value:0,label:"2 Teams"},{value:1,label:"3 Teams"},{value:2,label:"4 Teams"},{value:3,label:"5 Teams"},{value:4,label:"6 Teams"},{value:5,label:"7 Teams"},{value:6,label:"8 Teams"},{value:7,label:"Battle Royale"},{value:10,label:"No Fullsend Battle Royale"},{value:9,label:"Zombie mode"}]},map:{label:"Map:",type:"selectMenu"},difficulty:{label:"Difficulty:",type:"selectMenu",options:[{value:0,label:"Very Easy (Default)"},{value:1,label:"Easy (1v1)"},{value:2,label:"Normal"},{value:3,label:"Hard"},{value:4,label:"Very Hard"},{value:5,label:"Impossible"}]},spawnSelection:{label:"Spawn selection",type:"checkbox"},botCount:{label:"Bot & player count:",type:"numberInput",attributes:{min:"1",max:"512"}}},se={},le={};function re(e,t){"checkbox"===ie[e].type?se[e].checked=0!==t:se[e].value=t.toString(),le[e]=t}function ce(e,t){fe("options",[e,parseInt(t.target.value)])}function de(e,t){fe("options",[e,t.target.checked?1:0])}Object.entries(ie).forEach((([e,t])=>{const n=document.createElement("label");t.tooltip&&(n.title=t.tooltip);const o=t.type.endsWith("Input"),a=document.createElement(o||"checkbox"===t.type?"input":"selectMenu"===t.type?"select":"button");if(se[e]=a,"textInput"===t.type&&(a.type="text"),"numberInput"===t.type&&(a.type="number"),t.placeholder&&(a.placeholder=t.placeholder),(o||"selectMenu"===t.type)&&a.addEventListener("change",ce.bind(void 0,e)),t.text&&(a.innerText=t.text),t.action&&a.addEventListener("click",t.action),t.label&&n.append(t.label+" "),t.note){const e=document.createElement("small");e.innerText=t.note,n.append(document.createElement("br"),e)}if(t.options&&be(t.options,a),t.attributes&&Object.entries(t.attributes).forEach((([e,t])=>a.setAttribute(e,t))),n.append(a),"checkbox"===t.type){a.type="checkbox";const t=document.createElement("span");t.className="checkmark",n.className="checkbox",n.append(t),a.addEventListener("change",de.bind(void 0,e))}else n.append(document.createElement("br"));ae.append(n)})),ee.append(te,ae);const ue=document.createElement("footer");function pe(e,t){const n=document.createElement("button");return n.textContent=e,n.addEventListener("click",t),n}ue.style.marginTop="10px";const he=pe("Start game",(function(){d.closeWindow("customLobby"),fe("startGame")})),me=pe("Leave lobby",(()=>q())),ye=pe("Copy link",(()=>{navigator.clipboard.writeText(`${window.location.href}#lobby=${G}`),ye.textContent="Copied!",setTimeout((()=>ye.textContent="Copy link"),1e3)}));function be(e,t){e.forEach((e=>{const n=document.createElement("option");n.setAttribute("value",e.value),n.textContent=e.label,t.append(n)}))}function fe(e,t){const n=void 0!==t?{t:e,d:t}:{t:e},o=z.encode(JSON.stringify(n)),a=new ArrayBuffer(o.length+1);new DataView(a).setUint8(0,120),new Uint8Array(a,1).set(o),V(1,a)}ue.append(he,me,ye),Y.append(Z,ee,ue),document.getElementById("lobbyCode").addEventListener("input",(({target:e})=>{5===e.value.length&&(G=e.value.toLowerCase(),e.value="",d.closeWindow("lobbyJoinMenu"),$=!0,X())})),document.getElementById("createLobbyButton").addEventListener("click",(()=>{G="",d.closeWindow("lobbyJoinMenu"),$=!0,X()}));let ge,ve=!1,we=[];function Ee(e,t){const n=document.createElement("span");return n.textContent=e,n.className=t?"":"d-none",n}function ke(e){const t=document.createElement("div");t.className="lobby-player",t.textContent=e.name;const n=document.createElement("button");n.textContent="Kick",n.className=ve&&!e.isHost?"":"d-none",n.addEventListener("click",xe);const o=Ee("Host",e.isHost),a=Ee("In Game",e.inGame);t.append(o,a,n),oe.append(t),we.push({element:t,hostBadge:o,inGameBadge:a,kickButton:n,isHost:e.isHost,inGame:e.inGame})}function xe(e){const t=e.target;for(let e=0;e<we.length;e++)if(we[e].kickButton===t){fe("kick",e);break}}function Te(){ne.textContent=`${we.length} Player${1===we.length?"":"s"}`}function Le(e){if(window.location.hash.startsWith("#lobby="))return d.openWindow("customLobbiesUnavailable")}window.addEventListener("hashchange",(()=>Le()));const Ie={gameInfo:le,showJoinPrompt:function(){return d.openWindow("customLobbiesUnavailable")},isCustomMessage:function(e){if(120!==e[0])return!1;if(1===e.length)return!0;const t=new Uint8Array(e.buffer,1),n=JSON.parse(Q.decode(t)),{t:o,d:a}=n;if("lobby"===o)d.openWindow("customLobby"),Z.textContent="Custom Lobby "+a.code,G=a.code,ve=a.isHost,he.disabled=!ve,ve?ae.classList.remove("disabled"):ae.classList.add("disabled"),Object.entries(a.options).forEach((([e,t])=>re(e,t))),i=a.players,s=a.id,we=[],oe.innerHTML="",i.forEach(ke),ge=we[s],Te();else if("addPlayer"===o)ke({name:a.name,inGame:!1,isHost:!1}),Te();else if("removePlayer"===o){const e=a;we[e].element.remove(),we.splice(e,1),Te()}else if("inLobby"===o){const e=a;we[e].inGame=!1,we[e].inGameBadge.className="d-none"}else if("options"===o){const[e,t]=a;re(e,t)}else if("setHost"===o){const e=a;we[e].isHost=!0,we[e].hostBadge.className=""}else"host"===o?(ve=!0,he.disabled=!1,ae.classList.remove("disabled"),we.forEach((e=>{e.isHost||(e.kickButton.className="")}))):"serverMessage"===o&&alert(a);var i,s;return!0},getSocketURL:function(){return"wss://fx.peshomir.workers.dev/"+(""===G?"create":"join?"+G)},getPlayerId:function(){let e=0;for(let t=0;t<we.length;t++){const n=we[t];if(n===ge)return e;!1===n.inGame&&e++}},setJoinFunction:function(e){X=e,setTimeout(Le,0)},setLeaveFunction:function(e){q=e},setSendFunction:function(e){V=e},setMapInfo:function(e){setTimeout((()=>be(e.map(((e,t)=>({value:t.toString(),label:e.name}))),se.map)),0)},rejoinLobby:function(){X()},hideWindow:function(){d.closeWindow("customLobby")},isActive:()=>$,setActive:function(e){$=e,!1===e&&d.closeWindow("customLobby")}},{rE:Se,_e:Ce}=e;"serviceWorker"in navigator&&(navigator.serviceWorker.addEventListener("message",(e=>{const t=e.data;"activate"===t.event&&buildTimestamp!==t.version&&(document.getElementById("updateNotification").style.display="block")})),navigator.serviceWorker.register("./sw.js"));const Oe=localStorage.getItem("fx_version");Oe!==Se&&(localStorage.setItem("fx_version",Se),null!==Oe&&f()),window.__fx=window.__fx||{};const Ae=window.__fx;Ae.version=Se+" "+Ce,Ae.settingsManager=x,Ae.leaderboardFilter=O,Ae.utils=W,Ae.WindowManager=d,Ae.keybindFunctions=D,Ae.keybindHandler=e=>{const t=T().attackPercentageKeybinds.find((t=>t.key===e));return void 0!==t&&(0!==S("gameState")&&_(t),!0)},Ae.mobileKeybinds=K,Ae.donationsTracker=H,Ae.reportError=function(e,t){function n(e){try{return S(e)}catch(e){return e.toString()}}t=e.filename+" "+e.lineno+" "+e.colno+" "+e.message+"\n"+t,fetch("https://fx.peshomir.workers.dev/stats/errors",{body:JSON.stringify({message:t,context:{debug:N,gameState:n("gameState"),singleplayer:n("gIsSingleplayer"),swState:navigator.serviceWorker?.controller?.state,location:window.location.toString(),userAgent:navigator.userAgent,dictionary:JSON.stringify(dictionary),buildTimestamp,scripts:Array.from(document.scripts).map((e=>e.src))}}),method:"POST"}).catch((e=>alert("Failed to report error: "+e)))},Ae.playerList=P,Ae.hoveringTooltip=j,Ae.clanFilter=A,Ae.wins=a,Ae.customLobby=Ie,console.log("Successfully loaded FX Client")})();