Skip to content

Networking Module

The Networking Module handles external API requests with built-in caching, rate limiting, and retry logic.

Overview

Making HTTP requests in Roblox can be challenging:

  • Rate limits (500 requests per minute)
  • No built-in caching
  • No automatic retry logic
  • Complex error handling

Raddish's Networking Module solves all of these problems.

HTTP Methods

GET Requests

lua
local Raddish = require(game.ReplicatedStorage.Raddish)

-- Basic GET request
local response = Raddish.HttpGet("https://api.example.com/data")

if response.Success then
    print("Data:", response.Body)
else
    warn("Failed:", response.StatusMessage)
end

GET with Caching

lua
-- Cache response for 5 minutes
local response = Raddish.HttpGet("https://api.example.com/data", {
    cache = true,
    cacheTTL = 300 -- seconds
})

-- First call: Fetches from API (slow)
-- Next calls within 5 min: Returns from cache (instant!)

GET with Headers

lua
local response = Raddish.HttpGet("https://api.example.com/protected", {
    headers = {
        ["Authorization"] = "Bearer your-token-here",
        ["User-Agent"] = "RobloxGame/1.0"
    }
})

POST Requests

lua
-- Send JSON data
local response = Raddish.HttpPost("https://api.example.com/submit", {
    username = "VerifiedHawaii",
    score = 9999,
    timestamp = os.time()
})

-- With custom headers
local response = Raddish.HttpPost("https://api.example.com/submit", {
    data = "value"
}, {
    headers = {
        ["Content-Type"] = "application/json",
        ["X-API-Key"] = "your-api-key"
    }
})

PUT Requests

lua
-- Update resource
local response = Raddish.HttpPut("https://api.example.com/users/123", {
    name = "UpdatedName",
    level = 100
})

DELETE Requests

lua
-- Delete resource
local response = Raddish.HttpDelete("https://api.example.com/users/123", {
    headers = {
        ["Authorization"] = "Bearer token"
    }
})

PATCH Requests

lua
-- Partial update
local response = Raddish.HttpPatch("https://api.example.com/users/123", {
    level = 51 -- Only update level
})

Batch Requests

Send multiple requests efficiently:

lua
local results = Raddish.HttpBatch({
    {method = "GET", url = "https://api.example.com/user/1"},
    {method = "GET", url = "https://api.example.com/user/2"},
    {method = "GET", url = "https://api.example.com/user/3"},
    {
        method = "POST",
        url = "https://api.example.com/log",
        data = {event = "batch_complete"}
    }
})

for i, result in ipairs(results) do
    if result.Success then
        print("Request", i, "succeeded:", result.Body)
    else
        print("Request", i, "failed:", result.StatusMessage)
    end
end

Discord Webhooks

Simple Webhook

lua
local webhookUrl = "https://discord.com/api/webhooks/YOUR_ID/YOUR_TOKEN"

Raddish.SendWebhook(webhookUrl, {
    content = "Server started successfully!",
    username = "Roblox Game Bot"
})

Rich Embeds

lua
Raddish.SendDiscordWebhook(webhookUrl, {
    title = "Player Achievement",
    description = "VerifiedHawaii reached level 100!",
    color = 0x00FF00, -- Green color
    fields = {
        {name = "Player", value = "VerifiedHawaii", inline = true},
        {name = "Level", value = "100", inline = true},
        {name = "Time Played", value = "50 hours", inline = true},
        {name = "Server", value = game.JobId, inline = false}
    },
    footer = {text = "Achievement System"},
    username = "Achievement Bot",
    avatar_url = "https://example.com/avatar.png"
})

Log System

lua
-- Create a logging system
local logWebhook = "https://discord.com/api/webhooks/YOUR_LOG_ID/TOKEN"

function logToDiscord(level, message, data)
    local colors = {
        INFO = 0x0099FF,    -- Blue
        WARN = 0xFFAA00,    -- Orange
        ERROR = 0xFF0000,   -- Red
        SUCCESS = 0x00FF00  -- Green
    }
    
    Raddish.SendDiscordWebhook(logWebhook, {
        title = level .. " Log",
        description = message,
        color = colors[level] or 0x808080,
        fields = data and {
            {name = "Details", value = game:GetService("HttpService"):JSONEncode(data)}
        } or {},
        footer = {text = "Server: " .. game.JobId}
    })
