Learn
Engine Class
DataModel
Not Creatable

Code Samples
GetService()
local Workspace = game:GetService("Workspace")
local Lighting = game:GetService("Lighting")
-- Examples of modifying properties of these services
Workspace.Gravity = 20
Lighting.ClockTime = 4

API Reference
Properties
CreatorId
Read Only
Not Replicated
Read Parallel
DataModel.CreatorId:number
Code Samples
Detect when the place owner joins the game
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
if game.CreatorType == Enum.CreatorType.User then
if player.UserId == game.CreatorId then
print("The place owner has joined the game!")
end
elseif game.CreatorType == Enum.CreatorType.Group then
if player:IsInGroupAsync(game.CreatorId) then
print("A member of the group that owns the place has joined the game!")
end
end
end)

CreatorType
Read Only
Not Replicated
Read Parallel
DataModel.CreatorType:Enum.CreatorType
Code Samples
Detect when the place owner joins the game
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
if game.CreatorType == Enum.CreatorType.User then
if player.UserId == game.CreatorId then
print("The place owner has joined the game!")
end
elseif game.CreatorType == Enum.CreatorType.Group then
if player:IsInGroupAsync(game.CreatorId) then
print("A member of the group that owns the place has joined the game!")
end
end
end)

Environment
Read Only
Not Replicated
Roblox Script Security
Read Parallel
DataModel.Environment:string

GameId
Read Only
Not Replicated
Read Parallel
DataModel.GameId:number

GearGenreSetting
Deprecated

Genre
Deprecated

JobId
Read Only
Not Replicated
Read Parallel
DataModel.JobId:string

lighting
Deprecated

MatchmakingType
Read Only
Not Replicated
Read Parallel
DataModel.MatchmakingType:Enum.MatchmakingType

PlaceId
Read Only
Not Replicated
Read Parallel
DataModel.PlaceId:number

PlaceVersion
Read Only
Not Replicated
Read Parallel
DataModel.PlaceVersion:number
Code Samples
Server version number GUI
local StarterGui = game:GetService("StarterGui")
local versionGui = Instance.new("ScreenGui")
local textLabel = Instance.new("TextLabel")
textLabel.Position = UDim2.new(1, -10, 1, 0)
textLabel.AnchorPoint = Vector2.new(1, 1)
textLabel.Size = UDim2.new(0, 150, 0, 40)
textLabel.BackgroundTransparency = 1
textLabel.TextColor3 = Color3.new(1, 1, 1)
textLabel.TextStrokeTransparency = 0
textLabel.TextXAlignment = Enum.TextXAlignment.Right
textLabel.TextScaled = true
local placeVersion = game.PlaceVersion
textLabel.Text = string.format("Server version: %s", placeVersion)
textLabel.Parent = versionGui
versionGui.Parent = StarterGui

PrivateServerId
Read Only
Not Replicated
Read Parallel
DataModel.PrivateServerId:string
Code Samples
Detecting Private Servers
local function getServerType()
if game.PrivateServerId ~= "" then
if game.PrivateServerOwnerId ~= 0 then
return "VIPServer"
else
return "ReservedServer"
end
else
return "StandardServer"
end
end
print(getServerType())

PrivateServerOwnerId
Read Only
Not Replicated
Read Parallel
DataModel.PrivateServerOwnerId:number
Code Samples
Detecting Private Servers
local function getServerType()
if game.PrivateServerId ~= "" then
if game.PrivateServerOwnerId ~= 0 then
return "VIPServer"
else
return "ReservedServer"
end
else
return "StandardServer"
end
end
print(getServerType())

RunService
Read Only
Not Replicated
Read Parallel
DataModel.RunService:RunService

VIPServerId
Deprecated

VIPServerOwnerId
Deprecated

Workspace
Read Only
Not Replicated
Read Parallel
DataModel.Workspace:Workspace

workspace
Deprecated

Methods
BindToClose
DataModel:BindToClose(function:function):()
Parameters
function:function
Returns
()
Code Samples
Saving player data before shutting down
local DataStoreService = game:GetService("DataStoreService")
local RunService = game:GetService("RunService")
local playerDataStore = DataStoreService:GetDataStore("PlayerData")
local allPlayerSessionDataCache = {}
local function savePlayerDataAsync(userId, data)
return playerDataStore:UpdateAsync(userId, function(oldData)
return data
end)
end
local function onServerShutdown(closeReason)
if RunService:IsStudio() then
-- Avoid writing studio data to production and stalling test session closing
return
end
-- Reference for yielding and resuming later
local mainThread = coroutine.running()
-- Counts up for each new thread, down when the thread finishes. When 0 is reached,
-- the individual thread knows it's the last thread to finish and should resume the main thread
local numThreadsRunning = 0
-- Calling this function later starts on a new thread because of coroutine.wrap
local startSaveThread = coroutine.wrap(function(userId, sessionData)
-- Perform the save operation
local success, result = pcall(savePlayerDataAsync, userId, sessionData)
if not success then
-- Could implement a retry
warn(string.format("Failed to save %d's data: %s", userId, result))
end
-- Thread finished, decrement counter
numThreadsRunning -= 1
if numThreadsRunning == 0 then
-- This was the last thread to finish, resume main thread
coroutine.resume(mainThread)
end
end)
-- This assumes playerData gets cleared from the data table during a final save on PlayerRemoving,
-- so this is iterating over all the data of players still in the game that hasn't been saved
for userId, sessionData in pairs(allPlayerSessionDataCache) do
numThreadsRunning += 1
-- This loop finishes running and counting numThreadsRunning before any of
-- the save threads start because coroutine.wrap has built-in deferral on start
startSaveThread(userId, sessionData)
end
if numThreadsRunning > 0 then
-- Stall shutdown until save threads finish. Resumed by the last save thread when it finishes
coroutine.yield()
end
end
game:BindToClose(onServerShutdown)
Binding to and Handling Game Shutdown
game:BindToClose(function(closeReason)
print(`Closing with reason {closeReason}`)
task.wait(3)
print("Done")
end)

