Open Source Suggestions
Key Required

Open Source Suggestions

Last Letter 💬Unnamed_GooseUnnamed_Goose 2.4K views 736 executesUpdated Dec 26, 2025
Unrated
00
Lua Script•172 lines (4436 chars)
-- This file is licensed under the Mozilla Public License version 2.0
-- The performance is good enough so I thought that I may as well just release it for anyone to use.
local Players = game:GetService("Players")
local Web = game:GetService("HttpService")

local player = Players.LocalPlayer
local parent = player:WaitForChild("PlayerGui")
local frame = parent:WaitForChild("InGame"):WaitForChild("Frame")

local SUGGESTIONS = 6
local SOURCE = "https://raw.githubusercontent.com/dwyl/english-words/refs/heads/master/words_dictionary.json"

local dictionary = {}
local prefixCache = {}

local screen = Instance.new("ScreenGui")
screen.Name = "AutoCompleteSuggestions"
screen.ResetOnSpawn = false
screen.Parent = parent

local labels = {}
for i = 1, SUGGESTIONS do
    local lbl = Instance.new("TextLabel")
    lbl.Name = "Suggestion"..i
    lbl.Size = UDim2.fromOffset(220, 28)
    lbl.Position = UDim2.new(1, -230, 0, 10 + (i-1)*30)
    lbl.BackgroundTransparency = 1
    lbl.TextColor3 = Color3.new(1, 1, 1)
    lbl.Font = Enum.Font.GothamBold
    lbl.TextSize = 22
    lbl.TextXAlignment = Enum.TextXAlignment.Right
    lbl.Text = ""
    lbl.Parent = screen
    labels[i] = lbl
end

task.spawn(function()
    local success, content = pcall(function()
        return game:HttpGet(SOURCE)
    end)
    if not success then
        warn("Failed to download dictionary")
        return
    end

    local data = nil
    local ok = pcall(function()
        data = Web:JSONDecode(content)
    end)

    if not ok or type(data) ~= "table" then
        warn("Dictionary decode failed")
        return
    end

    for word in pairs(data) do
        dictionary[#dictionary+1] = word:lower()
    end
    table.sort(dictionary)
end)

-- Basically just binary search
local function findRange(prefix)
    local low, high = 1, #dictionary
    local startIdx, endIdx

    while low <= high do
        local mid = math.floor((low + high) / 2)
        if dictionary[mid]:sub(1, #prefix) < prefix then
            low = mid + 1
        else
            high = mid - 1
        end
    end
    startIdx = low

    low, high = startIdx, #dictionary
    while low <= high do
        local mid = math.floor((low + high) / 2)
        if dictionary[mid]:sub(1, #prefix) == prefix then
            low = mid + 1
        else
            high = mid - 1
        end
    end
    endIdx = high

    if startIdx > endIdx then
        return nil, nil
    end
    return startIdx, endIdx
end

-- Yes, I know this is a slightly autistic way of designing the UI.
local function getWord()
    local wordFrame = frame:FindFirstChild("CurrentWord")
    if not wordFrame or not wordFrame.Visible then
        return ""
    end

    local letters = {}
    local numbered = {}
    for _, child in ipairs(wordFrame:GetChildren()) do
        local idx = tonumber(child.Name)
        if idx and child:FindFirstChild("Letter") then
            numbered[#numbered+1] = {idx = idx, obj = child}
        end
    end

    table.sort(numbered, function(a,b) return a.idx < b.idx end)
    for _, entry in ipairs(numbered) do
        local letter = entry.obj.Letter.Text
        if type(letter) == "string" then
            letters[#letters+1] = letter
        end
    end

    return table.concat(letters):lower()
end

local lastInput = ""
local function update()
    local prefix = getWord()
    if prefix == lastInput then
        return
    end
    lastInput = prefix

    for i = 1, SUGGESTIONS do
        labels[i].Text = ""
    end

    if prefix == "" then
        return
    end

    local range = prefixCache[prefix]
    local sIdx, eIdx -- Start and end indexes, sorry for the naming

    if range then
        sIdx, eIdx = range[1], range[2]
    else
        sIdx, eIdx = findRange(prefix)
        if sIdx then
            prefixCache[prefix] = {sIdx, eIdx}
            if #prefixCache > 4 then
                for k in pairs(prefixCache) do
                    prefixCache[k] = nil
                    break
                end
            end
        end
    end

    if not sIdx then
        return
    end

    local count = 0
    for i = sIdx, eIdx do
        if count >= SUGGESTIONS then break end
        local w = dictionary[i]
        if w and w ~= prefix then
            count += 1
            labels[count].Text = w
        end
    end
end

local display = frame:WaitForChild("CurrentWord")
display.ChildAdded:Connect(update)
display.ChildRemoved:Connect(update)

Features & Information

This is a simple open source script that shows word suggestions based on what you type and yes, that includes any prefix.
#word#open source#suggestion

Community Comments (3)

Unnamed_GooseUnnamed_GooseDec 26, 2025(edited)

If you want to remove any words you can do so by modifying the dictionary JSON link with one of your own. This supports dictionary tier lists so if enough suggestions aren't found in the first one it'll go onto the next, this is useful when you want to mostly use a subset of words.

frzfrsyfrzfrsyDec 26, 2025

top tier programming

frzfrsyfrzfrsyDec 26, 2025

try do guess do drawing!

More Scripts for Last Letter 💬