v1.0.0

DoorSystem API

A high-performance, DOD-optimized door management system for Roblox with bit-level state control and O(1) operations

Overview

DoorSystem is a production-ready, memory-efficient door management library for Roblox that uses Data-Oriented Design (DOD) principles and bit-level operations to achieve O(1) performance for all state operations.

⚑ High Performance

O(1) state operations using bit manipulation and buffer storage

🎯 Memory Efficient

DOD architecture with isolated memory allocation per door group

πŸ”§ Easy Integration

Fluent API design with chainable methods

πŸ” Built-in Security

Lock states, key requirements, and access control out of the box

Installation

Method 1: Manual Installation

  1. Download the DoorSystem.rbxm file
  2. Drag and drop the file into Roblox Studio
  3. Move the DoorSystem module to ServerScriptService
  4. Copy the example Main.luau to ServerScriptService

File Structure

ServerScriptService
β”œβ”€β”€ Main.luau (ServerScript)
└── DoorSystem (ModuleScript)
    β”œβ”€β”€ Core
    β”‚ └── DoorGroup.luau
    β””── Utils
        β””── BufferSerializer.luau (optional)

Quick Start

Here's a minimal example to get you started:

local DoorSystem = require(game.ServerScriptService.DoorSystem)

-- Create a door group
local MyDoors = DoorSystem.new(workspace.Map.Doors, {
    PromptProps = { ActionText = "Open/Close" }  -- optional
})

-- Define what happens when a door toggles
MyDoors:SetCallback(function(door, isOpen, player)
    door.Transparency = isOpen and 0.8 or 0
    door.CanCollide = not isOpen
end)

-- That's it! Your doors are ready to use
Note: The system automatically creates ProximityPrompts for each door in the folder if they don't exist.

API Reference

DoorSystem.new()

Creates and returns a new DoorGroup instance with isolated memory allocation.

Syntax

DoorSystem.new(folder: Folder, config: table?) β†’ DoorGroup

Parameters

Parameter Type Required Description
folder Folder Required The folder containing door instances
config table Optional Configuration table (see configuration section)

Returns

A DoorGroup object with chainable methods.

Example

-- Basic usage
local doors = DoorSystem.new(workspace.Doors)

-- With configuration
local secureDoors = DoorSystem.new(workspace.SecureDoors, {
    RequiredKey = "Keycard",  -- optional
    PromptProps = {           -- optional
        ActionText = "Access Panel",
        HoldDuration = 1.5
    }
})

SetCallback()

Defines the behavior when a door is successfully toggled.

Syntax

DoorGroup:SetCallback(fn: function) β†’ DoorGroup

Parameters

Parameter Type Required Description
fn function Required Callback function(door, isOpen, player)

Callback Arguments

Argument Type Description
door Instance The door instance that was toggled
isOpen boolean The new state (true = open, false = closed)
player Player? The player who triggered it (nil for system calls)

Example

doors:SetCallback(function(door, isOpen, player)
    -- Animate the door
    door.Transparency = isOpen and 0.8 or 0
    door.CanCollide = not isOpen
    
    -- Play sound
    if isOpen then
        door.OpenSound:Play()
    else
        door.CloseSound:Play()
    end
    
    -- Log who opened it
    if player then
        print(player.Name .. " toggled " .. door.Name)
    end
end)

SetDeniedCallback()

Defines the behavior when access is denied (locked or missing key).

Syntax

DoorGroup:SetDeniedCallback(fn: function) β†’ DoorGroup

Parameters

Parameter Type Required Description
fn function Required Callback function(door, player, reason)

Callback Arguments

Argument Type Description
door Instance The door instance
player Player The player who was denied access
reason string "Locked" or "MissingKey"

Example

doors:SetDeniedCallback(function(door, player, reason)
    if reason == "Locked" then
        warn(player.Name .. " tried to open locked door: " .. door.Name)
        -- Play error sound
        door.ErrorSound:Play()
    elseif reason == "MissingKey" then
        -- Send notification to player
        game.ReplicatedStorage.Notify:FireClient(player, "You need a keycard!")
    end
end)

OpenAll()

Opens all doors in the group instantly.

Syntax

DoorGroup:OpenAll() β†’ DoorGroup

Example

-- Emergency evacuation: open all doors
doors:OpenAll()

-- Chain with other methods
doors:UnlockAll():OpenAll()

CloseAll()

Closes all doors in the group instantly.

Syntax

DoorGroup:CloseAll() β†’ DoorGroup

Example

