local Q=game:GetService("\080\108\097\121\101\114\115")local h=game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")local N=game:GetService("\077\097\114\107\101\116\112\108\097\099\101\083\101\114\118\105\099\101")local H=require((h:WaitForChild("\080\114\111\106\101\099\116")):WaitForChild("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101"))local O=(require((h:WaitForChild("\080\114\111\106\101\099\116")):WaitForChild("\083\101\114\118\101\114\083\099\114\105\112\116\083\101\114\118\105\099\101"))):GetContext(script)local U=H:GetResource("\071\097\109\101\068\097\116\097\046\073\116\101\109\046\083\116\111\114\101")local T=H:GetResource("\071\097\109\101\082\101\112\108\105\099\097\116\105\111\110")local J=(H:GetResource("\069\120\116\101\114\110\097\108\085\116\105\108\046\078\101\120\117\115\073\110\115\116\097\110\099\101\046\078\101\120\117\115\073\110\115\116\097\110\099\101")):Extend()J:SetClassName("\083\116\111\114\101\083\101\114\118\105\099\101")O:SetContextResource(J)local t=O:GetResource("\083\101\114\118\105\099\101\046\073\110\118\101\110\116\111\114\121\083\101\114\118\105\099\101")local P=O:GetResource("\083\101\114\118\105\099\101\046\080\108\097\121\101\114\068\097\116\097\083\101\114\118\105\099\101")local b=Instance.new("\070\111\108\100\101\114")b.Name="\083\116\111\114\101\082\101\112\108\105\099\097\116\105\111\110"b.Parent=T local B=Instance.new("\082\101\109\111\116\101\070\117\110\099\116\105\111\110")B.Name="\080\117\114\099\104\097\115\101\073\116\101\109"B.Parent=b B.OnServerInvoke=function(Q,h)return J:PurchaseItemWithCoins(Q,h)end function J.CompleteTransaction(N,Q,h)local H=U[h]if not H then return false end local O=t:GetInventory(Q)local T=P:GetPlayerData(Q)if H.CanPurchase and not H.CanPurchase(Q)then return false end if H.Type=="\073\116\101\109"then if not O:GetNextOpenSlot()then return false end if H.AllowMultiple~=true and#O:GetItemSlots(H.ItemName)>0 then return false end elseif H.Type=="\080\101\116"then if(T:GetValue("\080\101\116\115\079\119\110\101\100"))[H.Name]then return false end end if H.HandlePurchase then H.HandlePurchase(Q)elseif H.Type=="\073\116\101\109"then t:AddItem(Q,H.ItemName)elseif H.Type=="\080\101\116"then local Q=T:GetValue("\080\101\116\115\079\119\110\101\100")Q[H.Name]=true T:SetValue("\080\101\116\115\079\119\110\101\100",Q)elseif H.Type=="\067\097\110\100\121"then T:SetValue("\067\117\114\114\101\110\099\121",T:GetValue("\067\117\114\114\101\110\099\121")+H.CandyAmount)end return true end function J.PurchaseItemWithCoins(N,Q,h)local H=U[h]if not H then return false end if not H.CostCandy then return false end local O=P:GetPlayerData(Q)if O:GetValue("\067\117\114\114\101\110\099\121")<H.CostCandy then return false end local T=N:CompleteTransaction(Q,h)if T then O:SetValue("\067\117\114\114\101\110\099\121",O:GetValue("\067\117\114\114\101\110\099\121")-H.CostCandy)end return T end N.ProcessReceipt=function(h)local N,H=h.PlayerId,h.ProductId local O=Q:GetPlayerByUserId(N)if not O then return Enum.ProductPurchaseDecision.NotProcessedYet end local T for Q,h in pairs(U)do if h.ProductId==H then T=Q break end end if not T then return Enum.ProductPurchaseDecision.NotProcessedYet end if J:CompleteTransaction(O,T)then return Enum.ProductPurchaseDecision.PurchaseGranted else return Enum.ProductPurchaseDecision.NotProcessedYet end end return J
--[[
TheNexusAvenger

Handles purchases by players.
Class is static (should not be created).
--]]

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local MarketplaceService = game:GetService("MarketplaceService")

local ReplicatedStorageProject = require(ReplicatedStorage:WaitForChild("Project"):WaitForChild("ReplicatedStorage"))
local ServerScriptServiceProject = require(ReplicatedStorage:WaitForChild("Project"):WaitForChild("ServerScriptService")):GetContext(script)

