Automated Doors

I’ve made some automated doors and decided to share them with you.
I’m not a good coder, so please do tell me if you find something odd or just overall improvements.

StarfallEx Automated Door

How to use:
put main chip on a door, once it is set up, you can add as much doors as you want using the slave door code.

This code is pretty simple to set-up just put the chip on a faded door and you should be good to go.
default commands:

adds or removes a player from the whitelist (all 4 do the same thing):
!up <name>
!update <name>
!updateplayer <name>
!addremove <name>

hides or removes the chip:
- !toggleview

update: better code, added option for more doors.
WIP: key use functionality

Code:

Main Door Code:

[email protected] Automated Door
[email protected]

local prefs = prefs or {}
local whitelist = whitelist or {}
local whitelisted_entity_table

-- the entity that's welded to the chip.
local door = chip():isWeldedTo()

-- salve doors list
local doors = doors or {}

if not isValid(door) then
    print(Color(255,0,0), "Couldn't find door, removing chip.")
    chip():remove()
end

-- initialization
whitelist[owner()] = 1

chip():setNocollideAll(true)

if not prefs.chip_visible then
    chip():setColor(chip():getColor():setA(0))
end

// prefs initialization
prefs.loop_interval = 0.25 -- loops every given time(in seconds)
prefs.collision = false -- used later for optimization
prefs.chip_visible = false

// preference customization
prefs.detection_range = 60 -- the distance from where the door should open.
prefs.open_with_key = false -- should the door open only when you press use key?

prefs.prefix = "!" -- set your prefix, leave blank if you dont want to use a prefix. 
prefs.commands = {
    update_player = "addremove", -- add or remove player from the list depending on its current state.

    show_list = "list", -- prints the whitelist.

    open_with_key = "toggleuse", -- should the door be opened only when you press use key?

    show_commands = "commands", -- prints all of the commands.
    
    toggle_chip_visible = "hidechip", -- will toggle the chip visibility
    
    add_slave_door = "dooradd", -- add another door to the whitelist
}

local function updatePlayer(ply) 
    whitelist[ply] = !whitelist[ply] 
end

local function printCommands()
    print(Color(255,70,70), "Availabe Commands:")
    for _, v in pairs(prefs.commands) do
        print(Color(70), "- " .. prefs.prefix .. v)
    end
end

local function printWhitelist()
    print(Color(255,70,70), "Whitelist: ")
    for k, v in pairs(whitelist) do
        if not v then goto skip end
        print(Color(70), "  - " .. k:getName())
        ::skip:: -- will skip the print if the player is blacklisted.
    end
end

local function updateWhitelistedTable()
    -- this is a table of the whitelisted entities, unlike the whitelist table which is (entity, bool), this one is
    -- (index, entity), so we can use it in find.sortByclosest()
    whitelisted_entity_table =  find.allPlayers(function(ply)
        return whitelist[ply]
    end)

end

local function updateChipVisible()
    prefs.chip_visible = !prefs.chip_visible
    if not prefs.chip_visible then
        chip():setColor(chip():getColor():setA(0))
        return false
    end
    
    chip():setColor(chip():getColor():setA(255))
    
    return true
end

local function addDoor(ent)
    doors[ent] = !doors[ent] -- adds or removes door from the doors list.
   
    -- notify owner about change
    local message = doors[ent] and 
        "Added door to the list."
    or 
        "Removed door from the list."
    print(Color(255), message)   
end

-- this door will send the whitlist to the slave doors.
local function notifyDoorsAboutChange()
    if table.count(doors) < 1 then return end -- if there are no other doors, we dont need to notify.

    print(Color(0,255,0), "Notifying doors...")
    
    for v, k in pairs(doors) do
        if k then 
            hook.runRemote(v, whitelist)
        else 
            hook.runRemote(v, {})
        end
        
    end
end