-- Lockdown protocol
doors:CloseAll():SetLockedAll(true)

SetLocked()

Sets the lock state of a specific door.

Syntax

DoorGroup:SetLocked(door: Instance, isLocked: boolean) β†’ DoorGroup

Parameters

Parameter Type Required Description
door Instance Required The door instance to lock/unlock
isLocked boolean Required true to lock, false to unlock

Example

-- Lock a specific door
local mainDoor = workspace.Doors.MainEntrance
doors:SetLocked(mainDoor, true)

-- Unlock it later
doors:SetLocked(mainDoor, false)

SetLockedAll()

Sets the lock state of all doors in the group.

Syntax

DoorGroup:SetLockedAll(isLocked: boolean) β†’ DoorGroup

Parameters

Parameter Type Required Description
isLocked boolean Required true to lock all, false to unlock all

Example

-- Security lockdown
doors:SetLockedAll(true)

-- End lockdown
doors:SetLockedAll(false)

Unlock()

Unlocks a specific door (convenience method).

Syntax

DoorGroup:Unlock(door: Instance) β†’ DoorGroup

Parameters

Parameter Type Required Description
door Instance Required The door instance to unlock

Example

doors:Unlock(workspace.Doors.MainEntrance)

UnlockAll()

Unlocks all doors in the group (convenience method).

Syntax

DoorGroup:UnlockAll() β†’ DoorGroup

Example

doors:UnlockAll()

Configuration

The configuration table passed to DoorSystem.new() accepts the following options:

Option Type Required Description
RequiredKey string Optional Name of tool/item required in player's character to open doors
PromptProps table Optional Properties to apply to ProximityPrompts

PromptProps Options

Any valid ProximityPrompt property can be set. Common options:

Property Type Description
ActionText string Text shown on the prompt
HoldDuration number Seconds player must hold to trigger
KeyboardKeyCode Enum Keyboard key to trigger prompt
ObjectText string Name of the object being interacted with

Example Configuration

local config = {
    RequiredKey = "SecurityCard",  -- optional
    PromptProps = {                 -- optional
        ActionText = "Access Panel",
        ObjectText = "Security Door",
        HoldDuration = 2,
        KeyboardKeyCode = Enum.KeyCode.E
    }
}

local doors = DoorSystem.new(workspace.SecureDoors, config)

Examples

Basic Door System

local DoorSystem = require(game.ServerScriptService.DoorSystem)

-- Simple doors that just change transparency
local basicDoors = DoorSystem.new(workspace.BasicDoors)
    :SetCallback(function(door, isOpen)
        door.Transparency = isOpen and 0.8 or 0
        door.CanCollide = not isOpen
    end)

Secure Area with Keycard

-- Doors that require a keycard
local secureDoors = DoorSystem.new(workspace.SecureArea, {
    RequiredKey = "Keycard",
    PromptProps = {
        ActionText = "Scan Keycard",
        HoldDuration = 1
    }
})
    :SetCallback(function(door, isOpen, player)
        door.Transparency = isOpen and 0.5 or 0
        door.CanCollide = not isOpen
        door.AccessLight.Color = isOpen and Color3.new(0, 1, 0) or Color3.new(1, 0, 0)
    end)
    :SetDeniedCallback(function(door, player, reason)
        if reason == "MissingKey" then
            print(player.Name .. " needs a keycard!")
            door.ErrorSound:Play()
        end
    end)

Emergency Lockdown System

local allDoors = DoorSystem.new(workspace.AllDoors)
    :SetCallback(function(door, isOpen)
        door.Transparency = isOpen and 0.7 or 0
        door.CanCollide = not isOpen
    end)

-- Trigger lockdown on event
game.ReplicatedStorage.EmergencyLockdown.Event:Connect(function()
    print("🚨 LOCKDOWN INITIATED")
    
    allDoors
        :CloseAll()           -- Close all doors
        :SetLockedAll(true)   -- Lock them
    
    -- Unlock after 60 seconds
    task.delay(60, function()
        print("βœ… Lockdown lifted")
        allDoors:SetLockedAll(false)
    end)
end)

Multiple Door Groups

-- Public areas - no restrictions
local publicDoors = DoorSystem.new(workspace.Public, {
    PromptProps = { ActionText = "Open/Close" }
})
    :SetCallback(function(door, isOpen)
        door.Transparency = isOpen and 0.8 or 0
        door.CanCollide = not isOpen
    end)

