콘텐츠로 이동

디버그 액션

디버그 액션은 게임 서버 코드에 미리 등록해 두는 확인용 명령입니다. QA 담당자 분은 명령 팔레트(Ctrl+K)에서 액션을 선택하고 인자를 채워 실행할 수 있습니다.

  • 전달되는 것은 액션 이름과 서버가 다시 검사한 인자뿐이며, 코드는 전달되지 않습니다.
  • 등록한 액션이 없으면 도구를 켜도 이 기능으로 할 수 있는 일이 없습니다.
  • 액션마다 최소 레벨을 정할 수 있어서 아이템 지급, 순간이동, 밴 같은 일을 권한별로 나눌 수 있습니다.

Server.Action에 정의 테이블을 넘깁니다. 게임의 서버 Script에서 Start를 호출한 뒤에 등록해 주세요.

local Devplorer = require(game.ServerStorage.Devplorer.Server)
Devplorer.Action({
Name = "Give test tool",
Group = "Items",
Description = "Puts a test Tool into the target's Backpack.",
MinLevel = "MainTester",
Cooldown = 2,
Args = {
{ Name = "Target", Type = "Player", Default = "Self" },
{ Name = "Tool", Type = "Choice", Choices = { "Sword", "Flashlight", "Radio" } },
{ Name = "Count", Type = "Integer", Min = 1, Max = 5, Default = 1 },
},
Run = function(player: Player, args)
local backpack = args.Target:FindFirstChildOfClass("Backpack")
if backpack == nil then
Devplorer.ActionFail("the target has no Backpack yet")
end
for _ = 1, args.Count do
local tool = Instance.new("Tool")
tool.Name = args.Tool
tool.RequiresHandle = false
tool.Parent = backpack
end
return `gave {args.Count} {args.Tool} to {args.Target.Name}`
end,
})
  • 정의가 틀리면 Action이 바로 에러를 냅니다. 모르는 키(오타)도 에러입니다.
  • 같은 이름을 두 번 등록하면 에러입니다.
  • 등록은 Start를 호출한 것과 같은 환경의 서버 스크립트에서 해야 합니다. Actor 안이나 콘솔에서 require한 사본에서 등록하면 에러가 납니다.
필드 타입 기본값 설명
Name string 필수 이름. 60바이트까지.
Run (player, args) -> ... 필수 실행 함수.
Group string "General" 목록에서 묶는 이름. 40바이트까지.
Description string "" 설명. 300바이트까지.
MinLevel 레벨 "Developer" 이 레벨 이상만 보고 실행할 수 있습니다.
Args { ArgDef } 없음 인자 정의 목록. 16개까지.
Allow (player) -> any 없음 액션 자신의 허용 판정. 정확히 true일 때만 통과.
Check (player, args) -> () 없음 Run 전에 실행되는 인자 검사.
LiveCheck number 없음 초 단위. 지정하면 인자를 입력하는 동안에도 Check를 실행합니다. Check가 있어야 합니다. 0.2~60.
Confirm boolean 또는 string 없음 실행 전에 한 번 더 확인합니다. 문자열이면 그 내용을 표시합니다(200바이트까지).
Cooldown number 0.5 같은 사람이 같은 액션을 다시 실행할 수 있기까지의 초. 0~3600.
Timeout number 8 요청이 결과를 기다리는 초. 1~8.

세 가지를 모두 통과해야 액션이 보이고 실행됩니다. 요청마다 다시 검사합니다.

  1. 사람의 레벨이 MinLevel 이상.
  2. 액션의 Allow(player)가 정확히 true. (없으면 통과)
  3. Start의 ActionAllowed 후크가 정확히 true. (없으면 통과)

권한 밖의 액션은 목록에서 이름과 모양까지 가려집니다.

Args의 각 항목에는 Name과 Type이 있습니다. 인자 이름은 40바이트까지이고 서로 겹치면 안 됩니다. 모든 타입에 쓸 수 있는 키는 Name, Type, Description(300바이트까지), Optional, Default입니다.

  • Optional = true이면 비워 둘 수 있습니다. 비우면 args에 그 이름이 없습니다.
  • Default를 주면 비웠을 때 그 값을 씁니다.
  • 타입에 맞지 않는 키를 주면 등록할 때 에러가 납니다(예: Number에 MaxLength).
