ब्लॉग पर वापस
Guide9 मिनट पढ़ें

FiveM वेयरहाउस और स्टोरेज: स्क्रिप्ट साझा स्टैशेस

FiveM में साझा गोदाम और भंडारण डिजाइन करें। गैंग स्टैश, नौकरी लॉकर, वजन सीमाएं और ox_inventory और अधिक के लिए सर्वश्रेष्ठ भंडारण स्क्रिप्ट।

Agency Scripts

Agency Scripts के संस्थापक और प्रमुख डेवलपर

रोलप्ले सर्वरों में स्टोरेज सिस्टम

हर रोलप्ले सर्वर को बुनियादी खिलाड़ी इन्वेंटरी से परे एक मजबूत भंडारण प्रणाली की जरूरत होती है। व्यक्तिगत इन्वेंटरी की क्षमता सीमित होती है, और खिलाड़ी नौकरियों, क्राफ्टिंग, ट्रेडिंग, और लूट के माध्यम से आइटम जमा करते हैं जिन्हें वे रखना चाहते हैं लेकिन हमेशा साथ नहीं ले जा सकते। वेयरहाउस और भंडारण प्रणालियाँ इस समस्या को हल करती हैं, जो गेम दुनिया में भौतिक स्थान प्रदान करती हैं जहाँ खिलाड़ी आइटम जमा और पुनः प्राप्त कर सकते हैं। ये प्रणालियाँ कई गेमप्ले उद्देश्यों की सेवा करती हैं: व्यक्तिगत भंडारण लॉकर व्यक्तिगत खिलाड़ियों को अतिरिक्त स्थान देते हैं, संगठनात्मक वेयरहाउस गैंग और व्यवसायों को उनके संसाधनों को पूल करने देते हैं, और किराये के भंडारण इकाइयाँ एक संपत्ति बाजार बनाती हैं जो सर्वर अर्थव्यवस्था के लिए आवर्ती राजस्व उत्पन्न करती हैं। तकनीकी कार्यान्वयन को समवर्ती पहुंच, वजन और स्लॉट सीमाएं, पहुंच अनुमतियाँ, और आपके सर्वर के मौजूदा इन्वेंटरी फ्रेमवर्क के साथ एकीकरण को संभालना चाहिए।

स्टोरेज के लिए डेटाबेस स्कीमा

अपने भंडारण डेटाबेस को कई भंडारण प्रकारों का समर्थन करने के लिए डिजाइन करें जिसमें लचीला स्वामित्व और पहुँच नियंत्रण हो। प्रत्येक भंडारण इकाई को एक अद्वितीय पहचानकर्ता, एक मालिक संदर्भ जो खिलाड़ी citizenid या संगठन पहचानकर्ता हो सकता है, वजन और स्लॉट संख्या द्वारा परिभाषित क्षमता सीमाएं, और वास्तविक इन्वेंटरी डेटा JSON के रूप में सीरियलाइज़ किया गया हो, की आवश्यकता होती है। एक किराया प्रणाली तालिका शामिल करें जो किराए पर ली गई इकाइयों के भुगतान स्थिति को ट्रैक करे, जिसमें किराया देर होने पर स्वचालित लॉकआउट हो। पहुँच नियंत्रण तालिका मालिकों को अन्य खिलाड़ियों को उनकी भंडारण इकाइयों तक पहुँच की अनुमति देने देती है:

CREATE TABLE IF NOT EXISTS storage_units (
    id INT AUTO_INCREMENT PRIMARY KEY,
    unit_id VARCHAR(50) UNIQUE NOT NULL,
    unit_type ENUM('personal', 'organization', 'rental', 'property') DEFAULT 'personal',
    owner_id VARCHAR(50) NOT NULL,
    label VARCHAR(100) DEFAULT NULL,
    max_weight INT DEFAULT 100000,
    max_slots INT DEFAULT 50,
    items LONGTEXT DEFAULT '[]',
    location VARCHAR(50) NOT NULL,
    is_locked BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_owner (owner_id),
    INDEX idx_location (location),
    INDEX idx_type (unit_type)
);

CREATE TABLE IF NOT EXISTS storage_access (
    unit_id VARCHAR(50) NOT NULL,
    citizenid VARCHAR(50) NOT NULL,
    permission ENUM('view', 'deposit', 'full') DEFAULT 'deposit',
    granted_by VARCHAR(50) NOT NULL,
    granted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (unit_id, citizenid)
);