local StoreItems = ReplicatedStorageProject:GetResource("GameData.Item.Store")
local GameReplication = ReplicatedStorageProject:GetResource("GameReplication")

local StoreService = ReplicatedStorageProject:GetResource("ExternalUtil.NexusInstance.NexusInstance"):Extend()
StoreService:SetClassName("StoreService")
ServerScriptServiceProject:SetContextResource(StoreService)

local InventoryService = ServerScriptServiceProject:GetResource("Service.InventoryService")
local PlayerDataService = ServerScriptServiceProject:GetResource("Service.PlayerDataService")



--Set up the replication.
local StoreReplication = Instance.new("Folder")
StoreReplication.Name = "StoreReplication"
StoreReplication.Parent = GameReplication

local PurchaseItem = Instance.new("RemoteFunction")
PurchaseItem.Name = "PurchaseItem"
PurchaseItem.Parent = StoreReplication

PurchaseItem.OnServerInvoke = function(Player,TransactionId)
    return StoreService:PurchaseItemWithCoins(Player,TransactionId)
end



--[[
Completes a transaction.
--]]
function StoreService:CompleteTransaction(Player,TransactionId)
    --Return false if the transaction doesn't exists.
    local Transaction = StoreItems[TransactionId]
    if not Transaction then
        return false
    end

    --Return if the transaction can't be satisfied.
    local Inventory = InventoryService:GetInventory(Player)
    local PlayerData = PlayerDataService:GetPlayerData(Player)
    if Transaction.CanPurchase and not Transaction.CanPurchase(Player) then
        return false
    end
    if Transaction.Type == "Item" then
        if not Inventory:GetNextOpenSlot() then
            return false
        end
        if Transaction.AllowMultiple ~= true and #Inventory:GetItemSlots(Transaction.ItemName) > 0 then
            return false
        end
    elseif Transaction.Type == "Pet" then
        if PlayerData:GetValue("PetsOwned")[Transaction.Name] then
            return false
        end
    end

    --Complete the transaction and return true.
    if Transaction.HandlePurchase then
        Transaction.HandlePurchase(Player)
    elseif Transaction.Type == "Item" then
        InventoryService:AddItem(Player,Transaction.ItemName)
    elseif Transaction.Type == "Pet" then
        local Pets = PlayerData:GetValue("PetsOwned")
        Pets[Transaction.Name] = true
        PlayerData:SetValue("PetsOwned",Pets)
    elseif Transaction.Type == "Candy" then
        PlayerData:SetValue("Currency",PlayerData:GetValue("Currency") + Transaction.CandyAmount)
    end
    return true
end

--[[
Purchases an item with coins.
--]]
function StoreService:PurchaseItemWithCoins(Player,TransactionId)
    --Return false if the transaction doesn't exists.
    local Transaction = StoreItems[TransactionId]
    if not Transaction then
        return false
    end

    --Return false if the transaction isn't coin based.
    if not Transaction.CostCandy then
        return false
    end

    --Return false if the player doesn't have enough coins.
    local PlayerData = PlayerDataService:GetPlayerData(Player)
    if PlayerData:GetValue("Currency") < Transaction.CostCandy then
        return false
    end

    --Complete the transaction and return if it worked.
    local TransactionCompleted = self:CompleteTransaction(Player,TransactionId)
    if TransactionCompleted then
        PlayerData:SetValue("Currency",PlayerData:GetValue("Currency") - Transaction.CostCandy)
    end
    return TransactionCompleted
end



--Set up handling Robux purchases.
MarketplaceService.ProcessReceipt = function(Receipt)
    local UserId,ProductId = Receipt.PlayerId,Receipt.ProductId

    --Return not processed if the player is not in the game.
    local Player = Players:GetPlayerByUserId(UserId)
    if not Player then
        return Enum.ProductPurchaseDecision.NotProcessedYet
    end

    --Return not processed if the transaction doesn't exist.
    local TransactionId
    for Id,Transaction in pairs(StoreItems) do
        if Transaction.ProductId == ProductId then
            TransactionId = Id
            break
        end
    end
    if not TransactionId then
        return Enum.ProductPurchaseDecision.NotProcessedYet
    end

    --Return based on the result of the transaction.
    if StoreService:CompleteTransaction(Player,TransactionId) then
        return Enum.ProductPurchaseDecision.PurchaseGranted
    else
        return Enum.ProductPurchaseDecision.NotProcessedYet
    end
end



return StoreService