end

-- Usage
logToDiscord("ERROR", "Player exploit detected", {
    player = "SuspiciousPlayer",
    reason = "Impossible speed",
    value = 500
})

logToDiscord("SUCCESS", "Server started", {
    players = 0,
    maxPlayers = 50
})

REST API Helper

Simplified REST API calls with authentication:

lua
local baseUrl = "https://api.yourgame.com"
local apiKey = "your-secret-api-key"

-- GET with authentication
local userData = Raddish.APIRequest(baseUrl, "/users/123", {
    method = "GET",
    apiKey = apiKey,
    cache = true,
    cacheTTL = 600
})

-- POST with authentication
local createResponse = Raddish.APIRequest(baseUrl, "/users", {
    method = "POST",
    apiKey = apiKey,
    data = {
        username = "NewPlayer",
        email = "player@example.com"
    }
})

-- With custom token header
local response = Raddish.APIRequest(baseUrl, "/protected", {
    method = "GET",
    token = "custom-token",
    headers = {
        ["X-Custom-Header"] = "value"
    }
})

Response Format

All HTTP methods return a consistent response format:

lua
{
    Success = true/false,
    StatusCode = 200,
    StatusMessage = "OK",
    Body = {...} -- Automatically parsed JSON or raw string
}

Cache Management

Invalidate Cache

lua
-- Invalidate specific URL cache
Raddish.InvalidateHttpCache("https://api.example.com/data")

-- Clear all HTTP cache
local clearedCount = Raddish.ClearHttpCache()
print("Cleared", clearedCount, "cached responses")

Check Network Stats

lua
local stats = Raddish.GetNetworkStats()
print("Queue size:", stats.queueSize)
print("Requests this window:", stats.requestsThisWindow)
print("Max per window:", stats.maxRequestsPerWindow)
print("Cache size:", stats.cacheSize)

Rate Limiting

The module automatically handles rate limiting:

lua
-- If rate limit is reached, requests are queued
local response = Raddish.HttpGet("https://api.example.com/data")

if response.StatusCode == 429 then
    print("Rate limited - request was queued")
end

-- Manually queue a request
local requestId = Raddish.QueueRequest("GET", "https://api.example.com/data")
print("Queued request:", requestId)

Retry Logic

Failed requests are automatically retried with exponential backoff:

lua
-- Configuration (in NetworkingModule.lua)
local MAX_RETRIES = 3
local RETRY_DELAY = 2 -- Initial delay in seconds

-- Attempts:
-- 1st: Immediate
-- 2nd: After 2 seconds
-- 3rd: After 4 seconds
-- Final: Return error

Use Cases

Analytics Tracking

lua
function trackEvent(eventName, eventData)
    Raddish.HttpPost("https://analytics.yourgame.com/events", {
        event = eventName,
        data = eventData,
        timestamp = os.time(),
        serverId = game.JobId,
        placeId = game.PlaceId
    }, {
        headers = {
            ["Authorization"] = "Bearer " .. analyticsKey
        }
    })
end

-- Track player join
game.Players.PlayerAdded:Connect(function(player)
    trackEvent("player_joined", {
        userId = player.UserId,
        username = player.Name,
        accountAge = player.AccountAge
    })
end)

External Inventory System