Type Run에서 받는 값 쓸 수 있는 키
String string MaxLength(기본 200, 최대 2000), Multiline
Number number Min, Max
Integer 정수 number Min, Max
Boolean boolean
Vector3 Vector3 Min, Max(성분마다)
Vector2 Vector2 Min, Max(성분마다)
Color3 Color3
Choice string Choices: 문자열 목록, 또는 목록을 돌려주는 함수
Enum EnumItem Enum: Roblox Enum 이름(예: "Material")
Player Player
UserId 양의 정수 number
Instance Instance Class(필수), Roots
  • Number, Integer, Vector: Min과 Max를 주지 않으면 절댓값 10억까지만 받습니다. Max를 항상 지정하는 것을 권합니다. 값은 유한해야 합니다.
  • String: 올바른 UTF-8이어야 하고 제어 문자는 거절합니다. Multiline = true이면 개행과 탭은 허용합니다.
  • Color3: 각 성분이 0~1이어야 합니다.
  • Choice: 실행할 때 목록을 다시 계산해 값이 들어 있는지 확인합니다. 함수로 지정하면 목록을 보낼 때와 실행할 때 호출합니다. 한 항목은 100바이트까지, 화면에는 1000개까지 전달합니다(나머지도 실행할 때는 통과합니다). Default는 목록에 있어야 합니다.
  • Enum: 없는 Enum 이름이면 등록할 때 에러가 납니다. Default는 지원하지 않습니다.
  • Player: 이 서버에 있는 플레이어입니다. Default로는 "Self"(실행한 사람)만 쓸 수 있습니다.
  • UserId: 이미 나간 사람을 지정할 때 유용합니다.
  • Instance: Class가 필수이고 IsA로 거릅니다. Roots에 인스턴스 목록을 주면 그 아래의 것만 받습니다. devplorer 자신과 Secret이 가리는 인스턴스는 늘 거절합니다. Default는 지원하지 않습니다.

Check(player, args)는 서버가 인자를 검사한 뒤, Run 전에 실행됩니다.

  • args는 얼린 사본이라 고칠 수 없습니다.
  • yield해도 되지만 2초 안에 끝나야 합니다. 넘으면 실행되지 않은 것으로 처리합니다. 사용한 시간만큼 Run의 제한 시간이 줄어듭니다.
  • nil(또는 true)을 돌려주면 통과입니다. false 같은 다른 값을 돌려주면 막힙니다.
  • 실행을 막을 때는 ArgFail이나 ActionFail을 호출하는 방법이 정식입니다.
  • Check가 막으면 Run은 실행되지 않으며 쿨다운도 되돌리지 않습니다.
  • Check가 끝난 뒤 실행 직전에 창, 레벨, Allow, ActionAllowed, Secret을 다시 확인합니다.
  • Lazy (기본): LiveCheck가 없으면 실행할 때만 검사합니다. 화면에는 실행 전까지 에러가 표시되지 않는다는 안내가 나타납니다.
  • Live: LiveCheck = 초를 지정하면 인자를 입력하는 동안에도 서버가 Check를 실행해 잘못된 칸을 표시합니다. 서버는 사람마다 그 간격(5% 오차 허용)보다 잦은 요청은 실행하지 않습니다.

Live 검사는 감사 기록에 남지 않습니다. 실행을 시도하면 Run 직전에 Check가 항상 다시 실행되고, 그때 기록됩니다.