GetJobsInfo
Plugin Security
DataModel:GetJobsInfo():{any}
Returns
Code Samples
Getting Jobs Info
local jobInfo = game:GetJobsInfo()
local jobTitles = jobInfo[1]
table.remove(jobInfo, 1)
local divider = string.rep("-", 120)
print(divider)
warn("JOB INFO:")
print(divider)
for _, job in pairs(jobInfo) do
for jobIndex, jobValue in pairs(job) do
local jobTitle = jobTitles[jobIndex]
warn(jobTitle, "=", jobValue)
end
print(divider)
end

GetMessage
Deprecated

GetObjects
Deprecated

GetRemoteBuildMode
Deprecated

IsGearTypeAllowed
Deprecated

IsLoaded
DataModel:IsLoaded():boolean
Returns
Code Samples
Custom Loading Screen
local Players = game:GetService("Players")
local ReplicatedFirst = game:GetService("ReplicatedFirst")
local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
-- Create a basic loading screen
local screenGui = Instance.new("ScreenGui")
screenGui.IgnoreGuiInset = true
local textLabel = Instance.new("TextLabel")
textLabel.Size = UDim2.new(1, 0, 1, 0)
textLabel.BackgroundColor3 = Color3.fromRGB(0, 20, 40)
textLabel.Font = Enum.Font.GothamMedium
textLabel.TextColor3 = Color3.new(0.8, 0.8, 0.8)
textLabel.Text = "Loading"
textLabel.TextSize = 28
textLabel.Parent = screenGui
-- Parent entire screen GUI to player GUI
screenGui.Parent = playerGui
-- Remove the default loading screen
ReplicatedFirst:RemoveDefaultLoadingScreen()
--task.wait(3) -- Optionally force screen to appear for a minimum number of seconds
if not game:IsLoaded() then
game.Loaded:Wait()
end
screenGui:Destroy()

SavePlace
Deprecated

SetPlaceId
Plugin Security
DataModel:SetPlaceId(placeId:number):()
Parameters
placeId:number
Returns
()

SetUniverseId
Plugin Security
DataModel:SetUniverseId(universeId:number):()
Parameters
universeId:number
Returns
()

Events
AllowedGearTypeChanged
Deprecated

GraphicsQualityChangeRequest
DataModel.GraphicsQualityChangeRequest(betterQuality:boolean):RBXScriptSignal
Parameters
betterQuality:boolean
Code Samples
Handling User Changes in Graphics Quality
game.GraphicsQualityChangeRequest:Connect(function(betterQuality)
if betterQuality then
print("The user has requested an increase in graphics quality!")
else
print("The user has requested a decrease in graphics quality!")
end
end)

ItemChanged
Deprecated

Loaded
DataModel.Loaded():RBXScriptSignal

ServerRestartScheduled
Capabilities: ServerCommunication
DataModel.ServerRestartScheduled(
restartTime:DateTime, source:Enum.CloseReason, attributes:Dictionary
Parameters
restartTime:DateTime
attributes:Dictionary
Code Samples
ServerRestartScheduled
local roundInProgress = false -- Set elsewhere in game code whenever a game round starts or ends
local restartPending = false
game.ServerRestartScheduled:Connect(function(restartTime, source, attributes)
local msg = attributes and attributes.message or ""
local timeStr = restartTime:FormatLocalTime("LTS", "en-us") -- since this is run on the server, it will be in UTC
-- Forward these fields to clients via remote:FireAllClients() to display customized messages in your UI
print(string.format("Server restart at %s from source: %s. Reason: %s.", timeStr, tostring(source), msg))
if not roundInProgress then
print("No round in progress. Teleporting players in 10 seconds")
task.wait(10)
-- Teleporting players when a restart has been scheduled will bring them to a server on the latest place version
game:GetService("TeleportService"):TeleportAsync(game.PlaceId, game:GetService("Players"):GetPlayers())
else
-- You can add code to teleport players after a game round ends if restartPending is true.
restartPending = true
end
end)

Callbacks
OnClose
Deprecated

©2026 Roblox Corporation. Roblox, the Roblox logo and Powering Imagination are among our registered and unregistered trademarks in the U.S. and other countries.