Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

How to implement UGC? (User Generated Content)

Asked by 1 year ago

Hi!

I'm planning to create a game where users can share their outfits with each other.

The problem I face is that it seems quite impossible to do this with the Roblox DataStore Service. The only way it would be possible to implement such a system purely with services that Roblox provides would be to have globally stored lists of all outfits that would all have their own ID. However, this seems to be very unstable and inefficient. The other solution I came up with was to host my own server where the outfits are stored, sorted and then sent back through a custom written API

My question is, are there any options that I'm missing? Is there a way to avoid hosting my own API to achieve this?

1 answer

Log in to vote
0
Answered by 1 year ago

from my personal experience with roblox datastores, I believe using two data stores (one hosting the outfits, and another hosting the owners of the specific outfits) would work fine.

we save outfits inside an OutfitIDStore with a unique ID (generate a unique ID and save a table with all the IDs) and then append that same ID to a user's outfits list (get the user's table and append the outfit ID to it)

this code has NOT been tested

-- TODO: test code

local DataStoreService = game:GetService('DataStoreService')

local OutfitIDStore = DataStoreService:GetDataStore('OUTFIT_STORE')
local UserIDStore = DataStoreService:GetDataStore('USER_STORE')

local Chars = ('abcdefghijklmnopqrstuvwxyz0123456789').split('')
local GenericLength = 6

-- DATASTORE FUNCTIONS
local function GetOutfitIDStore(key)
    if key == nil then
        error(('missing argument key (got %s, expected not nil)').format(tostring(key)))
    end

    return pcall(function()
        OutfitIDStore:GetAsync(key)
    end)
end

local function SetOutfitIDStore(key, data)
    if key == nil then
        error(('missing argument key (got %s').format(tostring(key)))
    end

    if data == nil then
        error(('missing argument data (got %s)').format(tostring(key)))
    end

    return pcall(function()
        OutfitIDStore:SetAsync(key, data)
    end)
end

local function GetUserIDStore(key)
    if key == nil then
        error(('missing argument key (got %s, expected not nil)').format(tostring(key)))
    end

    return pcall(function()
        UserIDStore:GetAsync(key)
    end)
end

local function SetUserIDStore(key, data)
    if key == nil then
        error(('missing argument key (got %s').format(tostring(key)))
    end

    if data == nil then
        error(('missing argument data (got %s)').format(tostring(key)))
    end

    return pcall(function()
        UserIDStore:SetAsync(key, data)
    end)
end

local function GenerateUniqueID(length: int)
    if type(length) ~= 'number' then
        length = GenericLength
    end

    local ID = ''
    for i = 1, length do
        ID = ID + Chars[math.random(1, #Chars)]
    end

    local ok, data = GetOutfitIDStore(ID)
    if not ok and type(data) ~= 'table' then
        return ID
    else
        return GenerateUniqueID(length)
    end
end

-- OUTFIT FUNCTIONS
local function SaveOutfit(Accessories: table, UserID: int)
    assert(Accessories, 'no accessories provided.')
    assert(UserID, 'no userid provided.')

    -- upload outfit to database
    local ID = GenerateUniqueID()
    local UploadSuccess, Message = SetOutfitIDStore(ID, Accessories)
    if not UploadSuccess and Message ~= nil then
        -- upload error, handle.
    end

    local GetSuccess, Data = GetUserIDStore(UserID)
    if not GetSuccess and Data == nil then
        -- get error, handle.
    end

    local UpdatedTable = Data
    table.insert(UpdatedTable, ID)

    local SetSuccess, Message = SetUserIDStore(UserID, UpdatedTable)
    if not SetSuccess and Message ~= nil then
        -- set error, handle.
    end
end

local function RemoveOutfit(ID: str, UserID: int)
    local GetSuccess, Data = GetUserIDStore(UserID)
    if not GetSuccess and Data == nil then
        -- get error, handle.
    end

    if not table.find(Data, ID) then
        return false, ('User %i is not the owner of outfit (%s)').format(UserID, ID)
    end
    local UpdatedTable = Data
    table.remove(UpdatedTable, table.find(Data, ID))

    local SetSuccess, Message = SetUserIDStore(UserID, UpdatedTable)
    if not SetSuccess and Message ~= nil then
        -- set error, handle.
    end
end

local function GetOutfitFromID(ID)
    return GetOutfitIDStore(ID)
end

local function GetUserOufits(UserID)
    return GetUserIDStore(UserID)
end
0
That's what I originally thought, but that option wouldn't allow browsing the outfits, would it? MageMasterHD 261 — 1y
0
i assume you mean browsing by listing every outfit created. no, that wouldn't be possible unless you used an OrderedDataStore (replacing the Outfit_Store GetDataStore with OrderedDataStore), if you wish I could upload a version of the script with that included. loowa_yawn 383 — 1y
0
that'd be great! MageMasterHD 261 — 1y
Ad

Answer this question