Devplorer.Action({
Name = "Ban (demo)",
Group = "Moderation",
Description = "Demo only: prints instead of banning.",
MinLevel = "Developer",
Confirm = "Ban this user? (demo: prints only)",
Args = {
{ Name = "User", Type = "UserId" },
{ Name = "Reason", Type = "String", MaxLength = 100 },
},
Check = function(player: Player, args)
if args.User == player.UserId then
Devplorer.ArgFail("User", "you cannot ban yourself")
end
if #args.Reason < 3 then
Devplorer.ArgFail(2, "give a reason of at least 3 characters")
end
end,
Run = function(player: Player, args)
print(`demo ban of {args.User} by {player.Name}: {args.Reason}`)
return `would ban {args.User}`
end,
})
함수 쓰는 곳 효과
Devplorer.ActionFail(message) Check, Run 실행한 사람에게 message를 이유로 표시합니다.
Devplorer.ArgFail(arg, reason) Check, Run 특정 인자가 잘못되었다고 표시합니다. arg는 인자 번호(1부터) 또는 이름입니다. 화면에서 해당 칸이 빨갛게 바뀌고 이유가 표시됩니다.
  • 정의에 없는 번호나 이름이면 이유만 표시됩니다.
  • 이유 문구는 RedactLog를 거쳐 실행한 사람에게 그대로 전달됩니다. 대상의 등급처럼 민감할 수 있는 내용은 알려도 되는지 확인한 뒤 적어 주세요.
  • 이 두 함수 외의 에러는 서버 출력에만 자세히 남습니다. 실행한 사람은 Logs 능력이 있을 때만 (RedactLog를 거친) 에러 내용을 볼 수 있고, 없으면 action failed만 표시됩니다.
  • 서버가 인자를 스키마로 다시 검사한 뒤 별도 스레드에서 Run(player, args)를 실행합니다.
  • 반환값은 문자열로 변환되어 2000자까지, RedactLog를 거쳐 실행한 사람에게 전달됩니다.
  • 요청은 Timeout초까지 결과를 기다리고, 넘으면 아직 실행 중이라고 응답합니다. 스레드는 중단되지 않으며, 끝나면 서버 출력에 상태 한 줄을 남깁니다.
  • 동시 실행은 사람마다 2개, 서버 전체 16개까지입니다. Run이 끝나지 않아도 5분이 지나면 실행 슬롯을 비웁니다(스레드는 중단하지 않습니다).
  • 쿨다운은 사람마다, 액션마다 따로 계산합니다.
  • 실행할 때마다 Action 감사 기록이 남습니다. 서버 출력에는 액션 이름만 남고, 인자와 결과는 Audit의 Data로 전달됩니다.
local removed: boolean = Devplorer.RemoveAction("Give test tool")

RemoveAction은 등록을 지우고, 지웠으면 true를 돌려줍니다.

서버가 강제할 수 없어 개발자가 직접 챙겨야 하는 내용입니다.

  • 액션은 좁고 구체적으로 작성해야 합니다. 경로, 함수 이름, 코드를 인자로 받아 무엇이든 호출하는 액션은 코드 실행 경로가 됩니다.
  • Confirm은 화면에서의 확인일 뿐입니다. 되돌릴 수 없는 작업은 Run 안에서도 따로 막아야 합니다.
  • Player와 UserId 인자로는 더 높은 레벨의 사람도 선택할 수 있습니다. 밴이나 강퇴 같은 액션은 Check에서 대상을 직접 비교하고 ArgFail로 알려 주세요. Check와 Run 사이에 대상의 레벨이 바뀔 수 있으므로, 되돌릴 수 없는 작업은 Run에서도 다시 확인하는 것이 좋습니다.
  • Allow, ActionAllowed, 함수로 된 Choices는 목록을 요청할 때마다 모든 액션에 대해 호출됩니다. yield 없이 빠르게 끝나야 하며, DataStore나 HTTP를 호출하면 안 됩니다.
  • InvokeClient처럼 상대가 응답하지 않으면 끝나지 않는 호출은 Check에서 쓰면 안 됩니다.
  • Run은 실행이 끝나도록 작성해야 합니다. 제한 시간을 넘겨도 중단되지 않고, 권한이 철회되어도 이미 시작한 Run은 계속 실행됩니다.
  • 문자열 인자는 로그, 채팅, DataStore 키로 쓰기 전에 다시 정리해 주세요. 에러 문구에 그대로 넣으면 안 됩니다.
  • Run의 반환값과 ActionFail 문구에는 Secret으로 가린 인스턴스의 이름이나 경로, 개인정보를 넣으면 안 됩니다.
  • 동시 실행이 같은 정의를 공유하므로, Run에서 쓰는 모듈 수준 상태는 경쟁 상태가 될 수 있습니다.
  • Grant, Revoke, Reset을 액션 안에서 호출하면 안 됩니다. 액션을 실행할 권한이 곧 레벨을 주는 권한이 됩니다.
  • Action, RemoveAction, Grant 등을 클라이언트 입력으로 호출하면 안 됩니다.

클라이언트에서 실행되는 액션은 클라이언트 액션에서 다룹니다.