// commands part
hook.add("PlayerSay", "chat_commands", function(ply, text, team)
    if ply ~= owner() then return end -- we only care about what the owner says

    if text[1] ~= prefs.prefix then return end -- if its not going to be a command, we dont care.

    -- the trim part removes the prefix from the text, so if you type "!addremove" it will return just "addremove"
    -- this is to make it easier to compare to the commands.
    local text_array = string.explode(" ", string.trimLeft(text, prefs.prefix)) 

    -- add/remove player
    if text_array[1] == prefs.commands.update_player then
        if text_array[2] == nil then print(Color(255,0,0), "invalid name") return false end
        
        local targetPlayer = find.playersByName(text_array[2], false, false) -- the target player that you want to add or remove.

        if #targetPlayer < 1 then print(Color(255,0,0), "cant find player") return false end -- check if theres a player with given name.

        -- if the player is whitelisted, blacklist him. and vice versa.
        updatePlayer(targetPlayer[1])
            
        -- update the entity whitelist
        updateWhitelistedTable()
        
        -- notify slave doors
        notifyDoorsAboutChange()
        
         -- notify owner about change
        local message = whitelist[targetPlayer[1]] and 
            "Added " .. targetPlayer[1]:getName() 
        or 
            "Removed " .. targetPlayer[1]:getName()
        print(Color(255), message)
        
        return false
    end

    -- show commands
    if text_array[1] == prefs.commands.show_commands then
        printCommands()

        return false
    end

    -- show  whitelist
    if text_array[1] == prefs.commands.show_list then
        printWhitelist()

        return false
    end

    -- toggle key use
    if text_array[1] == prefs.commands.open_with_key then
        prefs.open_with_key = !prefs.open_with_key
        
        -- notify owner about change
        local message = prefs.open_with_key and 
            "Use door is now " .. "enabled"
        or 
            "Use door is now " .. "disabled"
        print(Color(255), message)
        
        return false
    end
    
    if text_array[1] == prefs.commands.toggle_chip_visible then
        local state = updateChipVisible()

        -- notify owner about change
        local message = state and 
            "Chip is now " .. "visible"
        or 
            "Chip is now " .. "hidden"
        print(Color(255), message)
        
        return false
    end
    
    -- add door
    local ply_eyetrace = owner():getEyeTrace().Entity
    if text_array[1] == prefs.commands.add_slave_door then
        -- check if the entity the owner is trying to add is a chip
        if ply_eyetrace:getClass() ~= "starfall_processor" then 
            print(Color(255,0,0), "This is not a Starfall Processor.") 
            return false
        end
        
        -- if the chip is not owner's, we dont care.
        if ply_eyetrace:getOwner() ~= owner() then 
            print(Color(255,0,0), "You are not the owner of this chip.") 
            return false
        end
        
        -- if user is trying to add this chip to the list.
        if ply_eyetrace == chip() then 
            print(Color(255,0,0), "Cant add main chip")
            return false
        end
        
        addDoor(ply_eyetrace) -- add or remove door from doors list     
        
        -- notify slave doors
        notifyDoorsAboutChange()
        
        return false
    end
    
end)


updateWhitelistedTable()
-- loop for detecting closest player.
timer.create("cheese", prefs.loop_interval, 0, function()
    if #whitelisted_entity_table < 1 then return end 
    
    -- closest player to the chip
    local closest_player = find.sortByClosest(whitelisted_entity_table, chip():getPos())[1]
    
    -- get the distance of the closest player from the chip
    local distance_from_chip = (chip():getPos() - closest_player:getPos()):getLength2D()
    
    -- if you are far and the door is open, close it
    if prefs.collision and distance_from_chip > prefs.detection_range then
        door:setNocollideAll(false) -- sets the door collision
        prefs.collision = false -- used for optimization
        door:setColor(door:getColor():setA(255)) -- sets the door alpha to indicate collision

        return
    end
    
    -- if you are close and the door is closed, open it.
    if not prefs.collision and distance_from_chip <= prefs.detection_range then
        door:setNocollideAll(true)
        prefs.collision = true
        door:setColor(door:getColor():setA(100))

        return
    end
    
end)

Slave Door Code:

[email protected] Automated Door - Slave
[email protected]

local whitelist = whitelist or {}
local prefs = prefs or {}
local whitelisted_entity_table = whitelisted_entity_table or {}

local door = chip():isWeldedTo()

if not isValid(door) then
    print(Color(255,0,0), "Couldn't find door, removing chip.")
    chip():remove()
end

// prefs initialization
prefs.loop_interval = 0.25 -- loops every given time(in seconds)
prefs.collision = false -- used later for optimization
prefs.chip_visible = false

if not prefs.chip_visible then
    chip():setColor(chip():getColor():setA(0))
end

chip():setNocollideAll(true)

// preference customization
prefs.detection_range = 60 -- the distance from where the door should open.

-- this hook is called whenever the whitelist is changed.
hook.add("remote", "get_whitelist_from_main", function(sender, owner, list)
    whitelist = list
    whitelisted_entity_table = find.allPlayers(function(ply)
        return whitelist[ply]
    end)
end)


timer.create("cheese_slave", prefs.loop_interval, 0, function()
    if #whitelisted_entity_table < 1 then return end 
    
    -- closest player to the chip
    local closest_player = find.sortByClosest(whitelisted_entity_table, chip():getPos())[1]
    
    -- get the distance of the closest player from the chip
    local distance_from_chip = (chip():getPos() - closest_player:getPos()):getLength2D()
    
    -- if you are far and the door is open, close it
    if prefs.collision and distance_from_chip > prefs.detection_range then
        door:setNocollideAll(false) -- sets the door collision
        prefs.collision = false -- used for optimization
        door:setColor(door:getColor():setA(255)) -- sets the door alpha to indicate collision

        return
    end
    
    -- if you are close and the door is closed, open it.
    if not prefs.collision and distance_from_chip <= prefs.detection_range then
        door:setNocollideAll(true)
        prefs.collision = true
        door:setColor(door:getColor():setA(100))

        return
    end
    
end)

aight thats it, i kinda took some code ideas from people thanks and sorry for publishing if i took from you and you care :slight_smile:

1 Like

Really cool to see someone using Starfall for something in game already :smiley:, Nice.

Updated code for a way more optimized version yayyz
old trash code can be found in the pastebin link if you want to hurt yourself
thanks to some people for helping me figure out stuff.

1 Like