- // ==UserScript==
- // @name IdlePixel+ New Card Interface
- // @namespace lbtechnology.info
- // @version 1.2.2
- // @description Improved interface for opening new cards, receiving cards in trade & trading cards
- // @author Zlef
- // @license MIT
- // @match *://idle-pixel.com/login/play*
- // @grant none
- // @icon https://d1xsc8x7nc5q8t.cloudfront.net/images/tcg_back_50.png
- // @require https://greasyfork.org/scripts/441206-idlepixel/code/IdlePixel+.js?anticache=20220905
- // ==/UserScript==
-
- (function() {
- 'use strict';
-
- class TCGRevamp extends IdlePixelPlusPlugin {
- constructor() {
- super("TCG Interface Changes", {
- about: {
- name: GM_info.script.name,
- version: GM_info.script.version,
- author: GM_info.script.author,
- description: GM_info.script.description
- }
- });
-
- this.showPopup = false;
- this.messageStart = "You got a"
- this.trade = false;
- this.card = "";
- this.refreshTCG = "";
- this.currentPopup = null;
- this.savedUsernamesTCG = null;
- this.previousTradeUsername = null;
- this.loadUsernames();
-
-
- this.overlay = document.createElement('div');
- this.overlay.id = 'newCardOverlay';
- this.overlay.style.position = 'fixed';
- this.overlay.style.top = '0';
- this.overlay.style.left = '0';
- this.overlay.style.width = '100%';
- this.overlay.style.height = '100%';
- this.overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
- this.overlay.style.zIndex = '1000';
- this.overlay.style.display = 'flex';
- this.overlay.style.justifyContent = 'center';
- this.overlay.style.alignItems = 'center';
- }
-
- onLogin() {
- this.originalTcgGiveCard = Modals.open_tcg_give_card;
-
- Modals.open_tcg_give_card = (modal_id, card) => {
- if (!modal_id) {
- this.newTradePopup(card);
- } else {
- this.originalTcgGiveCard(modal_id, card);
- }
- };
-
-
- if (!CardData.data) {
- CardData.fetchData();
- }
- this.monitorRevealTCG();
- }
-
- saveUsernames(){
- const saveData = JSON.stringify({usernames: this.savedUsernamesTCG});
- localStorage.setItem(`savedUsernamesTCG`, saveData)
-
- }
-
- loadUsernames(){
- const savedUsernamesTCG = localStorage.getItem(`savedUsernamesTCG`)
-
- if (savedUsernamesTCG){
- this.savedUsernamesTCG = JSON.parse(savedUsernamesTCG).usernames
- } else {
- this.savedUsernamesTCG = [];
- }
-
- }
-
- monitorRevealTCG() {
- const originalWebSocketSend = WebSocket.prototype.send;
- const self = this;
- WebSocket.prototype.send = function(data) {
- try {
- originalWebSocketSend.call(this, data);
- if (data === 'REVEAL_TCG_CARD') {
- self.showPopup = true;
- }
- } catch (error) {
- console.error('Error in overridden WebSocket send:', error);
- }
- };
- }
-
- onMessageReceived(data){
- const originalOpenImageModal = Modals.open_image_modal;
- const self = this;
-
- if (data.includes("OPEN_DIALOGUE")){
- Modals.open_image_modal = function(title, imgUrl, description, footerText, closeBtnText, anotherBtnText, isModalDismissible) {
-
- if (description.includes("You were given a card from")) {
-
- const usernameRegex = /You were given a card from (.*?)<br \/>/;
- const cardRegex = /<span class='color-grey'>(.*?)<\/span>/;
-
- const usernameMatch = description.match(usernameRegex);
- const cardMatch = description.match(cardRegex);
-
- let username = "";
- let card = "";
-
- if (usernameMatch && usernameMatch.length > 1) {
- username = usernameMatch[1];
- }
-
- if (cardMatch && cardMatch.length > 1) {
- self.card = cardMatch[1]
- }
-
-
- self.messageStart = `${username} sent you a`
- self.trade = true;
- self.showPopup = true;
- } else {
- originalOpenImageModal.call(this, title, imgUrl, description, footerText, closeBtnText, anotherBtnText, isModalDismissible);
- }
- }
- }
-
- if (data.includes("REFRESH_TCG")){
- this.refreshTCG = data;
- if (this.showPopup){
- if (this.trade){
- this.getCardInfo();
- // this.trade = false;
- this.card = "";
- } else {
- this.getCardInfo();
- }
-
- this.showPopup = false;
- this.messageStart = "You got a"
- }
- }
- }
-
- getCardInfoTrade(cardid) {
- const cardData = this.refreshTCG.replace('REFRESH_TCG=', '').split('~');
- // cardData looks like this: [ "21882", "tcg_thief_icon", "false", "21881", "tcg_raw_swordfish", "false", "21880", "tcg_raw_tuna", "false", "21805", … ]
- const index = cardData.indexOf(cardid);
- const isThisYourCard = [cardData[index], cardData[index + 1], cardData[index + 2]];
-
- const isHolo = isThisYourCard[2] === 'true';
- const cardHTML = CardData.getCardHTML(isThisYourCard[0], isThisYourCard[1], isHolo);
- return cardHTML;
-
- }
-
- updateUserListDisplay() {
- // Clear existing contents
- this.userListContainer.innerHTML = '';
-
- // Create table
- const table = document.createElement('table');
- table.className = 'table table-hover';
-
- // Table header
- const thead = document.createElement('thead');
- thead.innerHTML = '<tr><th scope="col">Saved users</th><th scope="col"></th></tr>';
- table.appendChild(thead);
-
- // Table body
- const tbody = document.createElement('tbody');
- table.appendChild(tbody);
-
- const usernames = this.savedUsernamesTCG;
- const minimumRows = 0; // Tested leaving blank rows, didn't like.
- const rowsToCreate = Math.max(minimumRows, usernames.length);
-
- // Everything else (I cba to comment atm)
- for (let i = 0; i < rowsToCreate; i++) {
- const tr = document.createElement('tr');
- const usernameCell = document.createElement('td');
-
- usernameCell.style.cursor = 'pointer';
- usernameCell.style.verticalAlign = 'middle';
- usernameCell.style.fontSize = '1.2em';
- usernameCell.addEventListener('click', () => {
- const usernameInput = document.getElementById('recipientUsernameInput');
- if (usernameInput) {
- usernameInput.value = usernames[i];
- }
- });
-
- const actionCell = document.createElement('td');
- actionCell.align = "right";
- actionCell.style.width = '80px';
-
- if (i < usernames.length) {
- usernameCell.textContent = usernames[i];
- const deleteButton = document.createElement('button');
- deleteButton.textContent = 'Delete';
- deleteButton.className = 'btn btn-danger btn-sm';
- deleteButton.style.padding = '5px 10px';
- deleteButton.style.height = 'auto';
- deleteButton.onclick = () => this.deleteUsername(usernames[i]);
- actionCell.appendChild(deleteButton);
- }
-
- tr.appendChild(usernameCell);
- tr.appendChild(actionCell);
- tbody.appendChild(tr);
- }
-
- this.userListContainer.appendChild(table);
- }
-
- deleteUsername(username) {
- const index = this.savedUsernamesTCG.indexOf(username);
- if (index !== -1) {
- this.savedUsernamesTCG.splice(index, 1);
- this.saveUsernames();
- this.updateUserListDisplay();
- }
- }
-
-
- newTradePopup(card) {
- const cardHTML = this.getCardInfoTrade(card).replace(/onclick='[^']+'/g, '');
-
- // tradePopup CSS
- const tradePopupStyles = `
- <style>
- #tradePopup {
- display: flex;
- flex-direction: column;
- align-items: center;
- width: 100%; /* Full width */
- max-width: 800px; /* Match the paint doodle's width */
- margin: 0 auto; /* Center the popup */
- background-color: #fff; /* White background */
- border-radius: 8px; /* Rounded corners */
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); /* Box shadow for some depth */
- padding: 20px; /* Padding around the content */
- box-sizing: border-box; /* Ensures padding is included in width */
- }
- #tradePopup .tradePopup-row {
- display: flex;
- width: 100%;
- }
- #tradePopup .tradePopup-col {
- flex: 1; /* Each column takes up equal space */
- box-sizing: border-box; /* Ensures padding is included in width */
- }
- #tradePopup .tradePopup-card-container {
- flex: none;
- width: 35%;
- }
- #tradePopup .tradePopup-button-container {
- display: flex;
- justify-content: right;
- width: 100%; /* Full width of the popup */
- }
- #tradePopup button {
- padding: 10px 20px; /* Padding inside the buttons */
- cursor: pointer; /* Pointer cursor on hover */
- margin-right: 10px;
- }
- #userListContainer {
- max-height: 230px; /* Adjust to the desired max-height */
- overflow-y: auto; /* Enables scrollbar when content overflows */
- }
- </style>
- `;
- // Add the tradePopup styles to the document head
- document.head.insertAdjacentHTML('beforeend', tradePopupStyles);
-
- // Element setup
- const popupBox = document.createElement('div');
- popupBox.id = 'tradePopup';
-
- // Create a row to contain columns
- const rowDiv = document.createElement('div');
- rowDiv.className = 'tradePopup-row';
- popupBox.appendChild(rowDiv);
-
- // Column for the card
- const cardColDiv = document.createElement('div');
- cardColDiv.className = 'tradePopup-col tradePopup-card-container'; // Bootstrap column class
- rowDiv.appendChild(cardColDiv);
-
- // Column for the transaction form
- const formColDiv = document.createElement('div');
- formColDiv.className = 'tradePopup-col'; // Bootstrap column class
- rowDiv.appendChild(formColDiv);
-
- // Card container
- const cardContainer = document.createElement('div');
- cardContainer.innerHTML = cardHTML; // Insert the card HTML
- cardColDiv.appendChild(cardContainer);
-
- // Modal title
- const title = document.createElement('h5');
- title.textContent = "Who do you want to send this card to?";
- title.className = "modal-title";
- formColDiv.appendChild(title);
-
- // Input group for username and add user button
- const inputGroup = document.createElement('div');
- inputGroup.className = 'input-group mb-3';
-
- // Create input for username
- const usernameInput = document.createElement('input');
- usernameInput.type = 'text';
- usernameInput.className = 'form-control';
- usernameInput.id = 'recipientUsernameInput';
- usernameInput.placeholder = 'Enter username';
- if (this.previousTradeUsername){
- usernameInput.value = this.previousTradeUsername;
- }
-
- // Append input to input group
- inputGroup.appendChild(usernameInput);
-
- // Add User button next to the input
- const addUserButton = document.createElement('button');
- addUserButton.textContent = 'SAVE USER';
- addUserButton.className = 'btn btn-secondary';
- addUserButton.type = 'button';
-
- inputGroup.appendChild(addUserButton);
- formColDiv.appendChild(inputGroup);
-
-
- // User list container TODO
- this.userListContainer = document.createElement('div');
- this.userListContainer.id = 'userListContainer';
- formColDiv.appendChild(this.userListContainer);
- this.updateUserListDisplay();
-
- // Buttons
- const sendCardButton = document.createElement('button');
- sendCardButton.textContent = 'SEND CARD';
- sendCardButton.className = 'btn btn-primary';
- sendCardButton.type = 'button';
-
- const closeButton = document.createElement('button');
- closeButton.textContent = 'CLOSE';
- closeButton.className = 'btn btn-secondary';
- closeButton.type = 'button';
-
- // Buttons container
- const buttonContainer = document.createElement('div');
- buttonContainer.className = 'tradePopup-button-container';
- buttonContainer.appendChild(sendCardButton);
- buttonContainer.appendChild(closeButton);
- popupBox.appendChild(buttonContainer);
-
- // Define button actions
- const actions = [
- {
- button: sendCardButton,
- handler: () => {
- const recipientUsername = usernameInput.value.trim();
- this.previousTradeUsername = recipientUsername;
- IdlePixelPlus.sendMessage(`GIVE_TCG_CARD=${recipientUsername}~${card}`);
- }
- },
- {
- button: closeButton,
- handler: () => {
- // Can be left blank
- },
- closeOnAction: true
- },
- {
- button: addUserButton,
- handler: () => {
- const username = usernameInput.value;
- if (username && !this.savedUsernamesTCG.includes(username)) {
- this.savedUsernamesTCG.push(username);
- this.saveUsernames();
- this.updateUserListDisplay();
- }
- },
- closeOnAction: false
- }
- ];
-
-
- this.launchPopup(popupBox, actions);
- }
-
- getCardInfo() {
- const cardData = this.refreshTCG.replace('REFRESH_TCG=', '').split('~');
- let isHolo = 'false';
-
- if (this.trade) {
- const cardName = this.card.replace(/ \(holo\)$/, '');
- const index = cardData.indexOf(cardName);
- if (index !== -1) {
- const id = cardData[index - 1];
- const nameKey = cardData[index];
- const holo = cardData[index + 1];
- isHolo = this.card.includes("(holo)") ? 'true' : holo;
- this.displayNewCard(id, nameKey, isHolo);
- }
- } else {
- // Default to the first card for non trade
- if (cardData.length >= 3) {
- const id = cardData[0];
- const nameKey = cardData[1];
- isHolo = cardData[2];
- this.displayNewCard(id, nameKey, isHolo);
- }
- }
- }
-
- displayNewCard(cardId, cardNameKey, holo) {
- const cardName = cardNameKey.replace('tcg_', '').replace(/_/g, ' ').replace(" icon", "");
- const isHolo = holo === 'true';
- let bloodyVowels = "";
-
- const vowels = ['a', 'e', 'i', 'o', 'u'];
- if (vowels.some(vowel => cardName.toLowerCase().startsWith(vowel))) {
- bloodyVowels = "n";
- }
-
- const message = isHolo ? `${this.messageStart} holo ${cardName} card!` : `${this.messageStart}${bloodyVowels} ${cardName} card!`;
-
- const cardHTML = CardData.getCardHTML(cardId, cardNameKey, isHolo);
-
- this.newCardOverlay(message, cardHTML);
-
- }
-
- newCardOverlay(message, cardHTML) {
- // Element setup
- const popupBox = document.createElement('div');
- popupBox.id = 'newCardPopupBox';
- popupBox.style.width = '300px';
- popupBox.style.margin = '0 auto';
- popupBox.style.backgroundColor = '#fff';
- popupBox.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.5)';
- popupBox.style.borderRadius = '8px';
- popupBox.style.padding = '20px';
- popupBox.style.textAlign = 'center';
-
- const messageP = document.createElement('p');
- messageP.textContent = message;
- messageP.style.fontSize = '18px';
- messageP.style.fontWeight = 'bold';
-
- const cardContainer = document.createElement('div');
- cardContainer.innerHTML = cardHTML;
- cardContainer.firstChild.style.marginTop = '0px';
-
- const cardTitle = cardContainer.querySelector('.tcg-card-title');
- const cardInnerText = cardContainer.querySelector('.tcg-card-inner-text');
- if (cardTitle) {
- cardTitle.style.textAlign = 'left';
- }
- if (cardInnerText) {
- cardInnerText.style.textAlign = 'left';
- }
-
- const openAnotherButton = document.createElement('button');
- openAnotherButton.textContent = 'OPEN ANOTHER';
- openAnotherButton.style.padding = '10px 20px';
- openAnotherButton.style.fontSize = '16px';
- openAnotherButton.style.cursor = 'pointer';
- openAnotherButton.style.marginRight = '10px';
-
- const tcg_unknown = IdlePixelPlus.getVarOrDefault("tcg_unknown", 0, "int");
- openAnotherButton.disabled = tcg_unknown == 1; // was but never fully tested to understand wtf was going on (var might not update quickly enough, would explain why I went with 1?) <=1
-
- const closeButton = document.createElement('button');
- closeButton.textContent = 'CLOSE';
- closeButton.style.padding = '10px 20px';
- closeButton.style.fontSize = '16px';
- closeButton.style.cursor = 'pointer';
-
- // Define button actions
- const actions = [
- {
- button: openAnotherButton,
- handler: () => {
- IdlePixelPlus.sendMessage("REVEAL_TCG_CARD");
- }
- },
- {
- button: closeButton,
- handler: () => {
- },
- closeOnAction: true // True by default but stated for future reference
- }
- ];
-
- // Append elements to main popup
- popupBox.appendChild(messageP);
- popupBox.appendChild(cardContainer);
- if (!this.trade) {
- popupBox.appendChild(openAnotherButton);
- }
- popupBox.appendChild(closeButton);
- this.trade = false;
-
- this.launchPopup(popupBox, actions);
- }
-
- launchPopup(popup, actions) {
-
- if (this.currentPopup) {
- this.overlay.removeChild(this.currentPopup);
- this.currentPopup = null;
- }
-
- this.currentPopup = popup;
-
- this.overlay.appendChild(popup);
- document.body.appendChild(this.overlay);
-
- const adjustPopupPosition = () => {
- const viewportHeight = window.innerHeight;
- const popupHeight = popup.offsetHeight;
- const scrollOffset = window.pageYOffset || document.documentElement.scrollTop;
- const topPosition = (viewportHeight - popupHeight) / 2 + scrollOffset;
- popup.style.position = 'absolute';
- popup.style.top = `${topPosition > 0 ? topPosition : 0}px`;
- };
-
- adjustPopupPosition();
- // window.addEventListener('scroll', adjustPopupPosition);
- window.addEventListener('resize', adjustPopupPosition);
-
-
- // Apply actions (button clicks)
- actions.forEach(action => {
- const button = action.button;
- button.addEventListener('click', () => {
- action.handler();
- // Only remove the overlay if specified by the action
- if (action.closeOnAction !== false) {
- document.body.removeChild(this.overlay);
- window.removeEventListener('resize', adjustPopupPosition);
- }
- });
- });
-
- this.overlay.addEventListener('click', (event) => {
- if (event.target === this.overlay) {
- document.body.removeChild(this.overlay);
- window.removeEventListener('resize', adjustPopupPosition);
- }
- });
-
- popup.addEventListener('click', (event) => {
- event.stopPropagation();
- });
-
- this.oldpopup = popup.id;
- }
-
- }
-
- const plugin = new TCGRevamp();
- IdlePixelPlus.registerPlugin(plugin);
-
- })();