local A=game:GetService("\067\111\108\108\101\099\116\105\111\110\083\101\114\118\105\099\101")local v=game:GetService("\080\108\097\121\101\114\115")local Y=game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")local i=Y:WaitForChild("\099\111\109\109\111\110")local C=Y:WaitForChild("\108\105\098")local R=require(C:WaitForChild("\080\114\111\109\105\115\101"))local M=require(C:WaitForChild("\080\105\122\122\097\065\108\112\097\099\097"))local k=require(i:WaitForChild("\065\099\116\105\111\110\115"))local H=require(i:WaitForChild("\083\101\108\101\099\116\111\114\115"))local c=require(C:WaitForChild("\083\105\103\110\097\108"))local p=M.GameModule:extend("\067\097\110\100\121")local f=600 function p.create(A)A.collections={}A.spawns={}A.last5Secs={}end function p.onPlayerJoin(v,A)v.collections[A]={}end function p.onPlayerRemoving(v,A)v.collections[A]=nil end function p.bindRespawn(Y,A,v)spawn(function()wait(f)if Y.collections[A]then Y.collections[A][v]=false Y.api:candyRespawn(A,v)end end)end function p.requestCollect(Y,A,v)assert(typeof(v)=="\073\110\115\116\097\110\099\101","\097\114\103 \050 \109\117\115\116 \098\101 \097 \112\097\114\116\044 \103\111\116\058"..tostring(v))assert(v:IsA("\066\097\115\101\080\097\114\116"),"\097\114\103 \050 \109\117\115\116 \098\101 \097 \112\097\114\116\044 \103\111\116\058"..tostring(v))assert(Y.spawns[v],"\073\110\118\097\108\105\100 \099\097\110\100\121 \115\112\097\119\110")if not Y.collections[A][v]then Y.collections[A][v]=true local i=A.Character if not i then return end local C=i:FindFirstChild("\072\117\109\097\110\111\105\100\082\111\111\116\080\097\114\116")if not C then return end local R=(C.Position-v.Position).Magnitude if R>40 then return end Y.store:dispatch(k.CANDY_ADD(A,math.random(1,5)))Y.last5Secs[A]=(Y.last5Secs[A]or 0)+1 if Y.last5Secs[A]>30 then A:Kick("\067\111\108\108\101\099\116\105\110\103 \099\097\110\100\121 \116\111\111 \102\097\115\116 \058\040 \084\104\101 \115\101\114\118\101\114 \109\105\103\104\116 \098\101 \108\097\103\103\105\110\103\046 \079\114 \097\114\101 \121\111\117 \099\104\101\097\116\105\110\103\063")end Y:bindRespawn(A,v)end end function p.init(Y)for A,v in pairs(A:GetTagged("\099\097\110\100\121\095\115\112\097\119\110"))do Y.spawns[v]=v end for A,v in pairs(v:GetPlayers())do Y:onPlayerJoin(v)end v.PlayerAdded:Connect(function(A)Y:onPlayerJoin(A)end)v.PlayerRemoving:Connect(function(A)Y:onPlayerRemoving(A)end)spawn(function()while true do Y.last5Secs={}wait(5)end end)end function p.postInit(A)local v=A.core:getModule("\083\101\114\118\101\114\065\112\105")local Y=A.core:getModule("\083\116\111\114\101\067\111\110\116\097\105\110\101\114")local function i(v,Y)A.api=v A.store=Y end;(R.all({v:getApi();Y:getStore()})):andThen(function(A)return R.async(function(v,Y)i(unpack(A))end)end)end return p
-- server side coin tracking

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

local common = ReplicatedStorage:WaitForChild("common")
local lib = ReplicatedStorage:WaitForChild("lib")

local Promise = require(lib:WaitForChild("Promise"))
local PizzaAlpaca = require(lib:WaitForChild("PizzaAlpaca"))
local Actions = require(common:WaitForChild("Actions"))
local Selectors = require(common:WaitForChild("Selectors"))
local Signal = require(lib:WaitForChild("Signal"))

local Candy = PizzaAlpaca.GameModule:extend("Candy")

local RESPAWN_TIME = 600

function Candy:create()
    self.collections = {}
    self.spawns = {}
    self.last5Secs = {}
end

function Candy:onPlayerJoin(player)
    self.collections[player] = {}
end

function Candy:onPlayerRemoving(player)
    self.collections[player] = nil
end

function Candy:bindRespawn(player,spawnPart)
    spawn(function()
        wait(RESPAWN_TIME)
        if self.collections[player] then
            self.collections[player][spawnPart] = false
            self.api:candyRespawn(player,spawnPart)
        end
    end)
end

function Candy:requestCollect(player,spawnPart)
    assert(typeof(spawnPart) == "Instance", "arg 2 must be a part, got:"..tostring(spawnPart))
    assert(spawnPart:IsA("BasePart"), "arg 2 must be a part, got:"..tostring(spawnPart))
    assert(self.spawns[spawnPart], "Invalid candy spawn")

    if not self.collections[player][spawnPart] then
        self.collections[player][spawnPart] = true

        local char = player.Character
        if not char then return end
        local root = char:FindFirstChild("HumanoidRootPart")
        if not root then return end

        local dist = (root.Position-spawnPart.Position).Magnitude

        if dist > 40 then
            return -- too far away :O
        end

        self.store:dispatch(Actions.CANDY_ADD(player, math.random(1,5)))

        self.last5Secs[player] = (self.last5Secs[player] or 0) + 1
        if self.last5Secs[player] > 30 then
            player:Kick("Collecting candy too fast :( The server might be lagging. Or are you cheating?")
        end

        self:bindRespawn(player,spawnPart)
    end
end

function Candy:init()
    for _, instance in pairs(CollectionService:GetTagged("candy_spawn")) do
        self.spawns[instance] = instance
    end

    for _,player in pairs(Players:GetPlayers()) do
		self:onPlayerJoin(player)
	end

    Players.PlayerAdded:Connect(function(player) self:onPlayerJoin(player) end)
    Players.PlayerRemoving:Connect(function(player) self:onPlayerRemoving(player) end)

    -- every 5 secs clear the coin collected table
    spawn(function()
        while true do
            self.last5Secs = {}
            wait(5)
        end
    end)
end

function Candy:postInit()
    local apiWrapper = self.core:getModule("ServerApi")
    local storeContainer = self.core:getModule("StoreContainer")

    local function onAll(api, store)
        self.api = api
        self.store = store
    end

    Promise.all({
        apiWrapper:getApi(),
        storeContainer:getStore()
    }):andThen(function(resolved)
        return Promise.async(function(resolve,reject)
            onAll(unpack(resolved))
        end)
    end)
end

return Candy