自定义饥荒服务器后台命令

本文最后更新于:2021-05-16 01:47

本教程适用Linux、Windows及Mac OS创建的专属服务器(Dedicated Server),也适用于客户端

背景

饥荒自带了很多命令,比如:c_save()c_rollback()TheNet:Ban()等等,详情请参见Console/Don’t Starve Together Commands

但是这些命令并不能满足我们的需求,这里我介绍一种不需要mod而添加自定义命令的方法,特别适用于纯净服

方法

  • 找到饥荒的存档目录,找到对应Cluster下的MasterCaves文件夹
  • MasterCaves文件夹下分别创建customcommands.lua
  • customcommands.lua内写入你想要添加的命令

举例

复活所有玩家

1
2
3
function res()
for i, v in ipairs(AllPlayers) do v:PushEvent('respawnfromghost') end
end

你在服务器后台或者游戏内控制台输入res()即可复活当前世界的所有玩家
注意:地面和地洞是分开的两个世界,在地面世界输入命令只对地面有效,地洞的玩家不会复活

清理一半的物品

1
2
3
4
5
6
7
8
9
10
11
12
function rmhalf(name)
local count = 0
for k,v in pairs(Ents) do
if v.prefab == name then
if math.random() < 0.5 then
v:Remove()
count = count + 1
end
end
end
print("removed", count, name)
end

比如,输入rmhalf("beefalo"),就可以清理一半的牛群

按百分比清理物品

1
2
3
4
5
6
7
8
9
10
11
12
function rmpart(name,percent)
local count = 0
for k,v in pairs(Ents) do
if v.prefab == name then
if percent and math.random() < percent then
v:Remove()
count = count + 1
end
end
end
print("removed", count, name)
end

比如,输入rmhalf("evergreen",0.8),就可以清理80%的常青树

清理地面的物品

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function rmog(name)
local count = 0
for k,v in pairs(Ents) do
if v.prefab == name then
if v.components.inventoryitem then
if v.components.inventoryitem.owner == nil then
v:Remove()
count = count + 1
end
else
v:Remove()
count = count + 1
end
end
end
print("removed", count, name)
end

比如,输入rmog("spoiled_food"),就可以清理地面上所有的腐烂的食物

清理烧毁的建筑及植物

1
2
3
4
5
6
7
8
9
10
function rmbt(name)
local count = 0
for k,v in pairs(Ents) do
if v.prefab == name and v:HasTag("burnt") then
v:Remove()
count = count + 1
end
end
print("removed", count, "burnt", name)
end

比如,输入rmbt("treasurechest")即可清理所有烧毁的箱子

清理虫木种在地上的作物腐烂后及枯萎后

1
2
3
4
5
6
7
8
9
10
11
12
function rmcrop()
local count = 0
for k,v in pairs(Ents) do
if v.prefab == "plant_normal_ground" then
if v:HasTag("rotten") or v:HasTag("withered") then
v:Remove()
count = count + 1
end
end
end
print("removed", count, "plant_normal_ground")
end

直接输入rmcrop()即可

显示当前世界的玩家

1
2
3
4
5
function list()
for i, v in ipairs(AllPlayers) do
print(string.format("[%d] (%s) %s <%s>", i, v.userid, v.name, v.prefab))
end
end

输入list()即可,注意:地面与地洞分开

显示当前服务器的所有玩家

1
2
3
4
5
6
7
8
9
10
function show()
local index = 0
for i, v in ipairs(TheNet:GetClientTable()) do
if index ~= 0 then
--print(' ['..index..'] {'..string.format('%03d', v.playerage)..'} ('..v.userid..') '..v.name..' <'..v.prefab..'>')
print(string.format("[%d] {%s} (%s) %s <%s>", index, string.format('%03d', v.playerage), v.userid, v.name, v.prefab))
end
index = index + 1
end
end

输入show()即可,输出结果[]内的为玩家的存活天数