CREATE TABLE IF NOT EXISTS storage_rentals (
    unit_id VARCHAR(50) PRIMARY KEY,
    tenant_id VARCHAR(50) NOT NULL,
    rent_amount INT NOT NULL,
    rent_interval ENUM('daily', 'weekly') DEFAULT 'weekly',
    last_paid TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    next_due TIMESTAMP NOT NULL,
    is_overdue BOOLEAN DEFAULT FALSE,
    INDEX idx_tenant (tenant_id),
    INDEX idx_due (next_due)
);

वेयरहाउस स्थान कॉन्फ़िगरेशन

मानचित्र के आसपास गोदाम स्थानों को रोलप्ले संदर्भ के अनुसार परिभाषित करें। बंदरगाह के पास औद्योगिक क्षेत्र बड़े वाणिज्यिक गोदामों के लिए उपयुक्त हैं। आवासीय पड़ोस व्यक्तिगत भंडारण लॉकर के लिए उपयुक्त हैं। भूमिगत या छिपे हुए स्थान गैंग स्टैश हाउस के रूप में काम करते हैं। प्रत्येक स्थान के लिए इसकी भौतिक स्थिति, उपलब्ध भंडारण इकाइयों का प्रकार, किराए की इकाइयों के लिए मूल्य निर्धारण, और जब कोई खिलाड़ी प्रवेश करता है तो लोड होने वाले इंटीरियर शेल के लिए कॉन्फ़िगरेशन आवश्यक है। गोदाम के इंटीरियर के लिए GTA के इंटीरियर प्रॉक्सी या कस्टम MLOs का उपयोग करें ताकि खिलाड़ी भौतिक रूप से एक इमारत में चलें न कि केवल सड़क पर मेनू खोलें:

Config.StorageLocations = {
    ['industrial_1'] = {
        label = 'Elysian Island Storage',
        entrance = vector3(-96.67, -1601.77, 29.41),
        blipSprite = 473,
        blipColor = 2,
        units = {
            {id = 'ind1_small_1', type = 'rental', size = 'small', maxWeight = 50000, maxSlots = 30, rent = 500, interval = 'weekly'},
            {id = 'ind1_small_2', type = 'rental', size = 'small', maxWeight = 50000, maxSlots = 30, rent = 500, interval = 'weekly'},
            {id = 'ind1_medium_1', type = 'rental', size = 'medium', maxWeight = 150000, maxSlots = 75, rent = 1500, interval = 'weekly'},
            {id = 'ind1_large_1', type = 'rental', size = 'large', maxWeight = 300000, maxSlots = 150, rent = 3500, interval = 'weekly'},
        },
    },
    ['gang_southside'] = {
        label = 'Southside Stash',
        entrance = vector3(93.41, -1961.08, 20.82),
        blipSprite = 0,  -- No blip for hidden locations
        restrictedTo = {'ballas', 'gsf'},  -- Gang-only access
        units = {
            {id = 'gang_ss_main', type = 'organization', size = 'large', maxWeight = 500000, maxSlots = 200},
        },
    },
}

इन्वेंटरी इंटीग्रेशन

आपकी वेयरहाउस प्रणाली को आपके सर्वर द्वारा उपयोग किए जाने वाले किसी भी इन्वेंटरी फ्रेमवर्क के साथ सहजता से एकीकृत होना चाहिए, चाहे वह ox_inventory हो, qb-inventory हो, या कोई कस्टम समाधान हो। स्टोरेज UI को परिचित इन्वेंटरी इंटरफ़ेस को प्रतिबिंबित करना चाहिए ताकि खिलाड़ी सहज रूप से समझ सकें कि व्यक्तिगत इन्वेंटरी और स्टोरेज यूनिट के बीच आइटम कैसे स्थानांतरित करें। स्टैक करने योग्य आइटमों के लिए मात्रा चयन के साथ ड्रैग-एंड-ड्रॉप आइटम ट्रांसफर लागू करें। जब कोई खिलाड़ी स्टोरेज यूनिट खोलता है, तो डेटाबेस से संग्रहित आइटम लोड करें और उन्हें खिलाड़ी की व्यक्तिगत इन्वेंटरी के साथ प्रस्तुत करें। सभी आइटम मूवमेंट्स को डुप्लिकेशन एक्सप्लॉइट्स को रोकने के लिए सर्वर-साइड मान्य किया जाना चाहिए। जांचें कि स्रोत इन्वेंटरी में वास्तव में वह आइटम है जिसे स्थानांतरित किया जा रहा है, गंतव्य में वजन और स्लॉट दोनों में पर्याप्त क्षमता है, और आइटम को अनट्रेडेबल या खिलाड़ी से बंधा हुआ नहीं चिह्नित किया गया है। आइटम ट्रांसफर के लिए डेटाबेस ट्रांजेक्शंस का उपयोग करें ताकि एक इन्वेंटरी से हटाना और दूसरे में जोड़ना परमाणु रूप से हो:

