Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- chatFunctions = {}
- droneFunctions = {}
- aboutFunctions = {}
- -- startup functions -------------
- function startup()
- curVersion = "1.1"
- patchNotes = "Added patch notes and the new function to teleport back with the @tp command."
- systemName = "server helper"
- if fs.exists(systemName .. "/refuelCoords") then
- local file = fs.open(systemName .. "/refuelCoords","r")
- refuelCoords = {["x"] = tonumber(file.readLine()) ,["y"] = tonumber(file.readLine()), ["z"] = tonumber(file.readLine())}
- file.close()
- else
- term.clear()
- print("x:")
- local x = tonumber(read())
- print("y:")
- local y = tonumber(read())
- print("z:")
- local z = tonumber(read())
- local file = fs.open(systemName .. "/refuelCoords","w")
- file.writeLine(x)
- file.writeLine(y)
- file.writeLine(z)
- file.flush()
- file.close()
- refuelCoords = {["x"] = x ,["y"] = y, ["z"] = z}
- end
- if fs.exists(systemName .. "/firstStartupDate") then
- local file = fs.open(systemName .. "/firstStartupDate","r")
- firstStartupDate = file.readLine()
- file.close()
- else
- firstStartupDate = os.date()
- local file = fs.open(systemName .. "/firstStartupDate","w")
- file.write(firstStartupDate)
- file.flush()
- file.close()
- end
- createFiles()
- getPeripherals()
- onlinePlayers = playerDetector.getOnlinePlayers()
- scrollmenuLen={}
- scrollmenuInfos={}
- dropdown = {}
- dropdown["loaded"] = {}
- dropdown["loaded"]["len"] = 0
- givenfeedback = readFolder(programFolderName .. "/givenfeedback")
- playerData = {}
- sendTheseMessages = {}
- checkTeleportTimers = {}
- createChatCommands()
- createRanks()
- createSettings()
- loadPlayerData()
- createRankups()
- createScoreboard("playtime")
- createScoreboard("balance")
- getDroneData()
- createDroneActions()
- addTimeTimer = os.startTimer(60)
- checkJoinedPlayersTimer = os.startTimer(10)
- end
- function createDroneActions() -- Creates all drone actions (a drone action is a list of functions that the drone will perform one after the other)
- createDroneAction("refuel",{"teleport","standby"})
- createDroneAction("teleportPlayer",{"importPlayer","teleport","exportEntity"})
- end
- function getPeripherals() -- checks if all peripherals that are needed are connected to the computer and connects them
- chatBoxes = {}
- droneNames = {}
- for k,peripheralName in pairs(peripheral.getNames()) do
- if string.find(peripheralName,"playerDetector") then
- playerDetector = peripheral.wrap(peripheralName)
- end
- if peripheral.getType(peripheralName) == "modem" then
- rednet.open(peripheralName)
- end
- if string.find(peripheralName,"chatBox") then
- table.insert(chatBoxes, {peripheral = peripheral.wrap(peripheralName), cooldownTime = 0})
- end
- if string.find(peripheralName,"drone_interface") then
- table.insert(droneNames, peripheralName)
- end
- end
- if not playerDetector then
- error("No Player Detector found")
- end
- if table.maxn(chatBoxes) < 1 then
- error("No Chat Box found")
- end
- end
- function createFiles() -- Creates all for the program necessary files/folders
- programFolderName = systemName
- if not fs.exists(programFolderName .. "/playerData") then
- fs.makeDir(programFolderName .. "/playerData")
- end
- end
- function createRanks() -- Creates all player ranks
- playerRanks = {}
- rankNames = {}
- standardRank = "Beginner"
- createRank("Banned",0,{["canChangeOtherPlayersSettings"] = false})
- createRank("Beginner",1)
- createRank("Member",2)
- createRank("Elder",3)
- createRank("Supervisor",4)
- createRank("Admin",5,{["canChangeOtherPlayersSettings"] = true})
- createRank("Owner",6,{["canChangeOtherPlayersSettings"] = true})
- end
- function createChatCommands() -- creates all chat commands (a chat command is a function that can be called by typing its name together with an @ in the chat)
- chatCommands = {}
- chatCommandNames = {}
- createChatCommand("help",1, "Lists all chat commands. As the first parameter either enter a number to change the help page or specify the name of a chat command to only get info about that command.")
- createChatCommand("about",1, "If you enter it without any parameters it gives you a list of what you can get information about.")
- createChatCommand("giveFeedback",1, "You can use this chat command to report bugs/problems or also to give ideas about new chat commands or things like settings.")
- createChatCommand("listSettings",1, "Lists all your settings.")
- createChatCommand("changeSetting",1, "The first parameter either needs to be the name of a player or the name of a setting. If you enter the name of a player, then the setting of that player will be changed either your setting will be changed. After that just enter the value you want the setting to be changed to.")
- createChatCommand("balance",1, "Shows your balance. If you enter a player as the first parameter then it shows the balance of that player.")
- createChatCommand("pay",1, "Pays the player that you enter as the first parameter the amount of credits that you specified as the second parameter.")
- createChatCommand("playtimeScoreboard",1, "Shows the playtime scoreboard. If the first parameter is blank, then it shows your position, if it is a number, then it shows the page with that number.")
- createChatCommand("balanceScoreboard",1, "Shows the balance scoreboard. If the first parameter is blank, then it shows your position, if it is a number, then it shows the page with that number.")
- createChatCommand("tp",1, "You can either enter a player as the first parameter or you can enter the x, y and z coordinates of your destination. If you enter \"Back\" as the first parameter you will be teleported to your last teleport position. The chunk you teleport to needs to be loaded.")
- createChatCommand("setRank",5, "Sets the rank of the player specified in the first parameter to the rank specified in the second parameter.")
- createChatCommand("ban",5, "Bans the player specified in the first parameter.")
- createChatCommand("unban",5, "Unbans the player specified in the first parameter.")
- end
- function createSettings() -- creates all player settings
- settings = {}
- standardSettings = {}
- createSetting("disableJoinMessage",false,0, "Disables the joining message.")
- createSetting("disablePatchMessage",false,0, "Disables the patch notes notifications.")
- createSetting("disableAllMessages",false,0, "Disables all system messages (not recommended).")
- createSetting("canChangeOtherPlayersSettings",false,5, "Allows you, to change other players settings.")
- end
- function createRankups() -- creates all rankup conditions (such as how long you need to play to get a new rank)
- createRankup("Member", "playtime", 300)
- createRankup("Elder", "playtime", 3000)
- end
- function loadPlayerData() -- loads the data of all registered players
- playerNames = fs.list(programFolderName .. "/playerData")
- for k,playerName in pairs(playerNames) do
- getPlayerData(playerName)
- updateSettings(playerName)
- end
- end
- function updateSettings(playerName) -- checks if the settings of any player are outdated and changes them if necessary
- for settingName, settingValue in pairs(standardSettings) do
- if not playerData[playerName]["settings"][settingName] then
- playerData[playerName]["settings"][settingName] = settingValue
- end
- end
- for settingName, settingValue in pairs(playerData[playerName]["settings"]) do
- if not settings[settingName] then
- playerData[playerName]["settings"][settingName] = nil
- end
- end
- savePlayerData(playerName)
- end
- -------------------------------------
- -- main functions -------------------
- function main() -- the main function that runs the whole time and listens to events
- while true do
- os.startTimer(0.25)
- info1,info2,info3,info4 = os.pullEvent()
- performDroneActions()
- if info1 == "chat" and not isMessageDouble() then
- if not playerData[executingPlayer] then -- checks if player is registered
- getPlayerData(info2)
- end
- returnMessage,params = getChatCommand(info2,info3)
- if returnMessage then -- checks if the message was a chat command
- executingPlayer = info2
- if type(returnMessage) == "function" then -- checks if the chat command is valid
- local chatErrorMessage = returnMessage(params)
- if chatErrorMessage then
- sendMessage(chatErrorMessage,executingPlayer,"red")
- end
- else
- sendMessage(returnMessage,executingPlayer,"red") -- sends an error message
- end
- end
- end
- if info1 == "timer" then
- if info2 == addTimeTimer then
- addTime()
- checkRankups()
- giveMoney()
- end
- if info2 == checkJoinedPlayersTimer then -- checks if a player joined the server
- sendJoinMessages()
- checkJoinedPlayersTimer = os.startTimer(10)
- end
- end
- end
- end
- ------------------------------------
- -- Drone functions ------------------------------
- function getDroneData(droneName) -- loads all drone data from the files
- if not droneName then
- droneData = readFolder(programFolderName .. "/droneData")
- for k,droneName in pairs(droneNames) do
- if not droneData[droneName] then
- registerDrone(droneName)
- else
- droneData[droneName]["peripheral"] = peripheral.wrap(droneName)
- end
- end
- else
- droneData[droneName] = readFolder(programFolderName .. "/droneData/" .. droneName)
- if not droneData[droneName] then
- registerDrone(droneName)
- else
- droneData[droneName]["peripheral"] = peripheral.wrap(droneName)
- end
- end
- end
- function registerDrone(droneName) -- registers a new drone (creates all the files and stuff)
- local dronePeripheral = peripheral.wrap(droneName)
- if not dronePeripheral then
- error("Not a valid drone interface")
- end
- droneData[droneName] ={["hasWork"] = false, ["peripheral"] = dronePeripheral}
- setDroneAction(droneName,"refuel",{refuelCoords})
- saveDroneData(droneName)
- end
- function saveDroneData(droneName) -- saves the drone data in a file
- if droneName == "all" or (not droneData) then
- saveTable(programFolderName .. "/droneData",droneData)
- return
- end
- if not droneData[droneName] then
- registerDrone(droneName)
- return
- end
- saveTable(programFolderName .. "/droneData/" .. droneName, droneData[droneName])
- end
- function setDroneAction(droneName,action,params,controllingPlayer) -- sets the action of a drone
- if not droneData[droneName] then
- error("This drone does not exist.")
- end
- if controllingPlayer then
- if playerData[controllingPlayer]["lostDrone"] and action ~= "refuel" then
- sendMessage("Because you have lost a drone, you currently cant use drones. Please try again later.", controllingPlayer, "red")
- return false
- end
- end
- droneData[droneName]["hasWork"] = true
- droneData[droneName]["actionName"] = action
- droneData[droneName]["startedFunctions"] = 0
- droneData[droneName]["controllingPlayer"] = controllingPlayer
- droneData[droneName]["params"] = params or {}
- droneData[droneName]["startTime"] = os.epoch("local")
- return true
- end
- function createDroneAction(name, functions)
- if type(name) ~= "string" then
- error("name needs to be a string got " .. type(name))
- end
- if type(functions) ~= "table" then
- error("functions needs to be a table got " .. type(name))
- end
- droneActions = droneActions or {}
- local actionFunctions = {}
- for k,v in pairs(functions) do
- table.insert(actionFunctions,_ENV["droneFunctions"][v])
- end
- droneActions[name] = actionFunctions
- end
- function disconnectDrone(droneName) -- disconnects the drone (this drone will not be used anymore till its reconnected)
- if not droneData[droneName] then
- error("A drone named \"" .. droneName .. "\" does not exist." )
- end
- local controller = droneData[droneName]["controllingPlayer"]
- local file = fs.open(programFolderName .. "/disconnectedDrones", "a")
- if controller then
- file.write(os.date("local") .. ": The player \"" .. controller .. "\" has disconnected the drone named \"" .. droneName .. "\"")
- sendMessage("Your reputation decreased by 50, because you havent recovered the drone in time. To recover some of your lost reputation you can recover the drone at a later time.", controller, "red")
- playerData[controller]["lostDrone"] = nil
- giveReputation(controller, -50)
- else
- file.writeLine(os.date() .. ": The drone named \"" .. droneName .. "\" has been disconnected.")
- end
- file.flush()
- file.close()
- droneData[droneName] = {["isDisconnected"] = true, ["hasWork"] = false, ["peripheral"] = droneData[droneName]["peripheral"]}
- saveDroneData(droneName)
- end
- function performDroneActions() -- performs the drone actions of all drones
- for droneName,drone in pairs(droneData) do
- checkDroneStatus(droneName)
- if drone["hasWork"] then
- performDroneAction(droneName)
- end
- end
- end
- function performDroneAction(droneName) -- performs the drone action of the specified drone
- local dronePeriph = droneData[droneName]["peripheral"]
- if not dronePeriph.isConnectedToDrone() then -- checks if the drone is connected
- return "error"
- end
- if os.epoch("local") - droneData[droneName]["startTime"] > 120000 then -- Checks if the drone takes too long to perform its action
- finishAction(droneName)
- end
- if droneData[droneName]["startedFunctions"] == 0 then -- Starts the first function of the drone
- droneData[droneName]["startedFunctions"] = droneData[droneName]["startedFunctions"] + 1
- droneActions[droneData[droneName]["actionName"]][droneData[droneName]["startedFunctions"]](droneName, droneData[droneName]["params"][droneData[droneName]["startedFunctions"]])
- end
- if (not pcall(dronePeriph.isActionDone)) and droneData[droneName]["actionName"] then -- restarts the drone function if it got cancelled because of something like a server restart
- droneActions[droneData[droneName]["actionName"]][droneData[droneName]["startedFunctions"]](droneName, droneData[droneName]["params"][droneData[droneName]["startedFunctions"]])
- end
- if dronePeriph.isActionDone() then -- starts next function or completes the action
- if droneData[droneName]["startedFunctions"] == table.maxn(droneActions[droneData[droneName]["actionName"]]) then
- finishAction(droneName)
- return
- end
- droneData[droneName]["startedFunctions"] = droneData[droneName]["startedFunctions"] + 1
- droneActions[droneData[droneName]["actionName"]][droneData[droneName]["startedFunctions"]](droneName, droneData[droneName]["params"][droneData[droneName]["startedFunctions"]])
- saveDroneData(droneName)
- end
- end
- function finishAction(droneName, errorMessage) -- cancels/finishes the action of the drone
- if droneData[droneName]["controllingPlayer"] and droneData[droneName]["actionName"] ~= "refuel" then
- if errorMessage then
- sendMessage(errorMessage, droneData[droneName]["controllingPlayer"] ,"red")
- elseif checkPlayerTpFailure(droneName) then
- sendMessage("Teleportation failed, please only teleport to loaded chunks", droneData[droneName]["controllingPlayer"], "red")
- else
- sendMessage("The drone named \"" .. droneName .. "\" has finished its task.", droneData[droneName]["controllingPlayer"], "green")
- end
- end
- if droneData[droneName]["actionName"] == "refuel" then
- droneData[droneName]["startedFunctions"] = nil
- droneData[droneName]["hasWork"] = false
- droneData[droneName]["params"] = nil
- droneData[droneName]["actionName"] = nil
- droneData[droneName]["controllingPlayer"] = nil
- droneData[droneName]["actionName"] = nil
- droneData[droneName]["startTime"] = nil
- else
- refuelDrone(droneName, droneData[droneName]["controllingPlayer"])
- end
- saveDroneData(droneName)
- end
- function checkPlayerTpFailure(droneName) -- checks if the player that was teleported has reached his destination
- local playerName = droneData[droneName]["controllingPlayer"]
- if droneData[droneName]["actionName"] ~= "teleportPlayer" or not table.contains(playerDetector.getOnlinePlayers(), playerName) then
- return false
- end
- local x = droneData[droneName]["params"][droneData[droneName]["startedFunctions"]-1]["x"]
- local y = droneData[droneName]["params"][droneData[droneName]["startedFunctions"]-1]["y"]
- local z = droneData[droneName]["params"][droneData[droneName]["startedFunctions"]-1]["z"]
- local playerPos = playerDetector.getPlayerPos(playerName)
- local pX = playerPos["x"]
- local pY = playerPos["y"]
- local pZ = playerPos["z"]
- if not (pX > x-10 and pX < x+10 and pY > y-10 and pY < y+10 and pZ > z-10 and pZ < z+10) then
- droneFunctions.exportEntity(droneName)
- return true
- end
- end
- function checkDroneStatus(droneName) -- checks if the drone was disconnected/reconnected etc.
- checkDroneDisconnection(droneName)
- checkCancelledDroneDisconnection(droneName)
- checkDroneReconnection(droneName)
- end
- function checkDroneDisconnection(droneName) -- checks if the drone was disconnected
- if (not droneData[droneName]["peripheral"].isConnectedToDrone()) and (not droneData[droneName]["isDisconnected"]) then
- if not droneData[droneName]["disconnectTime"] and droneData[droneName]["controllingPlayer"] then
- sendMessage("The drone named \"" .. droneName .. "\" you were using has been disconnected, please recover the drone (replace it in the world) within 60 seconds, if you dont, and this happens too often, you will get banned.", droneData[droneName]["controllingPlayer"], "red")
- playerData[droneData[droneName]["controllingPlayer"]]["lostDrone"] = true
- savePlayerData(droneData[droneName]["controllingPlayer"])
- end
- if not droneData[droneName]["disconnectTime"] then
- droneData[droneName]["disconnectTime"] = os.epoch("local")
- saveDroneData(droneName)
- elseif os.epoch("local") - droneData[droneName]["disconnectTime"] > 60000 then
- disconnectDrone(droneName)
- end
- end
- end
- function checkCancelledDroneDisconnection(droneName) -- checks if the drone disconnection was cancelled
- if droneData[droneName]["disconnectTime"] and droneData[droneName]["peripheral"].isConnectedToDrone() then
- droneData[droneName]["disconnectTime"] = nil
- refuelDrone(droneName, droneData[droneName]["peripheral"].getOwnerName())
- if droneData[droneName]["controllingPlayer"] then
- sendMessage("The drone named \"" .. droneName .. "\" has been reconnected.", droneData[droneName]["controllingPlayer"], "green")
- playerData[droneData[droneName]["controllingPlayer"]]["lostDrone"] = nil
- savePlayerData(droneData[droneName]["controllingPlayer"])
- end
- end
- end
- function checkDroneReconnection(droneName) -- checks if the drone was reconnected
- if droneData[droneName]["isDisconnected"] and droneData[droneName]["peripheral"].isConnectedToDrone() then
- droneData[droneName]["isDisconnected"] = nil
- droneData[droneName]["disconnectTime"] = nil
- saveDroneData(droneName)
- refuelDrone(droneName, droneData[droneName]["peripheral"].getOwnerName())
- giveReputation(droneData[droneName]["peripheral"].getOwnerName(), 25)
- sendMessage("You have gained 25 reputation for reconnecting the drone named \"" .. droneName .. "\".", droneData[droneName]["peripheral"].getOwnerName(), "green")
- end
- end
- function refuelDrone(droneName,player) -- refuels the drone
- if not droneData[droneName] then
- error("The drone named " .. droneName .. " does not exist.")
- end
- setDroneAction(droneName,"refuel",{refuelCoords},player)
- end
- function getFreeDrone() -- gets the first free drone (a drone that currently does not perform an action)
- for droneName,drone in pairs(droneData) do
- if not drone["hasWork"] and not drone["isDisconnected"] then
- return droneName
- end
- end
- end
- function getConnectedDroneCount() -- gets the count of connected drones
- local count = 0
- for k,v in pairs(droneData) do
- if not v["isDisconnected"] then
- count = count + 1
- end
- end
- return count
- end
- function droneFunctions.teleport(droneName,params) -- teleports the drone to the specified coordinates
- if not params then
- finishAction(droneName, "The teleportation was stopped because of an unexpected error.")
- return
- end
- local dronePeriph = droneData[droneName]["peripheral"]
- local x = params["x"]
- local y = params["y"]
- local z = params["z"]
- dronePeriph.clearArea()
- dronePeriph.addArea(x,y,z)
- dronePeriph.abortAction()
- dronePeriph.setAction("goto")
- end
- function droneFunctions.standby(droneName) -- sets the drone to be on standby
- droneData[droneName]["peripheral"].abortAction()
- droneData[droneName]["peripheral"].setAction("standby")
- end
- function droneFunctions.importPlayer(droneName,params) -- picks up the player that is controlling the drone
- if not params then
- finishAction(droneName, "The player import was stopped because of an unexpected error.")
- return
- end
- local x1 = params["x"] - 3
- local y1 = params["y"] - 3
- local z1 = params["z"] - 3
- local x2 = params["x"] + 3
- local y2 = params["y"] + 3
- local z2 = params["z"] + 3
- local dronePeriph = droneData[droneName]["peripheral"]
- dronePeriph.clearArea()
- dronePeriph.addArea(x1,y1,z1,x2,y2,z2,"Filled")
- dronePeriph.clearWhitelistText()
- dronePeriph.clearBlacklistText()
- dronePeriph.addWhitelistText("player")
- dronePeriph.abortAction()
- dronePeriph.setAction("entity_import")
- end
- function droneFunctions.exportEntity(droneName) -- exports the entity that the drone is currently carrying
- local dronePeriph = droneData[droneName]["peripheral"]
- dronePeriph.clearWhitelistText()
- dronePeriph.clearBlacklistText()
- dronePeriph.clearArea()
- dronePeriph.addArea(dronePeriph.getDronePosition())
- dronePeriph.abortAction()
- dronePeriph.setAction("entity_export")
- end
- -------------------------------------------------
- -- Settings and data functions -------------------
- function getPlayerSetting(setting,player) -- get the value of the specified setting of the specified player
- if not playerData[player] then
- error(player .. " is not a registered player.")
- end
- if not settings[setting] then
- error(setting .. " is not a setting")
- end
- return playerData[player]["settings"][setting] or settings[setting]["standardValue"]
- end
- function createSetting(name,standardValue,requiredPermLevl,info) -- creates a player setting
- settings[name] = {}
- settings[name]["standardValue"] = standardValue
- settings[name]["requiredPermLevl"] = requiredPermLevl
- settings[name]["type"] = type(standardValue)
- settings[name]["info"] = info
- settingNames = settingNames or {}
- table.insert(settingNames,name)
- standardSettings[name] = standardValue
- end
- function changeSetting(player,setting,value) -- changes the setting of a player
- if not table.contains(playerNames,player) then
- error("not a viable player")
- end
- if not settings[setting] then
- error("not a viable setting")
- end
- if type(value) ~= settings[setting]["type"] then
- error("bad argument #3 (value supposed to have the type " .. settings[setting]["type"] .. " but has the type" .. type(value) .. ")")
- end
- playerData[player]["settings"][setting] = value
- saveTable(programFolderName .. "/playerData/" .. player .. "/settings", playerData[player]["settings"])
- end
- function addTime() -- adds playtime to all players
- for k,player in pairs(playerDetector.getOnlinePlayers()) do
- if not playerData[player] then -- registers the player if they are new
- getPlayerData(player)
- end
- playerData[player]["stats"]["playtime"] = playerData[player]["stats"]["playtime"] + 1
- if playerData[player]["stats"]["playtime"] % 60 == 0 then
- giveMoney(player, 150)
- end
- savePlayerData(player, "stats")
- updateScoreboard("playtime", player)
- end
- addTimeTimer = os.startTimer(60)
- end
- function updateScoreboard(data, player) -- updates position of the specified player in the specified scoreboard
- if not scoreboards[data] then
- error("This scoreboard does not exist")
- end
- local score = playerData[player]["stats"][data]
- local position = getScoreboardPosition(data, player)
- if not position then -- adds the player to the end of the scoreboard if they dont have a position yet
- table.insert(scoreboards[data], {["playerName"] = player, ["score"] = score})
- end
- local position = table.maxn(scoreboards[data])
- scoreboards[data][position]["score"] = score
- if position ~= 1 then
- while score > scoreboards[data][position-1]["score"] do -- ckecks if the score of the player is higher than the players in the spots over them
- table.remove(scoreboards[data], position)
- position = position - 1
- table.insert(scoreboards[data], position, {["playerName"] = player, ["score"] = score})
- if position == 1 then
- return
- end
- end
- end
- if scoreboards[data][position+1] then
- while score < scoreboards[data][position+1]["score"] do -- ckecks if the score of the player is lower than the players in the spots under them
- table.remove(scoreboards[data], position)
- position = position + 1
- table.insert(scoreboards[data], position, {["playerName"] = player, ["score"] = score})
- if not scoreboards[data][position+1] then
- return
- end
- end
- end
- end
- function getScoreboardPosition(data, player) -- gets the position of a specified player in a specified scoreboard
- if not scoreboards[data] then
- error("This scoreboard does not exist")
- end
- for k,v in pairs(scoreboards[data]) do
- if v["playerName"] == player then
- return k
- end
- end
- end
- function createScoreboard(data) -- creates a scoreboard (the variable data needs to be a index of the playerData[playerName]["stats"] table)
- scoreboards = scoreboards or {}
- local returnTable = {}
- local scores = {}
- local temporaryTable = {}
- for k,v in pairs(playerData) do
- temporaryTable[v["stats"][data]] = temporaryTable[v["stats"][data]] or {}
- table.insert(temporaryTable[v["stats"][data]], k)
- if not table.contains(scores, v["stats"][data]) then
- table.insert(scores,v["stats"][data])
- end
- end
- scores = sortScores(scores)
- local maxn = table.maxn(scores)
- for k,v in pairs(scores) do
- for k2,v2 in pairs(temporaryTable[v]) do
- table.insert(returnTable, table.maxn(returnTable)+1, {playerName = v2, score = v})
- end
- end
- scoreboards[data] = returnTable
- end
- function sortScores(scores) -- sorts the scores of a scoreboard in the right order
- local returnTable = {[1] = scores[table.maxn(scores)]}
- scores[table.maxn(scores)] = nil
- for k,v in pairs(scores) do
- local worked = false
- for k2,v2 in pairs(returnTable) do
- if v > v2 then
- table.insert(returnTable,k2 , v)
- worked = true
- break
- end
- end
- if not worked then
- table.insert(returnTable, v)
- end
- end
- return returnTable
- end
- ----------------------------------------
- -- player functions ---------------
- function getJoinedPlayer() -- checks if a player joined the server
- onlinePlayers = onlinePlayers or {}
- local returnTable = {}
- for k, playerName in pairs(playerDetector.getOnlinePlayers()) do
- if not table.contains(onlinePlayers, playerName) then
- table.insert(onlinePlayers, playerName)
- if playerData[playerName] then
- table.insert(returnTable, playerName)
- end
- end
- end
- return returnTable
- end
- function isPlayerOnline(player) -- checks if the player is online
- return table.contains(playerDetector.getOnlinePlayers(),player)
- end
- function giveReputation(player, amount) -- gives reputation to the player
- if not playerData[player]["stats"]["reputation"] then
- playerData[player]["stats"]["reputation"] = amount
- else
- playerData[player]["stats"]["reputation"] = playerData[player]["stats"]["reputation"] + amount
- end
- if playerData[player]["stats"]["reputation"] <= -100 and playerData[player]["rank"] ~= "Banned" then -- checks if the player should be banned
- banPlayer(player)
- elseif playerData[player]["stats"]["reputation"] > -100 and playerData[player]["rank"] == "Banned" then -- chekcs if the player should be unbanned
- unbanPlayer(player)
- end
- savePlayerData(player)
- end
- function unbanPlayer(player, unbanningPlayer) -- unbanns the specified player
- if unbanningPlayer then
- sendMessage("You have been unbanned from the " .. systemName .. " by " .. unbanningPlayer .. ".", player, "green")
- sendMessage("You have succesfully unbanned the player " .. player .. ".", unbanningPlayer, "green")
- setPlayerRank(player, getRankByPlaytime(player))
- else
- sendMessage("You have been unbanned from the " .. systemName .. ".", player, "green")
- setPlayerRank(player, getRankByPlaytime(player))
- end
- savePlayerData(player)
- end
- function banPlayer(player, banningPlayer) -- banns the specified player
- if banningPlayer then
- if getPermissionLevel(banningPlayer) > getPermissionLevel(player) then
- sendMessage("You have been banned from the " .. systemName .. " by " .. banningPlayer .. ". If you think this is unfair, please message someon of the rank of supervisor or higher.", player, "red")
- sendMessage("You have succesfully banned the player " .. player .. ".", banningPlayer, "green")
- setPlayerRank(player, "Banned")
- else
- sendMessage("Your permission level isnt high enaugh to ban this player.", banningPlayer, "red")
- end
- else
- sendMessage("You have been banned from the " .. systemName .. ". If you think this is unfair, please message someon of the rank of supervisor or higher.", player, "red")
- setPlayerRank(player, "Banned")
- end
- savePlayerData(player)
- end
- function getRankByPlaytime(playerName) -- checks what rank the player would have based on their playtime (used for unbannig)
- local curHighestRank = "Beginner"
- for rankupName,rankup in pairs(rankups) do
- if playerData[playerName]["stats"][rankup["statName"]] >= rankup["condition"] and playerRanks[curHighestRank]["permissionLevel"] < playerRanks[rankupName]["permissionLevel"] then
- curHighestRank = rankupName
- end
- end
- return curHighestRank
- end
- function giveMoney(player,amount) -- gives money to the specified player
- if not table.contains(playerNames,player) then
- return
- end
- if playerData[player]["stats"]["balance"] then
- playerData[player]["stats"]["balance"] = playerData[player]["stats"]["balance"] + amount
- else
- playerData[player]["stats"]["balance"] = amount
- end
- updateScoreboard("balance", player)
- sendMessage({"You have received ", {text = amount .. "c", color = "green"}, ".\nBalance: ", {text = playerData[player]["stats"]["balance"], color = "green"}},player)
- end
- function getPlayerData(player) -- gets the data of a player
- playerData[player] = {}
- if fs.exists(programFolderName .. "/playerData/" .. player) then
- playerData[player] = readFolder(programFolderName .. "/playerData/" .. player)
- else
- registerNewPlayer(player)
- end
- end
- function registerNewPlayer(player) -- registers a new player
- playerData[player]["rank"] = standardRank
- playerData[player]["settings"] = standardSettings
- playerData[player]["stats"] = {
- ["playtime"] = 0,
- ["balance"] = 250,
- ["reputation"] = 0
- }
- table.insert(playerNames,player)
- saveTable(programFolderName .. "/playerData",playerData)
- updateScoreboard("playtime", player)
- updateScoreboard("balance", player)
- sendMessage("Congratulations, you have been registered to the " .. systemName .. ", you can use it for things like teleporting, paying other players or getting stat ranklists. Type \"@help\" for more info.", player, "green")
- end
- function savePlayerData(player,saveWhat) -- saves the data of a player (if player is "all" then it saves the data of all players, if saveWhat is nil it saves the whole playerData)
- if player == "all" then
- for k,v in pairs(playerData) do
- savePlayerData(k, saveWhat)
- end
- else
- if saveWhat then
- if not playerData[player][saveWhat] then
- error(saveWhat .. "is not a existing playerData")
- end
- saveTable(programFolderName .. "/playerData/" .. player .. "/" .. saveWhat, playerData[player][saveWhat])
- else
- saveTable(programFolderName .. "/playerData/" .. player, playerData[player])
- end
- end
- end
- function setPlayerRank(player,rank) -- sets the rank of the specified player
- if not table.contains(playerNames,player) then
- error("bad argument #1 (" .. player .. " is not a viable player)")
- elseif not table.contains(rankNames,rank) then
- error("bad argument #1 (" .. rank .. " is not a viable rank)")
- end
- playerData[player]["rank"] = rank
- for k,v in pairs(playerRanks[rank]["settings"]) do
- playerData[player]["settings"][k] = v
- end
- savePlayerData(player)
- end
- function createRank(name,permissionLevel,rankSettings) -- creates a player rank (the rank settings are all the settings that will be changed when a player reaches that rank. its a table in the format {[settingName] = settingValue})
- if type(name) ~= "string" then
- error("bad argument #1 (name is supposed to be a string)")
- elseif type(permissionLevel) ~= "number" then
- error("bad argument #2 (permissionLevel is supposed to be a number)")
- end
- playerRanks[name] = {
- ["allowedChatCommands"] = allowedChatCommands,
- ["permissionLevel"] = permissionLevel,
- ["settings"] = rankSettings or {}
- }
- table.insert(rankNames,name)
- end
- function getPermissionLevel(player) -- gets the permission level of a player based on their rank
- return playerRanks[playerData[player]["rank"]]["permissionLevel"] or 0
- end
- function isPermLevelHigher(playerOne,playerTwo) -- checks if the permission level of playerOne is higher than that of player two
- return getPermissionLevel(playerOne) > getPermissionLevel(playerTwo)
- end
- function createRankup(rank, statName, condition) -- creates a rankup, players will automatically rank up to that rank if the player has the specified value of the data specified in statName
- rankups = rankups or {}
- rankups[rank] =
- {["statName"] = statName,
- ["condition"] = condition
- }
- end
- function checkRankups() -- checks if any of the online players are supposed to rank up
- for k,player in pairs(playerDetector.getOnlinePlayers()) do
- checkRankup(player)
- end
- end
- function checkRankup(player) -- checks if the specified player is supposed to rank up (if so they will get ranked up)
- for rankupName,rankup in pairs(rankups) do
- if playerData[player]["stats"][rankup["statName"]] == rankup["condition"] and playerRanks[rankupName]["permissionLevel"] > playerRanks[playerData[player]["rank"]]["permissionLevel"] then
- setPlayerRank(player, rankupName)
- return
- end
- end
- end
- -------------------------
- -- chat functions -------------
- function sendJoinMessages() -- sends a welcome message to all newly joined players, also sends the newest patchnotes if the player is only for the first time in the current version
- for k,playerName in pairs(getJoinedPlayer()) do
- if playerData[playerName] then
- if not getPlayerSetting("disableJoinMessage", playerName) then
- sendMessage({{text = "\nWelcome back to the server. For more info on the " .. systemName .. " enter @help.", hoverEvent = hoverMessage("shift + click to disable this message."), insertion = "@changeSetting disableJoinMessage true"}}, playerName, "green")
- end
- if playerData[playerName]["latestVersion"] ~= curVersion then
- playerData[playerName]["latestVersion"] = curVersion
- savePlayerData(playerName)
- if not getPlayerSetting("disablePatchMessage", playerName) then
- sendMessage({{text = "\nPatch notes " .. curVersion .. ":\n", hoverEvent = hoverMessage("shift + click to disable this message."), insertion = "@changeSetting disablePatchMessage true", color = "green"},{text = patchNotes, hoverEvent = hoverMessage("shift + click to disable this message."), insertion = "@changeSetting disablePatchMessage true" }}, playerName)
- end
- end
- end
- end
- end
- function isMessageDouble() -- checks if the chat event is double (if multiple chatboxes are connected to the same computer there will be multiple events for each message)
- if os.epoch("local") - (lastMessageTime or 0) < 100 and lastMessagePlayer == info2 then
- return true
- end
- lastMessageTime = os.epoch("local")
- lastMessagePlayer = info2
- end
- function createChatCommand(name,requiredPermLevl,info) -- creats a chat command, if someon types @[name] in the chat the function named chatFunctions.[name] will be executed
- if type(name) ~= "string" then
- error("bad argument #1 (name is supposed to be a string)")
- elseif type(requiredPermLevl) ~= "number" then
- error("bad argument #2 (requiredPermLevl is supposed to be a number)")
- elseif type(info) ~= "string" then
- error("bad argument #3 (info is supposed to be a string)")
- end
- chatCommands[name] = {
- ["requiredPermLevl"] = requiredPermLevl,
- ["function"] = _ENV["chatFunctions"][name],
- ["info"] = info
- }
- table.insert(chatCommandNames,name)
- end
- function getChatCommand(player,message) -- checks if the chat message was a chat command and also returns the parameters written into the chat if the message was a chat command
- if string.sub(message,1,1) == "@" then
- chatCommand = string.sub(message,2,(string.find(message," ") or 0) -1)
- if chatCommands[chatCommand] then
- if getPermissionLevel(player) >= chatCommands[chatCommand]["requiredPermLevl"] then
- messageRest = string.sub(message,string.len(chatCommand)+3)
- local params = {}
- i = 1
- while string.len(messageRest) ~= 0 do
- params[i] = string.sub(messageRest,1,(string.find(messageRest," ") or 0) -1)
- messageRest = string.sub(messageRest,string.len(params[i])+2)
- i = i+1
- end
- return chatCommands[chatCommand]["function"], params
- else
- return "You do not have permission to use this command."
- end
- else
- return "This command does not exist."
- end
- end
- end
- function sendMessage(message,player,color) -- sends a message to the specified player, the message can be a normal string or a table. For more info go to https://docs.advanced-peripherals.de/latest/peripherals/chat_box/#sendformattedmessage
- if not isPlayerOnline(player) then
- return false
- end
- if getPlayerSetting("disableAllMessages", player) then
- return false
- end
- table.insert(sendTheseMessages, {message = message, player = player, color = color or "white"})
- os.queueEvent("sendMessage")
- end
- function hoverMessage(message) -- returns the table used for a hoverEvent in the sendMessage function for more info also check https://docs.advanced-peripherals.de/latest/peripherals/chat_box/#sendformattedmessage
- return {action = "show_text",value = message}
- end
- function showScoreboard(data, player, page, extraText) -- shows the specified scoreboard to the specified player (in form of a chat message)
- if not scoreboards[data] then
- error("This scoreboard does not exist")
- return
- end
- local page = page or math.ceil(getScoreboardPosition(data, player)/10) -- sets the page to the page the executing player is on if the page isnt specified
- if not scoreboards[data][page*10-9] then
- sendMessage("This page does not exist", player, "red")
- return
- end
- local message = {"\n"}
- for i = 1,10 do
- position = (page-1)*10+i
- if not scoreboards[data][position] then
- break
- end
- table.insert(message, {text = "#" .. position .. " ", color = "green"})
- local color = "white"
- if scoreboards[data][position]["playerName"] == player then
- color = "green"
- elseif position == 1 then
- color = "#ffe400"
- elseif position == 2 then
- color = "#c0cbe4"
- elseif position == 3 then
- color = "#c46403"
- end
- table.insert(message, {text = scoreboards[data][position]["playerName"] .. ": " .. scoreboards[data][position]["score"] .. (extraText or "") .. "\n", color = color})
- end
- sendMessage(message, player)
- end
- function combineFormattedMessages(messages) -- a function used in the help chat command to format the message because im to lazy to do it properly
- local returnTable = {}
- for k,message in pairs(messages) do
- for k2, v in pairs(message) do
- table.insert(returnTable, v)
- end
- end
- return returnTable
- end
- function getOwnersText() -- returns a text about the owner*s of the system (used for the about sytem command)
- local owners = ""
- local ownerCount = 0
- for name,data in pairs(playerData) do
- if data["rank"] == "Owner" then
- ownerCount = ownerCount + 1
- if ownerCount == 1 then
- owners = name
- else
- owners = owners .. ", " .. name
- end
- end
- end
- local ownersText = {}
- if ownerCount == 1 then
- table.insert(ownersText, {text = "Owner: ", color = "green"})
- else
- table.insert(ownersText, {text = "Owners: ", color = "green"})
- end
- if ownerCount == 0 then
- table.insert(ownersText, "None")
- else
- table.insert(ownersText, owners)
- end
- return ownersText[1], ownersText[2]
- end
- function aboutFunctions.system() -- gives the executing player information about the system (in form of a chat message)
- local ownerOrOwners, ownerNames = getOwnersText()
- sendMessage({
- {text = "\nFirst startup date: ", color = "green"},
- firstStartupDate .. "\n",
- ownerOrOwners,
- ownerNames,
- {text = "\nRegistered player count: ", color = "green"},
- table.maxn(playerNames),
- {text = "\nConnected drone count: ", color = "green"},
- getConnectedDroneCount()
- }, executingPlayer)
- end
- function chatFunctions.setRank(params) -- chat function to set the rank of a player
- local player = params[1]
- local rank = params[2]
- if not table.contains(playerNames,player) then
- return "param #1 is supposed to be a registered player"
- end
- if not playerRanks[rank] then
- return "param #2 is not a viable rank"
- end
- if not (isPermLevelHigher(executingPlayer,player) or executingPlayer == player) then
- return "Your permission level is not high enough to change the rank of this player"
- end
- if playerData[player]["rank"] == rank then
- return "This player already has this rank"
- end
- if getPermissionLevel(executingPlayer) <= playerRanks[rank]["permissionLevel"] then
- return "Your permission level is not high enough to grant this rank"
- end
- setPlayerRank(player,rank)
- sendMessage("Rank succesfully changed to " .. rank, executingPlayer, "green")
- end
- function chatFunctions.changeSetting(params) -- chat function to change the setting of a player
- if playerData[params[1]] then
- player = params[1]
- setting = params[2]
- value = params[3]
- else
- player = executingPlayer
- setting = params[1]
- value = params[2]
- end
- if not table.contains(playerNames,player) then
- return "This player is not registered."
- end
- if not settings[setting] then
- return "This setting does not exist."
- end
- if getPermissionLevel(player) < settings[setting]["requiredPermLevl"] then
- return "Your permission level is not high enough to change this setting."
- end
- if not getPlayerSetting("canChangeOtherPlayersSettings", player) and player ~= executingPlayer then
- return "You do not have permission to change other players settings."
- end
- if player ~= executingPlayer and getPermissionLevel(player) >= getPermissionLevel(executingPlayer) then
- return "Your permission level is not high enaugh to change this players settings."
- end
- if settings[setting]["type"] == "boolean" then
- if string.lower(value) == "true" then
- value = true
- elseif string.lower(value) == "false" then
- value = false
- end
- elseif settings[setting]["type"] == "number" then
- value = tonumber(value)
- end
- if type(value) ~= settings[setting]["type"] then
- return "bad argument (value has the wrong type, expected type: ".. settings[setting]["type"] ..")"
- end
- if executingPlayer == player or (isPermLevelHigher(executingPlayer,player) and getPlayerSetting("canChangeOtherPlayersSettings")) then
- changeSetting(player,setting,value)
- sendMessage("The setting was succesfully changed.", executingPlayer, "green")
- end
- end
- function chatFunctions.help(params) -- chat function that gives the executing player information about the chat commands
- local returnMessage = nil
- local getHelpOnWhat = params[1]
- if tonumber(getHelpOnWhat) or not getHelpOnWhat then -- checks if a chat command to get information on was specified
- local sendThisMessage = {}
- local page = tonumber(getHelpOnWhat) or 1
- local numberOfCommands = 0
- if (page-1)*10+1 > table.maxn(chatCommandNames) then
- sendMessage("This page does not exist.", executingPlayer, "red")
- return
- end
- if page > 1 then
- table.insert(sendThisMessage, {{text = "\n<<<< Last page", color = "blue", hoverEvent = hoverMessage("shift + click to insert"), insertion = "@help " .. page-1}})
- end
- for k,commandName in pairs(chatCommandNames) do
- if numberOfCommands >= (page-1)*10 and numberOfCommands < page*10 then
- local info = chatCommands[commandName]["info"]
- if getPermissionLevel(executingPlayer) >= chatCommands[commandName]["requiredPermLevl"] then
- table.insert(sendThisMessage,
- {"\n",
- {text = "@" .. commandName, color = "green", insertion = "@" .. commandName, hoverEvent = hoverMessage(info .. "\nshift + click to insert")},
- {text = " - Required permission level: ", insertion = "@" .. commandName, hoverEvent = hoverMessage(info .. "\nshift + click to insert")},
- {text = chatCommands[commandName]["requiredPermLevl"], color = "green", insertion = "@" .. commandName, hoverEvent = hoverMessage(info .. "\nshift + click to insert")}})
- else
- table.insert(sendThisMessage,
- {"\n",
- {text = "@" .. commandName, color = "red", hoverEvent = hoverMessage("You dont have permission to use this command.")},
- {text = " - Required permission level: ", color = "red",hoverEvent = hoverMessage("You dont have permission to use this command.")},
- {text = chatCommands[commandName]["requiredPermLevl"], color = "red", hoverEvent = hoverMessage("You dont have permission to use this command.")}})
- end
- end
- numberOfCommands = numberOfCommands + 1
- end
- if (page)*10 < table.maxn(chatCommandNames) then
- table.insert(sendThisMessage, {{text = "\nNext page >>>>", color = "blue", hoverEvent = hoverMessage("shift + click to insert"), insertion = "@help " .. page+1}})
- end
- sendMessage(combineFormattedMessages(sendThisMessage), executingPlayer)
- return
- end
- if chatCommands[getHelpOnWhat] then
- sendMessage({"\n", {text = "@" .. getHelpOnWhat .. ": ", color = "green", insertion = "@" .. getHelpOnWhat, hoverEvent = {action = "show_text",value = "shift + click to insert"}}, {text = chatCommands[getHelpOnWhat]["info"] .. " ", insertion = "@" .. getHelpOnWhat, hoverEvent = {action = "show_text",value = "shift + click to insert"} }, {text = "Required permission level: " .. chatCommands[getHelpOnWhat]["requiredPermLevl"], color = "green", insertion = "@" .. getHelpOnWhat, hoverEvent = {action = "show_text",value = "shift + click to insert"}}}, executingPlayer)
- else
- return nil
- end
- end
- function chatFunctions.about(params) -- gives information about many things like ranks or the system
- local aboutWhat = params[1]
- availableInfo = availableInfo or {
- ["system"] = "Gives you information about the system."
- }
- if aboutWhat == nil then
- local message = {"Available params:"}
- for infoName,infoDescription in pairs(availableInfo) do
- table.insert(message, {text = "\n@about ", insertion = "@about " .. infoName, hoverEvent = hoverMessage(infoDescription .. "\nshift + click to insert")})
- table.insert(message, {text = infoName, insertion = "@about " .. infoName, hoverEvent = hoverMessage(infoDescription .. "\nshift + click to insert"), color = "green"})
- end
- sendMessage(message, executingPlayer)
- return
- end
- if not availableInfo[aboutWhat] then
- return "You cant get information about this"
- end
- _ENV["aboutFunctions"][aboutWhat]()
- end
- function chatFunctions.playtimeScoreboard(params) -- shows the executing player the playtime scoreboard
- showScoreboard("playtime", executingPlayer, params[1], " minutes")
- end
- function chatFunctions.listSettings() -- lists the settings of the executing player
- local message = {}
- local greenOrRed = {[true] = "green", [false] = "red"}
- for k,settingName in pairs(settingNames) do
- local settingValue = getPlayerSetting(settingName,executingPlayer)
- table.insert(message, "\n")
- if getPermissionLevel(executingPlayer) >= settings[settingName]["requiredPermLevl"] then
- table.insert(message, {text = settingName .. ": ", color = "green", insertion = "@changeSetting " .. settingName .. " ", hoverEvent = hoverMessage(settings[settingName]["info"] .. "\nshift + click to change")})
- table.insert(message, {text = settingValue, hoverEvent = hoverMessage(settings[settingName]["info"] .. "\nshift + click to change")})
- else
- table.insert(message, {text = settingName .. ": ", color = "red", hoverEvent = hoverMessage(settings[settingName]["info"] .. "\nYou dont have permission to change this setting.")})
- table.insert(message, {text = settingValue, hoverEvent = hoverMessage(settings[settingName]["info"] .. "\nYou dont have permission to change this setting.")})
- end
- end
- sendMessage(message, executingPlayer)
- end
- function chatFunctions.balance(params) -- tells the executing player what their balance is
- player = params[1] or executingPlayer
- if not playerData[player] then
- return "This is not a registered player."
- end
- sendMessage({"Balance: ", {text = (playerData[player]["stats"]["balance"] or 0) .. "c", color = "green"}}, executingPlayer)
- end
- function chatFunctions.pay(params) -- pays the receiving player the specified amount and removes that amount from the balance of the executing player
- local receivingPlayer = params[1]
- local amount = tonumber(params[2])
- if not playerData[receivingPlayer] then
- return "This is not a registered player."
- end
- if amount > playerData[executingPlayer]["stats"]["balance"] then
- return "Your balance is too low."
- end
- if amount < 0 then
- return "You cant pay someon less then zero credits."
- end
- playerData[receivingPlayer]["stats"]["balance"] = playerData[receivingPlayer]["stats"]["balance"] + amount
- playerData[executingPlayer]["stats"]["balance"] = playerData[executingPlayer]["stats"]["balance"] - amount
- savePlayerData(receivingPlayer, "stats")
- savePlayerData(executingPlayer, "stats")
- updateScoreboard("balance", receivingPlayer)
- updateScoreboard("balance", executingPlayer)
- sendMessage({"You succesfully paid ", receivingPlayer, " ", {text = amount .. "c", color = "green"}, "\n Balance: ", {text = playerData[executingPlayer]["stats"]["balance"] .. "c", color = "green"}}, executingPlayer)
- end
- function chatFunctions.balanceScoreboard(params) -- shows the executing player the balance scoreboard
- showScoreboard("balance", executingPlayer, params[1], "c")
- end
- function chatFunctions.tp(params) -- teleports the executing player to the specified coordinates
- local x,y,z = 0,0,0
- if table.contains(playerDetector.getOnlinePlayers(),params[1]) then
- if getPermissionLevel(executingPlayer) > 1 then
- local playerPos = playerDetector.getPlayerPos(params[1])
- x = playerPos["x"]
- y = playerPos["y"]
- z = playerPos["z"]
- else
- return "You can only tp to other players at Member rank or higher."
- end
- elseif string.lower(params[1]) == "back" then
- if not playerData[executingPlayer]["lastTpPos"] then
- return "You dont have a saved last teleport position."
- end
- x = playerData[executingPlayer]["lastTpPos"]["x"]
- y = playerData[executingPlayer]["lastTpPos"]["y"]
- z = playerData[executingPlayer]["lastTpPos"]["z"]
- else
- x = tonumber(params[1])
- y = tonumber(params[2])
- z = tonumber(params[3])
- end
- if type(x) ~= "number" then
- return "The first parameter needs to be either a player or a number."
- end
- if type(y) ~= "number" then
- return "The second parameter needs to be a number."
- end
- if type(z) ~= "number" then
- return "The third parameter needs to be a number."
- end
- local executingPlayerPos = playerDetector.getPlayerPos(executingPlayer)
- eX = executingPlayerPos["x"]
- eY = executingPlayerPos["y"]
- eZ = executingPlayerPos["z"]
- local droneName = getFreeDrone()
- if not droneName then
- sendMessage("There is currently no free drone available.", executingPlayer, "red")
- return
- elseif setDroneAction(droneName,"teleportPlayer",{{x=eX,y=eY,z=eZ},{x=x,y=y,z=z}},executingPlayer) then
- sendMessage("Please stand still until the teleportation is complete.", executingPlayer, "green")
- playerData[executingPlayer]["lastTpPos"] = {["x"]=eX,["y"]=eY,["z"]=eZ}
- savePlayerData(executingPlayer,"lastTpPos")
- end
- end
- function chatFunctions.ban(params) -- bans the specified player
- local player = params[1]
- if not playerData[player] then
- return "This is not a registered player."
- end
- if playerData[player]["rank"] == "Banned" then
- return "This player is already banned."
- end
- banPlayer(player, executingPlayer)
- end
- function chatFunctions.unban(params) -- unbans the specifed player
- local player = params[1]
- if not playerData[player] then
- return "This is not a registered player."
- end
- if playerData[player]["rank"] ~= "Banned" then
- return "This player is not banned."
- end
- unbanPlayer(player, executingPlayer)
- end
- function chatFunctions.giveFeedback(params) -- gives feedback about the system
- local feedback = ""
- for k,v in pairs(params) do
- feedback = feedback .. v .. " "
- end
- table.insert(givenfeedback,{["player"] = executingPlayer, ["feedback"] = feedback, ["date"] = os.date()})
- saveTable(programFolderName .. "/givenfeedback" ,givenfeedback)
- sendMessage("Thank you for giving feedback.", executingPlayer, "green")
- end
- ------------------------------------------------
- -- Other stuff
- function table.contains(inputTable,value) -- checks if the specified table contains a value
- for k,v in pairs(inputTable) do
- if v == value then
- return true
- end
- end
- return false
- end
- function saveTable(folderName,inputTable) -- saves the specifed table in files inside of the specified folder
- fs.delete(folderName)
- local file = false
- for k,v in pairs(inputTable) do
- if type(v) ~= "table" and type(v) ~= "function" then
- if not file then
- file = fs.open(folderName .. "/variables","w")
- end
- vType = type(v)
- if vType == "boolean" then
- if v then
- v = "true"
- else
- v = "false"
- end
- end
- file.writeLine(k .. string.sub(type(k),1,1) .. "=" .. string.sub(vType,1,1) .. v)
- elseif type(v) == "table" then
- saveTable(folderName .. "/" .. k,v)
- end
- end
- if file then
- file.flush()
- file.close()
- end
- end
- function readFile(fileName) -- reads a file created by the save table function and returns the saved table
- local file = fs.open(fileName,"r")
- local returnTable = {}
- if not file then
- return {}
- end
- repeat
- local curLine = file.readLine()
- local equalPos = string.find(curLine or "","=")
- if equalPos then
- local indexType = string.sub(curLine,equalPos-1,equalPos-1)
- local valueType = string.sub(curLine,equalPos+1,equalPos+1)
- local index = string.sub(curLine,1,equalPos-2)
- if indexType == "n" then
- index = tonumber(index)
- elseif indexType == "b" then
- if index == "true" then
- index = true
- else
- index = false
- end
- end
- local value = string.sub(curLine,equalPos+2)
- if valueType == "n" then
- value = tonumber(value)
- elseif valueType == "b" then
- if value == "true" then
- value = true
- else
- value = false
- end
- end
- returnTable[index] = value
- end
- until not curLine
- file.close()
- return returnTable
- end
- function readFolder(folderName)-- reads a folder created by the save table function and returns the saved table
- if not fs.isDir(folderName) then
- return {}
- end
- local returnTable = {}
- for k,v in pairs(fs.list(folderName)) do
- if fs.isDir(folderName .. "/" .. v) then
- if tonumber(v) then
- key = tonumber(v)
- elseif v == "true" or v == "false" then
- key = v == "true"
- else
- key = v
- end
- returnTable[key] = readFolder(folderName .. "/" .. v)
- else
- for k2,v2 in pairs(readFile(folderName .. "/" .. v)) do
- returnTable[k2] = v2
- end
- end
- end
- return returnTable
- end
- -------------------------------------------------
- noError, errorMessage = pcall(startup)
- if noError then
- noError, errorMessage = pcall(main)
- end
- if errorMessage ~= "Terminated" then
- print(noError)
- print(errorMessage)
- local curDate = string.gsub(os.date(),":",".")
- local file = fs.open("crashReports/" .. curDate,"w")
- file.write(errorMessage)
- file.flush()
- file.close()
- term.setTextColor(colors.red)
- print("REBOOTING")
- sleep(10)
- os.reboot()
- end
Add Comment
Please, Sign In to add comment