lua
function syncInventory(player)
    local response = Raddish.APIRequest(
        "https://inventory.yourgame.com",
        "/player/" .. player.UserId .. "/items",
        {
            method = "GET",
            apiKey = inventoryApiKey,
            cache = true,
            cacheTTL = 300
        }
    )
    
    if response.Success then
        local items = response.Body.items
        
        -- Store in Raddish cache
        for _, item in ipairs(items) do
            Raddish.HSet("inventory:" .. player.UserId, item.id, item.quantity)
        end
        
        print("Synced", #items, "items for", player.Name)
    end
end

-- Update external inventory
function giveItem(player, itemId, quantity)
    -- Update local cache first
    Raddish.HSet("inventory:" .. player.UserId, itemId, quantity)
    
    -- Sync with external API
    Raddish.APIRequest(
        "https://inventory.yourgame.com",
        "/player/" .. player.UserId .. "/items",
        {
            method = "POST",
            apiKey = inventoryApiKey,
            data = {
                itemId = itemId,
                quantity = quantity
            }
        }
    )
end

Server Status Monitoring

lua
local monitoringUrl = "https://monitoring.yourgame.com"

function reportServerStatus()
    local stats = {
        serverId = game.JobId,
        placeId = game.PlaceId,
        players = #game.Players:GetPlayers(),
        maxPlayers = game.Players.MaxPlayers,
        memory = game:GetService("Stats"):GetTotalMemoryUsageMb(),
        uptime = workspace.DistributedGameTime,
        timestamp = os.time()
    }
    
    Raddish.HttpPost(monitoringUrl .. "/server-status", stats, {
        headers = {
            ["X-Server-Key"] = "monitoring-key"
        }
    })
end

-- Report every 30 seconds
task.spawn(function()
    while true do
        reportServerStatus()
        task.wait(30)
    end
end)

External Leaderboard

lua
function syncLeaderboard()
    -- Fetch from external API
    local response = Raddish.HttpGet("https://api.yourgame.com/leaderboard/top100", {
        cache = true,
        cacheTTL = 60 -- Cache for 1 minute
    })
    
    if response.Success then
        -- Update local sorted set
        for _, entry in ipairs(response.Body.players) do
            Raddish.ZAdd("leaderboard:global", entry.score, entry.userId)
        end
    end
end

-- Sync every minute
task.spawn(function()
    while true do
        syncLeaderboard()
        task.wait(60)
    end
end)

-- Update external leaderboard when player scores
function updateScore(player, newScore)
    -- Update local
    Raddish.ZAdd("leaderboard:global", newScore, player.UserId)
    
    -- Update external
    Raddish.HttpPost("https://api.yourgame.com/leaderboard/update", {
        userId = player.UserId,
        username = player.Name,
        score = newScore
    })
end

Payment Verification

lua
function verifyPurchase(player, receiptInfo)
    local response = Raddish.APIRequest(
        "https://payment.yourgame.com",
        "/verify",
        {
            method = "POST",
            apiKey = paymentApiKey,
            data = {
                userId = player.UserId,
                productId = receiptInfo.ProductId,
                purchaseId = receiptInfo.PurchaseId,
                timestamp = os.time()
            }
        }
    )
    
    if response.Success and response.Body.verified then
        -- Grant product
        grantProduct(player, receiptInfo.ProductId)
        return Enum.ProductPurchaseDecision.PurchaseGranted
    else
        return Enum.ProductPurchaseDecision.NotProcessedYet
    end
end

Error Handling

lua
local response = Raddish.HttpGet("https://api.example.com/data")

if not response.Success then
    if response.StatusCode == 404 then
        print("Resource not found")
    elseif response.StatusCode == 429 then
        print("Rate limited")
    elseif response.StatusCode == 500 then
        print("Server error")
    else
        warn("Request failed:", response.StatusMessage)
    end
else
    -- Success
    print("Data:", response.Body)
end

Best Practices

  1. Always use caching for repeated requests

    lua
    -- Good
    Raddish.HttpGet(url, {cache = true, cacheTTL = 300})
    
    -- Bad (makes API call every time)
    Raddish.HttpGet(url)
  2. Handle errors gracefully

    lua
    local success, response = pcall(function()
        return Raddish.HttpGet(url)
    end)
    
    if success and response.Success then
        -- Process data
    end
  3. Use environment variables for API keys

    lua
    -- Don't hardcode API keys!
    local apiKey = game:GetService("ServerStorage").Config.ApiKey.Value
  4. Monitor rate limits

    lua
    local stats = Raddish.GetNetworkStats()
    if stats.requestsThisWindow > 80 then
        warn("Approaching rate limit!")
    end

"Beyond Boundaries. Beyond Imagination."