RegisterNetEvent('storage:server:moveItem', function(unitId, direction, itemName, amount, fromSlot, toSlot)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    if not Player then return end

    -- Validate access
    if not HasStorageAccess(Player.PlayerData.citizenid, unitId, 'full') then
        TriggerClientEvent('QBCore:Notify', src, 'Access denied', 'error')
        return
    end

    -- Load storage unit
    local unit = GetStorageUnit(unitId)
    if not unit or unit.is_locked then
        TriggerClientEvent('QBCore:Notify', src, 'Storage is locked', 'error')
        return
    end

    amount = math.floor(tonumber(amount) or 0)
    if amount <= 0 then return end

    if direction == 'to_storage' then
        -- Player -> Storage
        local playerItem = Player.Functions.GetItemBySlot(fromSlot)
        if not playerItem or playerItem.name ~= itemName then return end
        if playerItem.amount < amount then return end

        local itemWeight = QBCore.Shared.Items[itemName].weight * amount
        local currentWeight = CalculateStorageWeight(unit.items)

        if currentWeight + itemWeight > unit.max_weight then
            TriggerClientEvent('QBCore:Notify', src, 'Storage is full (weight)', 'error')
            return
        end

        -- Atomic transfer
        Player.Functions.RemoveItem(itemName, amount, fromSlot)
        AddItemToStorage(unitId, itemName, amount, playerItem.info, toSlot)

    elseif direction == 'from_storage' then
        -- Storage -> Player
        local storageItem = GetStorageItemBySlot(unit.items, fromSlot)
        if not storageItem or storageItem.name ~= itemName then return end
        if storageItem.amount < amount then return end

        if not Player.Functions.AddItem(itemName, amount, toSlot, storageItem.info) then
            TriggerClientEvent('QBCore:Notify', src, 'Inventory full', 'error')
            return
        end

        RemoveItemFromStorage(unitId, itemName, amount, fromSlot)
    end

    -- Refresh UI for all viewers
    RefreshStorageViewers(unitId)
end)

किराया भुगतान प्रणाली

किराया भंडारण इकाइयों के लिए एक आवर्ती भुगतान प्रणाली आवश्यक है जो स्वचालित रूप से किरायेदारों से शुल्क लेती है और बकाया खातों को संभालती है। एक सर्वर-साइड अनुसूचित कार्य चलाएं जो नियमित अंतराल पर सभी किराया इकाइयों की जांच करता है, देय इकाइयों के लिए भुगतान संसाधित करता है, और बकाया इकाइयों को लॉक करता है। जब भुगतान देय हो, तो किरायेदार के बैंक खाते से किराया राशि काटने का प्रयास करें। यदि बैंक खाते में पर्याप्त धन नहीं है, तो किराया को बकाया के रूप में चिह्नित करें और खिलाड़ी को सूचना भेजें। बकाया किरायेदारों को उनकी इकाई लॉक करने से पहले कुछ दिनों की मोहलत दें। एक लॉक की गई इकाई किरायेदार को उनके संग्रहित आइटमों तक पहुँचने से रोकती है जब तक कि बकाया राशि का भुगतान न हो जाए। यदि किराया लंबी अवधि तक अदा नहीं किया जाता है, तो सामग्री नीलामी या साफ़ की जा सकती है, जो दिलचस्प द्वितीयक गेमप्ले बनाती है। एक भुगतान इतिहास लॉग लागू करें ताकि किरायेदार अपने किराया शुल्क और भुगतान तिथियों की समीक्षा संग्रह प्रबंधन इंटरफ़ेस के माध्यम से कर सकें।

संगठन और साझा भंडारण

गैंग, व्यवसाय, और सरकारी विभाग जैसे संगठन को साझा भंडारण की आवश्यकता होती है जिसे कई सदस्य उपयुक्त अनुमति स्तरों के साथ एक्सेस कर सकें। संगठन के नेता के पास पूर्ण नियंत्रण होता है और वह एक्सेस सूची में सदस्यों को जोड़ या हटा सकता है, व्यक्तिगत अनुमति स्तर सेट कर सकता है, और जमा या निकाले गए सभी आइटमों के ऑडिट लॉग देख सकता है। नियमित सदस्यों को केवल जमा करने की अनुमति हो सकती है जहां वे आइटम जोड़ सकते हैं लेकिन निकाल नहीं सकते, जो गैंग सदस्यों के लिए साझा पूल में सामग्री योगदान के लिए उपयोगी है। विश्वसनीय सदस्यों को जमा और निकासी दोनों की पूर्ण पहुंच मिलती है। एक व्यापक ऑडिट लॉग लागू करें जो साझा भंडारण में हर आइटम मूवमेंट को रिकॉर्ड करे, जिसमें कार्रवाई करने वाला खिलाड़ी, आइटम और मात्रा, और टाइमस्टैम्प शामिल हों। यह ऑडिट ट्रेल संगठन नेताओं को ट्रैक करने में मदद करता है कि कौन योगदान दे रहा है और कौन साझा पूल से चोरी कर सकता है। लॉग को स्टोरेज UI के माध्यम से देखा जा सकता है जिसमें खिलाड़ी, आइटम प्रकार, और तिथि सीमा द्वारा फ़िल्टरिंग विकल्प हों।

