forked from ac-minetest/basic_robot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
commands.lua
310 lines (237 loc) · 8.86 KB
/
commands.lua
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
basic_robot.commands = {};
-- set up nodes for planting (for example seeds -> plant) : [nodename] = plant_name
basic_robot.plant_table = {["farming:seed_barley"]="farming:barley_1",["farming:beans"]="farming:beanpole_1", -- so it works with farming redo mod
["farming:blueberries"]="farming:blueberry_1",["farming:carrot"]="farming:carrot_1",["farming:cocoa_beans"]="farming:cocoa_1",
["farming:coffee_beans"]="farming:coffee_1",["farming:corn"]="farming:corn_1",["farming:blueberries"]="farming:blueberry_1",
["farming:seed_cotton"]="farming:cotton_1",["farming:cucumber"]="farming:cucumber_1",["farming:grapes"]="farming:grapes_1",
["farming:melon_slice"]="farming:melon_1",["farming:potato"]="farming:potato_1",["farming:pumpkin_slice"]="farming:pumpkin_1",
["farming:raspberries"]="farming:raspberry_1",["farming:rhubarb"]="farming:rhubarb_1",["farming:tomato"]="farming:tomato_1",
["farming:seed_wheat"]="farming:wheat_1"}
local function tick(pos) -- needed for plants to start growing: minetest 0.4.14 farming
minetest.get_node_timer(pos):start(math.random(166, 286))
end
local pi = math.pi;
local function pos_in_dir(obj, dir) -- position after we move in specified direction
local yaw = obj:getyaw();
local pos = obj:getpos();
if dir == 1 then
yaw = yaw + pi/2;
elseif dir == 2 then
yaw = yaw - pi/2;
elseif dir == 3 then
elseif dir == 4 then
yaw = yaw+pi;
elseif dir == 5 then -- up
pos.y=pos.y+1
elseif dir == 6 then -- down
pos.y=pos.y-1
elseif dir == 7 then -- forward, down
pos.y=pos.y-1
end
if dir<5 or dir == 7 then -- left, right, back
pos.x = pos.x+math.cos(yaw)
pos.z = pos.z+math.sin(yaw)
end
return pos
end
basic_robot.commands.move = function(name,dir)
local obj = basic_robot.data[name].obj;
local pos = pos_in_dir(obj, dir)
-- can move through walkable nodes
if minetest.registered_nodes[minetest.get_node(pos).name].walkable then return end
-- up; no levitation!
if minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z}).name == "air" and
minetest.get_node({x=pos.x,y=pos.y-2,z=pos.z}).name == "air" then
return false
end
obj:moveto(pos, true)
-- sit and stand up for model - doenst work for overwriten obj export
-- if dir == 5 then-- up
-- obj:set_animation({x=0,y=0})
-- elseif dir == 6 then -- down
-- obj:set_animation({x=81,y=160})
-- end
return true
end
basic_robot.commands.turn = function (name, angle)
local obj = basic_robot.data[name].obj;
local yaw = obj:getyaw()+angle;
obj:setyaw(yaw);
end
basic_robot.commands.dig = function(name,dir)
local digcount = 0;
if basic_robot.maxdig~=0 then
digcount = basic_robot.data[name].digcount;
if digcount > basic_robot.maxdig then return false end
end
local obj = basic_robot.data[name].obj;
local pos = pos_in_dir(obj, dir)
local luaent = obj:get_luaentity();
if minetest.is_protected(pos,luaent.owner ) then return false end
local nodename = minetest.get_node(pos).name;
if nodename == "air" then return false end
local spos = obj:get_luaentity().spawnpos;
local inv = minetest.get_meta(spos):get_inventory();
if not inv then return end
--inv:add_item("main",ItemStack( nodename ));
basic_robot.give_drops(nodename, inv);
minetest.set_node(pos,{name = "air"})
basic_robot.data[name].digcount = digcount+1;
--DS: sounds
local sounds = minetest.registered_nodes[nodename].sounds
if sounds then
local sound = sounds.dug
if sound then
minetest.sound_play(sound,{object=obj, max_hear_distance = 10})
end
end
return true
end
basic_robot.commands.insert_item = function(name,item, inventory,dir)
local obj = basic_robot.data[name].obj;
local tpos = pos_in_dir(obj, dir); -- position of target block
local luaent = obj:get_luaentity();
if minetest.is_protected(tpos,luaent.owner ) then return false end
local pos = basic_robot.data[name].spawnpos; -- position of spawner block
local meta = minetest.get_meta(pos);
local tmeta = minetest.get_meta(tpos);
local inv = minetest.get_meta(pos):get_inventory();
local tinv = minetest.get_meta(tpos):get_inventory();
if not inventory then inventory = "main"; end
--if not inv then return end
local stack = ItemStack(item);
if (not inv:contains_item("main", stack) or not tinv:room_for_item(inventory, stack)) and meta:get_int("admin")~=1 then
return false
end
tinv:add_item(inventory,stack);
inv:remove_item("main", stack);
return true
end
basic_robot.commands.take_item = function(name,item, inventory,dir)
local obj = basic_robot.data[name].obj;
local tpos = pos_in_dir(obj, dir); -- position of target block
local luaent = obj:get_luaentity();
if minetest.is_protected(tpos,luaent.owner ) then return false end
local pos = basic_robot.data[name].spawnpos; -- position of spawner block
if basic_robot.bad_inventory_blocks[ minetest.get_node(tpos).name ] then return false end -- dont allow take from
local meta = minetest.get_meta(pos);
local tmeta = minetest.get_meta(tpos);
local inv = minetest.get_meta(pos):get_inventory();
local tinv = minetest.get_meta(tpos):get_inventory();
if not inventory then inventory = "main"; end
--if not inv then return end
local stack = ItemStack(item);
if (not tinv:contains_item(inventory, stack) or not inv:room_for_item("main", stack)) and meta:get_int("admin")~=1 then
return false
end
inv:add_item("main",stack);
tinv:remove_item(inventory, stack);
return true
end
basic_robot.commands.read_node = function(name,dir)
local obj = basic_robot.data[name].obj;
local pos = pos_in_dir(obj, dir)
return minetest.get_node(pos).name or ""
end
basic_robot.commands.read_text = function(name,dir,stringname)
local obj = basic_robot.data[name].obj;
local pos = pos_in_dir(obj, dir)
if stringname == nil then
stringname = "infotext"
end
return minetest.get_meta(pos):get_string(stringname) or ""
end
basic_robot.commands.place = function(name,nodename, dir)
local obj = basic_robot.data[name].obj;
local pos = pos_in_dir(obj, dir)
local luaent = obj:get_luaentity();
if minetest.is_protected(pos,luaent.owner ) then return false end
if minetest.get_node(pos).name~="air" then return false end
local spos = obj:get_luaentity().spawnpos;
local meta = minetest.get_meta(spos);
local inv = meta:get_inventory();
if not inv then return false end
if not inv:contains_item("main", ItemStack(nodename)) and meta:get_int("admin")~=1 then return end
inv:remove_item("main", ItemStack(nodename));
--DS
local sounds = minetest.registered_nodes[nodename].sounds
if sounds then
local sound = sounds.place
if sound then
minetest.sound_play(sound,{object=obj, max_hear_distance = 10})
end
end
placename = basic_robot.plant_table[nodename];
if placename then
minetest.set_node(pos,{name = placename})
tick(pos); -- needed for seeds to grow
else
minetest.set_node(pos,{name = nodename})
end
return true
end
basic_robot.commands.attack = function(name, target) -- attack range 4, damage 5
local reach = 4;
local damage = 5;
local tplayer = minetest.get_player_by_name(target);
if not tplayer then return false end
local obj = basic_robot.data[name].obj;
local pos = obj:getpos();
local tpos = tplayer:getpos();
if math.abs(pos.x-tpos.x)> reach or math.abs(pos.y-tpos.y)> reach or math.abs(pos.z-tpos.z)> reach then
return false
end
tplayer:set_hp(tplayer:get_hp()-damage)
return true
end
basic_robot.commands.read_book = function (itemstack) -- itemstack should contain book
local data = minetest.deserialize(itemstack:get_metadata())
if data then
return data.text;
else
return nil
end
end
basic_robot.commands.write_book = function(name,text) -- returns itemstack containing book
local lpp = 14;
local new_stack = ItemStack("default:book_written")
local data = {}
data.title = "program book"
data.text = text
data.text_len = #data.text
data.page = 1
data.page_max = math.ceil((#data.text:gsub("[^\n]", "") + 1) / lpp)
data.owner = name
local data_str = minetest.serialize(data)
new_stack:set_metadata(data_str);
return new_stack;
end
basic_robot.give_drops = function(nodename, inv) -- gives apropriate drops when node is dug
local table = minetest.registered_items[nodename];
local dropname;
if table~=nil then --put in chest
if table.drop~= nil then -- drop handling
if table.drop.items then
--handle drops better, emulation of drop code
local max_items = table.drop.max_items or 0;
if max_items==0 then -- just drop all the items (taking the rarity into consideration)
max_items = #table.drop.items or 0;
end
local drop = table.drop;
local i = 0;
for k,v in pairs(drop.items) do
if i > max_items then break end; i=i+1;
local rare = v.rarity or 1;
if math.random(1, rare)==1 then
dropname = v.items[math.random(1,#v.items)]; -- pick item randomly from list
inv:add_item("main",dropname);
end
end
else
inv:add_item("main",table.drop);
end
else
inv:add_item("main",nodename);
end
end
end