服务器宣告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function say(msg, interval, category)
if msg == nil then
if TheWorld.__announcementtask ~= nil then
TheWorld.__announcementtask:Cancel()
TheWorld.__announcementtask = nil
end
elseif interval == nil or interval <= 0 then
if category == "system" then
TheNet:SystemMessage(msg)
else
TheNet:Announce(msg, nil, nil, category)
end
else
if TheWorld.__announcementtask ~= nil then
TheWorld.__announcementtask:Cancel()
end
TheWorld.__announcementtask =
TheWorld:DoPeriodicTask(
interval,
category == "system" and
function() TheNet:SystemMessage(msg) end or
function() TheNet:Announce(msg, nil, nil, category) end,
0
)
end
end

输入say("欢迎加入")即可发出相应内容的公告

计数

1
2
3
4
5
6
7
8
9
10
11
12
function count(prefab, noprint)
local count = 0
for k,v in pairs(Ents) do
if v.prefab == prefab then
count = count + 1
end
end
if not noprint then
print("There are ", count, prefab.."s in the world.")
end
return count
end

输入count("flint")即可打印出碎石的数量

计数所有物品

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
function countall()
local total = 0
local unk = 0
local counted = {}
for k,v in pairs(Ents) do
if v.prefab ~= nil then
if counted[v.prefab] == nil then
counted[v.prefab] = 1
else
counted[v.prefab] = counted[v.prefab] + 1
end
total = total + 1
else
unk = unk + 1
end
end