-- Staff areas - require staff pass
local staffDoors = DoorSystem.new(workspace.StaffOnly, {
    RequiredKey = "StaffPass",
    PromptProps = {
        ActionText = "Staff Access",
        HoldDuration = 0.5
    }
})
    :SetCallback(function(door, isOpen, player)
        door.Transparency = isOpen and 0.5 or 0
        door.CanCollide = not isOpen
        if player then
            print("Staff access: " .. player.Name)
        end
    end)
    :SetDeniedCallback(function(door, player)
        warn("Unauthorized access attempt by " .. player.Name)
    end)

-- Admin vault - require admin key + longer hold
local vaultDoors = DoorSystem.new(workspace.Vault, {
    RequiredKey = "AdminKey",
    PromptProps = {
        ActionText = "Admin Access",
        HoldDuration = 3
    }
})
    :SetCallback(function(door, isOpen, player)
        door.Transparency = isOpen and 0.3 or 0
        door.CanCollide = not isOpen
        door.AlarmLight.Enabled = isOpen
        if isOpen and player then
            warn("⚠️ VAULT OPENED BY: " .. player.Name)
        end
    end)

Timed Auto-Close Doors

local autoDoors = DoorSystem.new(workspace.AutoDoors)
    :SetCallback(function(door, isOpen)
        door.Transparency = isOpen and 0.8 or 0
        door.CanCollide = not isOpen
        
        -- Auto-close after 5 seconds
        if isOpen then
            task.delay(5, function()
                -- Re-close the door by finding it in the group
                local doorGroup = autoDoors
                local id = doorGroup.InstanceToId[door]
                if id then
                    doorGroup:_setState(id, false)
                    door:SetAttribute("IsOpen", false)
                    -- Trigger callback
                    door.Transparency = 0
                    door.CanCollide = true
                end
            end)
        end
    end)

Sound Effects and Animations

local animatedDoors = DoorSystem.new(workspace.AnimatedDoors)
    :SetCallback(function(door, isOpen, player)
        local tween = game:GetService("TweenService")
        local info = TweenInfo.new(0.5, Enum.EasingStyle.Quad)
        
        if isOpen then
            -- Slide door to the side
            tween:Create(door, info, {CFrame = door.CFrame * CFrame.new(0, 0, -5)}):Play()
            door.OpenSound:Play()
        else
            -- Slide back to original position
            tween:Create(door, info, {CFrame = door.CFrame * CFrame.new(0, 0, 5)}):Play()
            door.CloseSound:Play()
        end
        
        door.CanCollide = not isOpen
    end)

Best Practices

1. Organize Doors in Folders

Group related doors in workspace folders for better organization and independent control:

Workspace
β”œβ”€β”€ PublicDoors
β”œβ”€β”€ SecureDoors
└── AdminDoors

2. Use Method Chaining

All methods return the DoorGroup, allowing for clean, fluent code:

doors
    :SetCallback(openCallback)
    :SetDeniedCallback(deniedCallback)
    :UnlockAll()

3. Separate Logic from Aesthetics

Define your callbacks separately for better maintainability:

local Callbacks = {
    Standard = function(door, isOpen)
        -- Animation logic here
    end,
    
    Secure = function(door, isOpen, player)
        -- Secure door logic here
    end
}

doors:SetCallback(Callbacks.Standard)

4. Handle Edge Cases

Always check if player exists when it might be nil:

:SetCallback(function(door, isOpen, player)
    if player then
        print(player.Name .. " opened the door")
    else
        print("System opened the door")
    end
end)

5. Use task.spawn for Callbacks

Callbacks are automatically spawned in new threads to prevent yielding. You can safely use wait() or other yielding functions inside callbacks.

Performance Note: Each DoorGroup allocates isolated memory buffers. For optimal performance, group related doors together rather than creating individual groups for each door.

Technical Details

Performance Characteristics

  • State Operations: O(1) using bit manipulation
  • Lock Operations: O(1) using separate lock buffer
  • Memory per Door: 1 bit for state + 1 bit for lock = 2 bits
  • Buffer Size: ceil(doorCount / 8) bytes per buffer

Architecture

DoorSystem uses Data-Oriented Design (DOD) principles:

  • Isolated memory allocation per door group
  • Bit-packed state storage for cache efficiency
  • Weak-keyed instance registry for O(1) lookups
  • Native Luau optimization hints (@native)

Attributes

Each door automatically gets an IsOpen attribute that reflects its current state. You can read this attribute from client scripts:

-- Client script
local door = workspace.Doors.MainDoor
print(door:GetAttribute("IsOpen"))  -- true or false