क्षमता अपग्रेड और स्तर

खिलाड़ियों को एक उन्नयन प्रणाली के माध्यम से अपनी भंडारण क्षमता बढ़ाने की अनुमति दें जो प्रगति प्रोत्साहन प्रदान करती है। छोटे भंडारण इकाइयों से शुरू करें जिनकी सीमित वजन और स्लॉट क्षमता होती है, फिर उन्नयन स्तर प्रदान करें जो इन सीमाओं को कीमत पर बढ़ाते हैं। प्रत्येक उन्नयन स्तर की लागत क्रमिक रूप से अधिक होनी चाहिए, जिससे सर्वर अर्थव्यवस्था के लिए एक महत्वपूर्ण धन सिंक बनता है। उन्नयन अधिकतम वजन बढ़ा सकते हैं, अतिरिक्त स्लॉट जोड़ सकते हैं, या तापमान नियंत्रित भंडारण जैसे विशेष सुविधाएँ अनलॉक कर सकते हैं जो नाशपाती वस्तुओं के लिए हैं या मजबूत सुरक्षा जो इकाई को तोड़फोड़ से सुरक्षित बनाती है। भंडारण प्रबंधन इंटरफ़ेस में वर्तमान स्तर और उपलब्ध उन्नयन स्पष्ट मूल्य निर्धारण और प्रत्येक स्तर के लाभों के साथ प्रदर्शित करें। कुछ उन्नयन स्तरों को केवल मौद्रिक लागत के बजाय उपलब्धियों या खेल समय मील के पत्थर से जोड़ने पर विचार करें, समर्पित खिलाड़ियों को प्रीमियम भंडारण लाभ प्रदान करते हुए जिन्हें वे केवल पैसे से नहीं खरीद सकते।

सुरक्षा और ब्रेक-इन मैकेनिक्स

स्टोरेज यूनिट्स को पूरी तरह से अपराध गतिविधि से सुरक्षित नहीं होना चाहिए। एक ब्रेक-इन मैकेनिक लागू करें जो खिलाड़ियों को उन स्टोरेज यूनिट्स तक पहुंचने का प्रयास करने की अनुमति देता है जिनके वे मालिक नहीं हैं, जिससे संग्रहीत कीमती वस्तुओं के लिए जोखिम पैदा होता है और हीस्ट परिदृश्य बनते हैं। ब्रेक-इन प्रक्रिया के लिए विशेष उपकरण जैसे लॉकपिक्स या इलेक्ट्रॉनिक बायपास डिवाइस की आवश्यकता होनी चाहिए, इसमें पर्याप्त समय लगे और दृश्य तथा श्रव्य संकेत हों जो आसपास के खिलाड़ियों को सचेत करें, और स्टोरेज मालिक तथा कानून प्रवर्तन को सूचना भेजे। उच्च-स्तरीय स्टोरेज यूनिट्स और सुरक्षा उन्नयन वाले यूनिट्स को तोड़ना progressively कठिन होना चाहिए, बेहतर उपकरण और अधिक समय की आवश्यकता हो। यदि ब्रेक-इन सफल होता है, तो अपराधी को अस्थायी रूप से स्टोरेज इन्वेंटरी तक पहुंच मिलती है और वह आइटम ले सकता है, लेकिन सिस्टम ब्रेक-इन को लॉग करता है और मालिक को आंशिक पहचान जानकारी जैसे सबूत प्रदान करता है जिसे पुलिस जांच सकती है। यह गोदाम छापे, जांच और परिणामों के चारों ओर एक पूर्ण गेमप्ले चक्र बनाता है जो सर्वर के अपराध और कानून प्रवर्तन गतिशीलता को समृद्ध करता है।

शुरू करने के लिए तैयार?

हमारी शॉप से स्क्रिप्ट लें, या सपोर्ट, अपडेट और आगे आने वाली चीज़ों की झलक के लिए Discord से जुड़ें।