local function pairsByKeys (t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function () -- iterator function
i = i + 1
if a[i] == nil then return nil
else return a[i], t[a[i]]
end
end
return iter
end

for k,v in pairsByKeys(counted) do
print(k, v)
end

print(string.format("There are %d different prefabs in the world, %d total (and %d unknown)", GetTableSize(counted), total, unk))
end

输入countall()即可

计数所有在地面的物品

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
function countog()
local total = 0
local unk = 0
local counted = {}
for k,v in pairs(Ents) do
if v.prefab ~= nil then
if v.components.inventoryitem then
if v.components.inventoryitem.owner == nil then
if counted[v.prefab] == nil then
counted[v.prefab] = 1
else
counted[v.prefab] = counted[v.prefab] + 1
end
total = total + 1
end
else
if counted[v.prefab] == nil then
counted[v.prefab] = 1
else
counted[v.prefab] = counted[v.prefab] + 1
end
total = total + 1
end
else
unk = unk + 1
end
end

local function pairsByKeys (t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function () -- iterator function
i = i + 1
if a[i] == nil then return nil
else return a[i], t[a[i]]
end
end
return iter
end

for k,v in pairsByKeys(counted) do
print(k, v)
end

print(string.format("There are %d different prefabs on the ground, %d total (and %d unknown)", GetTableSize(counted), total, unk))
end

输入countog()即可打印所有在地面的物品、建筑及动植物(即不包括箱子里和玩家身上的物品)

显示世界天数即季节

1
2
3
4
5
function day()
print('World Day:', TheWorld.state.cycles + 1)
print('Season:', TheWorld.state.season)
print('Days Left in the Season:',TheWorld.state.remainingdaysinseason)
end

输入day()即可

按照自定义设置清理服务器

这条命令比较复杂,实现了类似其他服务器清理mod的功能,故不需要再订阅服务器清理mod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
local function count_current(prefab)
local count = 0
for k,v in pairs(Ents) do
if v.prefab == prefab then
if v.components.inventoryitem then
if v.components.inventoryitem.owner == nil then
count = count + 1
end
else
count = count + 1
end
end
end
return count
end

local function s_rmognum(name,maxnum)
local count = 0
for k,v in pairs(Ents) do
if v.prefab == name then
if v.components.inventoryitem then
if v.components.inventoryitem.owner == nil and count_current(name) > maxnum then
v:Remove()
count = count + 1
end
else
if count_current(name) > maxnum then
v:Remove()
count = count + 1
end
end
end
end
if count ~= 0 then
print("removed", count, name)
end
end

local rmlist = {
------------------------ 动 物 ------------------------
{"hound", 30}, -- 狗
{"firehound", 10}, -- 火狗
{"icehound", 10}, -- 冰狗
{"spider_warrior", 10}, -- 蜘蛛战士
{"spider", 10}, -- 蜘蛛
{"flies", 10}, -- 苍蝇
{"mosquito", 10}, -- 蚊子
{"bee", 10}, -- 蜜蜂
{"killerbee", 10}, -- 杀人蜂
{"frog", 20}, -- 青蛙
{"beefalo", 50}, -- 牛
{"grassgekko", 15}, -- 草蜥蜴
{"lightninggoat", 50}, -- 羊
{"deer", 50}, -- 鹿
------------------------ 地面 物体 ------------------------
{"evergreen_sparse", 250}, -- 常青树
{"twiggytree", 150}, -- 树枝树
{"marsh_tree", 100}, -- 针刺树
{"rock_petrified_tree", 1000}, -- 石化树
{"skeleton_player", 50}, -- 玩家尸体
{"spiderden", 80}, -- 蜘蛛巢
{"burntground", 50}, -- 陨石痕跡
------------------------ 可拾取物品 ------------------------
--{"seeds", 0}, -- 种子
--{"log", 0}, -- 木头
--{"pinecone", 0}, -- 松果
--{"twiggy_nut", 0}, -- 多枝树的果实
--{"cutgrass", 0}, -- 草
--{"twigs", 0}, -- 树枝
--{"rocks", 100}, -- 石头
--{"nitre", 100}, -- 硝石
--{"flint", 100}, -- 燧石
{"poop", 0}, -- 屎
{"guano", 0}, -- 鸟屎
{"manrabbit_tail", 0}, -- 兔毛
{"silk", 50}, -- 蜘蛛丝
{"spidergland", 50}, -- 蜘蛛腺体
{"stinger", 0}, -- 蜂刺
{"houndstooth", 0}, -- 狗牙
{"mosquitosack", 0}, -- 蚊子血袋
--{"glommerfuel", 0}, -- 格罗姆粘液
{"slurtleslime", 0}, -- 鼻涕虫粘液
{"slurtle_shellpieces", 0}, -- 鼻涕虫壳碎片
{"charcoal", 0}, -- 炭
{"rottenegg", 0}, -- 坏蛋
{"horn", 5}, -- 牛角
{"beardhair", 0}, -- 胡须
{"beefalowool", 0}, -- 牛毛
{"feather_crow", 0}, -- 羽毛
{"feather_robin", 0}, -- 羽毛
{"feather_robin_winter", 0}, -- 羽毛
{"spoiled_food", 0}, -- 腐烂食物
{"sketch", 0}, -- 草图
{"blueprint", 0}, -- 蓝图
{"backpack", 0}, -- 背包
{"piggyback", 0}, -- 小猪包
{"candybag", 0}, -- 糖果包
{"compass", 0}, -- 指南針
{"bedroll_furry", 0}, -- 兔毛席子
{"bedroll_straw", 0}, -- 草席
{"axe", 3}, -- 斧子
{"goldenaxe", 3}, -- 黄金斧子
{"torch", 0}, -- 火炬
{"pickaxe", 3}, -- 镐子
{"goldenpickaxe", 3}, -- 黄金镐子
{"hammer", 3}, -- 锤子
{"shovel", 3}, -- 铲子
{"goldenshovel", 3}, -- 黄金铲子
{"razor", 1}, -- 剃刀
{"pitchfork", 0}, -- 草叉
{"bugnet", 0}, -- 捕虫网
{"fishingrod", 0}, -- 鱼竿
{"umbrella", 0}, -- 雨伞
{"earmuffshat", 0}, -- 兔耳罩
{"winterhat", 0}, -- 冬帽
--{"heatrock", 5}, -- 热能石
{"strawhat", 0}, -- 草帽
{"tophat", 0}, -- 高礼帽
{"featherhat", 0}, -- 羽毛帽
{"beehat", 0}, -- 蜜蜂帽
{"spiderhat", 0}, -- 女王帽
{"bushhat", 0}, -- 浆果丛帽
{"trap", 10}, -- 动物陷阱
{"birdtrap", 3}, -- 鸟陷阱
{"spear", 0}, -- 矛
{"boomerang", 0}, -- 回旋镖
--{"nightsword", 10}, -- 影刀
{"ruins_bat", 0}, -- 铥矿棒
--{"spear_wathgrithr", 0}, -- 女武神长矛
{"armorgrass", 0}, -- 草甲
{"armormarble", 0}, -- 大理石甲
--{"armor_sanity", 10}, -- 影甲
{"armorsnurtleshell", 0}, -- 蜗牛甲
{"armorwood", 0}, -- 木甲
{"armordragonfly", 0}, -- 蜻蜓甲
{"armor_bramble", 0}, -- 荆棘甲
{"footballhat", 0}, -- 猪皮帽
{"slurtlehat", 0}, -- 蜗牛帽
--{"wathgrithrhat", 0}, -- 女武神头盔
--{"firestaff", 0}, -- 火魔杖
--{"icestaff", 0}, -- 冰魔杖
{"chesspiece_deerclops_sketch", 0}, -- 四季 boss 棋子图
{"chesspiece_bearger_sketch", 0},
{"chesspiece_moosegoose_sketch", 0},
{"chesspiece_dragonfly_sketch", 0},
--{"shadowheart", 3}, -- 影心
{"oar", 0}, -- 桨
{"oar_driftwood", 0}, -- 桨
{"antliontrinket", 0}, -- 蚁狮掉落物
------------------------ 厨师的物品 ------------------------
{"portablecookpot_item", 0},
{"portableblender_item", 0},
{"portablespicer_item", 0},
}

--冬季盛宴
local function winterfeast_rmlist()
for i=1,9 do table.insert(rmlist, {"winter_food"..i, 0}) end
for i=1,12 do table.insert(rmlist, {"winter_ornament_plain"..i, 0}) end
for i=1,8 do table.insert(rmlist, {"winter_ornament_fancy"..i, 0}) end
for i=1,8 do table.insert(rmlist, {"winter_ornament_light"..i, 0}) end
for i=1,5 do table.insert(rmlist, {"winter_ornament_festivalevents"..i, 0}) end
table.insert(rmlist, {"winter_ornament_boss_bearger", 0 })
table.insert(rmlist, {"winter_ornament_boss_beequeen", 0})
table.insert(rmlist, {"winter_ornament_boss_deerclops", 0})
table.insert(rmlist, {"winter_ornament_boss_dragonfly", 0})
table.insert(rmlist, {"winter_ornament_boss_moose", 0})
table.insert(rmlist, {"winter_ornament_boss_toadstool", 0})
table.insert(rmlist, {"winter_ornament_boss_antlion", 0})
table.insert(rmlist, {"winter_ornament_boss_fuelweaver", 0})
table.insert(rmlist, {"winter_ornament_boss_klaus", 0})
table.insert(rmlist, {"winter_ornament_boss_krampus", 0})
table.insert(rmlist, {"winter_ornament_boss_noeyered", 0})
table.insert(rmlist, {"winter_ornament_boss_noeyeblue", 0})
end

--万圣节
local function hallowed_night_rmlist()
for i=1,14 do table.insert(rmlist, {"halloweencandy_"..i, 0}) end
for i=1,6 do table.insert(rmlist, {"halloween_ornament_"..i, 0}) end
table.insert(rmlist, {"halloween_experiment_bravery", 0})
table.insert(rmlist, {"halloween_experiment_health", 0})
table.insert(rmlist, {"halloween_experiment_sanity", 0})
table.insert(rmlist, {"halloween_experiment_volatile", 0})
table.insert(rmlist, {"halloween_experiment_moon", 0})
table.insert(rmlist, {"halloween_experiment_root", 0})
end

--玩具
local function trinket_rmlist()
for i=2,5 do table.insert(rmlist, {"trinket_"..i, 0}) end
for i=7,45 do table.insert(rmlist, {"trinket_"..i, 0}) end
end

function clean()
winterfeast_rmlist()
hallowed_night_rmlist()
trinket_rmlist()
for k,v in pairs(rmlist) do s_rmognum(v[1],v[2]) end
print("Clean Finished!")
end

输入clean()即可
其中rmlist的内容可以根据喜好自行修改,只清理在地面上的物品

随机再生资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
function printground()
print("自然地皮")
print("DECIDUOUS")
print("GRASS")
print("SAVANNA")
print("FOREST")
print("MARSH")
print("ROCKY")
print("DIRT")
print("DESERT_DIRT")
print("月岛地皮")
print("METEOR")
print("PEBBLEBEACH")
print("人工地皮")
print("SCALE")
print("CHECKER")
print("CARPET")
print("WOODFLOOR")
print("海洋:")
print("OCEAN_HAZARDOUS")
print("OCEAN_START")
print("OCEAN_COASTAL_SHORE")
print("OCEAN_BRINEPOOL")
print("OCEAN_COASTAL")
print("OCEAN_SWELL")
print("OCEAN_REEF")
print("OCEAN_ROUGH")
print("不可用")
print("IMPASSABLE")
print("INVALID")
end

function tilespawn(prefab,groundtype)
local pt = Vector3(math.random(-1000, 1000), 0, math.random(-1000, 1000))
local tile = TheWorld.Map:GetTileAtPoint(pt.x, pt.y, pt.z)
--local canspawn = tile ~= GROUND.IMPASSABLE and tile ~= GROUND.INVALID and tile ~= 255 and tile ~= GROUND.OCEAN_START and tile ~= GROUND.OCEAN_SWELL and tile ~= GROUND.OCEAN_ROUGH
if tile == groundtype then
print(prefab, "spawned!")
local b = SpawnPrefab(prefab)
b.Transform:SetPosition(pt:Get())
else
tilespawn(prefab,groundtype)
end
end

function ramdomspawn(prefab)
local pt = Vector3(math.random(-1000, 1000), 0, math.random(-1000, 1000))
local tile = TheWorld.Map:GetTileAtPoint(pt.x, pt.y, pt.z)
local canspawn = tile ~= GROUND.IMPASSABLE and tile ~= GROUND.INVALID and tile ~= 255 and
tile ~= GROUND.OCEAN_HAZARDOUS and tile ~= GROUND.OCEAN_START and tile ~= GROUND.OCEAN_COASTAL_SHORE and
tile ~= GROUND.OCEAN_BRINEPOOL and tile ~= GROUND.OCEAN_COASTAL and tile ~= GROUND.OCEAN_SWELL and
tile ~= GROUND.OCEAN_REEF and tile ~= GROUND.OCEAN_ROUGH
if canspawn then
print(prefab, "spawned!")
local b = SpawnPrefab(prefab)
b.Transform:SetPosition(pt:Get())
else
tilespawn(prefab,groundtype)
end
end

有三条命令
printground()可显示所有的地皮类型,为后面两条命令服务
tilespawn("beefalo", GROUND.SAVANNA)即可随机在沙草地皮上随机生成一只牛,其中GROUND.SAVANNA中的SAVANNA根据printground()的输出结果自行调整
ramdomspawn("lightninggoat")即可在世界上随机生成一只羊

小结

customcommands.lua可以根据喜好自行添加,还可以增加更多DIY的内容

对于上面的距离有什么不懂,欢迎提问


自定义饥荒服务器后台命令
https://peppernotes.top/2019/11/dstcustomcmd/
作者
辣椒小皇纸
发布于
2019年11月18日
许可协议