Enhanced Bank Sorting for flatmmmo.com

Add better sorting features to bank storage

当前为 2025-08-01 提交的版本,查看 最新版本

// ==UserScript==
// @name         Enhanced Bank Sorting for flatmmmo.com
// @namespace    http://tampermonkey.net/
// @version      2.6.1
// @description  Add better sorting features to bank storage
// @author       Carlos
// @match        https://flatmmo.com/play.php
// @match        https://flatmmo.com/play.php*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    console.log('Enhanced Bank Sorting script loaded!');

    let original_bank_items = [];
    let current_sort_method = 'original';
    let isSorting = false;

    function init() {
        if (typeof bank_items === 'undefined' || typeof refresh_bank !== 'function') {
            setTimeout(init, 500);
            return;
        }

        if (original_bank_items.length === 0 && bank_items.length > 0) {
            original_bank_items = [...bank_items];
        }

        addSortingControls();
    }

    function addSortingControls() {
        const storageWrapper = document.querySelector('.storage-wrapper');
        if (!storageWrapper) {
            setTimeout(addSortingControls, 500);
            return;
        }

        if (document.getElementById('sorting-controls')) return;

        const sortingControls = document.createElement('div');
        sortingControls.id = 'sorting-controls';
        sortingControls.style.cssText = `
            margin: 10px 0;
            padding: 15px;
            background: rgba(255,255,255,0.1);
            border: 1px solid #555;
            border-radius: 5px;
            display: flex;
            gap: 15px;
            flex-wrap: wrap;
            align-items: center;
        `;

        const sortLabel = document.createElement('span');
        sortLabel.textContent = 'Sort by: ';
        sortLabel.style.cssText = `
            color: white;
            font-weight: bold;
            font-size: 14pt;
        `;

        const buttonContainer = document.createElement('div');
        buttonContainer.style.cssText = `
            display: flex;
            gap: 8px;
            flex-wrap: wrap;
        `;

        const sortOptions = [
            { id: 'original', text: 'Original', method: sortByOriginal },
            { id: 'name-asc', text: 'Name A-Z', method: () => sortByName(false) },
            { id: 'name-desc', text: 'Name Z-A', method: () => sortByName(true) },
            { id: 'amount-high', text: 'Amount ↓', method: () => sortByAmount(true) },
            { id: 'amount-low', text: 'Amount ↑', method: () => sortByAmount(false) },
            { id: 'type', text: 'Type', method: sortByType }
        ];

        sortOptions.forEach(option => {
            const button = document.createElement('button');
            button.id = `sort-${option.id}`;
            button.textContent = option.text;
            button.style.cssText = `
                padding: 8px 12px;
                border: 1px solid #666;
                border-radius: 3px;
                background-color: #333;
                color: white;
                cursor: pointer;
                font-size: 11pt;
                font-family: Courier;
                transition: all 0.2s;
            `;

            button.addEventListener('mouseenter', function () {
                if (current_sort_method !== option.id) {
                    this.style.backgroundColor = '#555';
                }
            });

            button.addEventListener('mouseleave', function () {
                if (current_sort_method !== option.id) {
                    this.style.backgroundColor = '#333';
                }
            });

            button.addEventListener('click', function () {
                if (current_sort_method === option.id) return;

                document.querySelectorAll('[id^="sort-"]').forEach(btn => {
                    btn.style.backgroundColor = '#333';
                    btn.style.borderColor = '#666';
                });

                this.style.backgroundColor = '#555';
                this.style.borderColor = '#888';

                current_sort_method = option.id;
                resetBankItems();
                option.method();
            });

            buttonContainer.appendChild(button);
        });

        setTimeout(() => {
            const btn = document.getElementById('sort-original');
            if (btn) {
                btn.style.backgroundColor = '#555';
                btn.style.borderColor = '#888';
            }
        }, 100);

        sortingControls.appendChild(sortLabel);
        sortingControls.appendChild(buttonContainer);

        const searchInput = storageWrapper.querySelector('input[type="text"]');
        if (searchInput && searchInput.parentNode) {
            searchInput.parentNode.insertBefore(sortingControls, searchInput.nextSibling);
        } else {
            storageWrapper.insertBefore(sortingControls, storageWrapper.firstChild);
        }
    }

    function resetBankItems() {
        bank_items.splice(0, bank_items.length, ...original_bank_items);
    }

    function sortByOriginal() {
        isSorting = true;
        resetBankItems();
        originalRefreshBank();
        isSorting = false;
    }

    function sortByName(reverse = false) {
        isSorting = true;
        resetBankItems();
        bank_items.sort((a, b) => {
            const nameA = a.name.toLowerCase();
            const nameB = b.name.toLowerCase();
            return reverse ? nameB.localeCompare(nameA) : nameA.localeCompare(nameB);
        });
        originalRefreshBank();
        isSorting = false;
    }

    function sortByAmount(highToLow = true) {
        isSorting = true;
        resetBankItems();
        bank_items.sort((a, b) => highToLow ? b.value - a.value : a.value - b.value);
        originalRefreshBank();
        isSorting = false;
    }

    function sortByType() {
        isSorting = true;
        resetBankItems();

        const itemCategories = {
            arrows: ['arrow', 'heads'],
            armor: ['helmet', 'body', 'legs', 'boots', 'gloves', 'mask', 'hat', 'top', 'skirt'],
            bars: ['_bar', 'promethium', 'gold', 'silver', 'iron', 'bronze', 'copper'],
            containers: ['bucket', 'vial'],
            food_cooked: ['cooked_', 'cake', 'bread'],
            food_raw: ['raw_', 'milk_bucket', 'wheat', 'sugarcane', 'banana'],
            gems: ['diamond', 'ruby', 'emerald', 'sapphire', 'crystal', 'gemstone'],
            jewelry: ['necklace', 'ring', 'sigil'],
            leaves: ['leaf'],
            materials: ['fur', 'hide', 'skin', 'silk', 'coal', 'string', 'feathers', 'nails', 'glass', 'bones', 'bonemeal', 'matches', 'algae'],
            misc: [],
            mushrooms: ['mushroom', 'shroom', 'fireshroom', 'moldshroom', 'seashroom', 'rockshroom', 'green_mushroom', 'blue_mushroom', 'spirit_mushroom', 'red_mushroom'],
            orbs: ['orb'],
            potions: ['potion'],
            seeds: ['seeds'],
            tools: ['pickaxe', 'axe', 'shovel', 'fishing_rod', 'bonecrusher'],
            trees: ['logs', 'plank'],
            weapons: ['sword', 'bow', 'staff', 'knife', 'mace', 'club', 'harpoon']
        };

        function getItemType(name) {
            const lower = name.toLowerCase();
            for (const [type, keywords] of Object.entries(itemCategories)) {
                if (type === 'misc') continue;
                if (keywords.some(keyword => lower.includes(keyword))) {
                    return type;
                }
            }
            return 'misc';
        }

        bank_items.sort((a, b) => {
            const typeA = getItemType(a.name);
            const typeB = getItemType(b.name);
            if (typeA !== typeB) return typeA.localeCompare(typeB);
            return a.name.localeCompare(b.name);
        });

        originalRefreshBank();
        isSorting = false;
    }

    const originalRefreshBank = window.refresh_bank;
    window.refresh_bank = function () {
        if (isSorting) {
            originalRefreshBank.apply(this, arguments);
            return;
        }

        if (bank_items.length > 0 && original_bank_items.length === 0 && current_sort_method === 'original') {
            original_bank_items = [...bank_items];
        }

        originalRefreshBank.apply(this, arguments);

        setTimeout(() => {
            if (current_sort_method === 'original') {
                original_bank_items = [...bank_items];
            } else {
                // Do NOT update original_bank_items when sorted
                switch (current_sort_method) {
                    case 'name-asc': sortByName(false); break;
                    case 'name-desc': sortByName(true); break;
                    case 'amount-high': sortByAmount(true); break;
                    case 'amount-low': sortByAmount(false); break;
                    case 'type': sortByType(); break;
                }
            }
        }, 50);
    };

    init();

    const originalIsBank = window.is_bank_open;
    if (originalIsBank) {
        setInterval(() => {
            if (is_bank_open() && !document.getElementById('sorting-controls')) {
                addSortingControls();
            }
        }, 1000);
    }
})();