railscaff:updates
[waspsaliva.git] / builtin / client / wasplib.lua
blobd685ada5a8892ce02de474e2be7d7cae8fa4417f
2 ws = {}
3 ws.registered_globalhacks = {}
4 ws.displayed_wps={}
6 ws.c = core
8 local nextact = {}
9 local ghwason={}
11 function ws.s(name,value)
12 if value == nil then
13 return ws.c.settings:get(name)
14 else
15 ws.c.settings:set(name,value)
16 return ws.c.settings:get(name)
17 end
18 end
20 function ws.dcm(msg)
21 return minetest.display_chat_message(msg)
22 end
23 function ws.set_bool_bulk(settings,value)
24 if type(settings) ~= 'table' then return false end
25 for k,v in pairs(settings) do
26 minetest.settings:set_bool(v,value)
27 end
28 return true
29 end
31 function ws.shuffle(tbl)
32 for i = #tbl, 2, -1 do
33 local j = math.random(i)
34 tbl[i], tbl[j] = tbl[j], tbl[i]
35 end
36 return tbl
37 end
39 function ws.in_list(val, list)
40 if type(list) ~= "table" then return false end
41 for i, v in ipairs(list) do
42 if v == val then
43 return true
44 end
45 end
46 return false
47 end
49 function ws.globalhacktemplate(setting,func,funcstart,funcstop,daughters)
50 funcstart = funcstart or function() end
51 funcstop = funcstop or function() end
52 return function()
53 if not minetest.localplayer then return end
54 if minetest.settings:get_bool(setting) then
55 if nextact[setting] and nextact[setting] > os.clock() then return end
56 nextact[setting] = os.clock() + 0.1
57 if not ghwason[setting] then
58 if not funcstart() then
59 ws.set_bool_bulk(daughters,true)
60 ghwason[setting] = true
61 ws.dcm(setting.. " activated")
62 else minetest.settings:set_bool(setting,false)
63 end
64 else
65 func()
66 end
68 elseif ghwason[setting] then
69 ghwason[setting] = false
70 funcstop()
71 ws.set_bool_bulk(daughters,false)
72 ws.dcm(setting.. " deactivated")
73 end
74 end
75 end
77 function ws.register_globalhack(func)
78 table.insert(ws.registered_globalhacks,func)
79 end
81 function ws.register_globalhacktemplate(name,category,setting,func,funcstart,funcstop,daughters)
82 ws.register_globalhack(ws.globalhacktemplate(setting,func,funcstart,funcstop,daughters))
83 minetest.register_cheat(name,category,setting)
84 end
86 ws.rg=ws.register_globalhacktemplate
88 function ws.step_globalhacks()
89 for i, v in ipairs(ws.registered_globalhacks) do
90 v()
91 end
92 end
94 minetest.register_globalstep(ws.step_globalhacks)
96 function ws.get_reachable_positions(range)
97 range=range or 2
98 local rt={}
99 local lp=minetest.localplayer:get_pos()
100 for x = -range,range,1 do
101 for y = -range,range,1 do
102 for z = -range,range,1 do
103 table.insert(rt,vector.add(lp,vector.new(x,y,z)))
107 return rt
110 function ws.do_area(radius,func,plane)
111 for k,v in pairs(ws.get_reachable_positions(range)) do
112 if not plane or v.y == minetest.localplayer:get_pos().y -1 then
113 func(v)
119 function ws.display_wp(pos,name)
120 table.insert(ws.displayed_wps,minetest.localplayer:hud_add({
121 hud_elem_type = 'waypoint',
122 name = name,
123 text = name,
124 number = 0x00ff00,
125 world_pos = pos
129 function ws.clear_wps()
130 for k,v in pairs(ws.displayed_wps) do
131 minetest.localplayer:hud_remove(v)
132 table.remove(ws.displayed_wps,k)
136 function ws.register_chatcommand_alias(old, ...)
137 local def = assert(minetest.registered_chatcommands[old])
138 def.name = nil
139 for i = 1, select('#', ...) do
140 minetest.register_chatcommand(select(i, ...), table.copy(def))
144 function ws.round2(num, numDecimalPlaces)
145 return tonumber(string.format("%." .. (numDecimalPlaces or 0) .. "f", num))
148 function ws.pos_to_string(pos)
149 if type(pos) == 'table' then
150 pos = minetest.pos_to_string(vector.round(pos))
152 if type(pos) == 'string' then
153 return pos
157 function ws.string_to_pos(pos)
158 if type(pos) == 'string' then
159 pos = minetest.string_to_pos(pos)
161 if type(pos) == 'table' then
162 return vector.round(pos)
166 function ws.on_connect(func)
167 if not minetest.localplayer then minetest.after(0,function() ws.on_connect(func) end) return end
168 if func then func() end
171 function ws.find_item(items,rnd)
172 if type(items) == 'string' then
173 return minetest.find_item(items)
175 if type(nodename) ~= 'table' then return end
176 if rnd then items=ws.shuffle(items) end
177 for i, v in pairs(items) do
178 local n = minetest.find_item(v)
179 if n then
180 return n
183 return false
186 local function find_named(inv, name)
187 if not inv then return -1 end
188 for i, v in ipairs(inv) do
189 --minetest.display_chat_message(name)
190 if v:get_name():find(name) then
191 return i
195 function ws.switch_inv_or_echest(name,max_count)
196 if not minetest.localplayer then return false end
197 local plinv = minetest.get_inventory("current_player")
199 local pos = find_named(plinv.main, name)
200 if pos then
201 minetest.localplayer:set_wield_index(pos)
202 return true
205 local epos = find_named(plinv.enderchest, name)
206 if epos then
207 local tpos
208 for i, v in ipairs(plinv.main) do
209 if v:is_empty() then
210 tpos = i
211 break
215 if tpos then
216 local mv = InventoryAction("move")
217 mv:from("current_player", "enderchest", epos)
218 mv:to("current_player", "main", tpos)
219 if max_count then
220 mv:set_count(max_count)
222 mv:apply()
223 minetest.localplayer:set_wield_index(tpos)
224 return true
227 return false
229 -- TOOLS
231 local function check_tool(stack, node_groups, old_best_time)
232 local toolcaps = stack:get_tool_capabilities()
233 if not toolcaps then return end
234 local best_time = old_best_time
235 for group, groupdef in pairs(toolcaps.groupcaps) do
236 local level = node_groups[group]
237 if level then
238 local this_time = groupdef.times[level]
239 if this_time and this_time < best_time then
240 best_time = this_time
244 return best_time < old_best_time, best_time
247 local function find_best_tool(nodename, switch)
248 local player = minetest.localplayer
249 local inventory = minetest.get_inventory("current_player")
250 local node_groups = minetest.get_node_def(nodename).groups
251 local new_index = player:get_wield_index()
252 local is_better, best_time = false, math.huge
254 is_better, best_time = check_tool(player:get_wielded_item(), node_groups, best_time)
255 if inventory.hand then
256 is_better, best_time = check_tool(inventory.hand[1], node_groups, best_time)
259 for index, stack in ipairs(inventory.main) do
260 is_better, best_time = check_tool(stack, node_groups, best_time)
261 if is_better then
262 new_index = index
266 return new_index
269 function ws.select_best_tool(pos)
270 local nd=minetest.get_node_or_nil(pos)
271 local nodename='air'
272 if nd then nodename=nd.name end
273 minetest.localplayer:set_wield_index(find_best_tool(nodename))
276 --- COORDS
277 function ws.coord(x, y, z)
278 return vector.new(x,y,z)
280 function ws.ordercoord(c)
281 if c.x == nil then
282 return {x = c[1], y = c[2], z = c[3]}
283 else
284 return c
288 -- x or {x,y,z} or {x=x,y=y,z=z}
289 function ws.optcoord(x, y, z)
290 if y and z then
291 return ws.coord(x, y, z)
292 else
293 return ws.ordercoord(x)
296 function ws.cadd(c1, c2)
297 return ws.coord(c1.x + c2.x, c1.y + c2.y, c1.z + c2.z)
300 function ws.relcoord(x, y, z)
301 local pos = minetest.localplayer:get_pos()
302 pos.y=math.ceil(pos.y)
303 return ws.cadd(pos, ws.optcoord(x, y, z))
306 local function between(x, y, z) -- x is between y and z (inclusive)
307 return y <= x and x <= z
310 function ws.getdir() --
311 local rot = minetest.localplayer:get_yaw() % 360
312 if between(rot, 315, 360) or between(rot, 0, 45) then
313 return "north"
314 elseif between(rot, 135, 225) then
315 return "south"
316 elseif between(rot, 225, 315) then
317 return "east"
318 elseif between(rot, 45, 135) then
319 return "west"
322 function ws.setdir(dir) --
323 if dir == "north" then
324 minetest.localplayer:set_yaw(0)
325 elseif dir == "south" then
326 minetest.localplayer:set_yaw(180)
327 elseif dir == "east" then
328 minetest.localplayer:set_yaw(270)
329 elseif dir == "west" then
330 minetest.localplayer:set_yaw(90)
334 function ws.dircoord(f, y, r)
335 local dir=ws.getdir()
336 local coord = ws.optcoord(f, y, r)
337 local f = coord.x
338 local y = coord.y
339 local r = coord.z
340 local lp=minetest.localplayer:get_pos()
341 if dir == "north" then
342 return ws.relcoord(r, y, f)
343 elseif dir == "south" then
344 return ws.relcoord(-r, y, -f)
345 elseif dir == "east" then
346 return ws.relcoord(f, y, -r)
347 elseif dir== "west" then
348 return ws.relcoord(-f, y, r)
350 return ws.relcoord(0, 0, 0)
353 function ws.aim(tpos)
354 local ppos=minetest.localplayer:get_pos()
355 local dir=vector.direction(ppos,tpos)
356 local yyaw=0;
357 local pitch=0;
358 if dir.x < 0 then
359 yyaw = math.atan2(-dir.x, dir.z) + (math.pi * 2)
360 else
361 yyaw = math.atan2(-dir.x, dir.z)
363 yyaw = ws.round2(math.deg(yyaw),2)
364 pitch = ws.round2(math.deg(math.asin(-dir.y) * 1),2);
365 minetest.localplayer:set_yaw(yyaw)
366 minetest.localplayer:set_pitch(pitch)
369 function ws.gaim(tpos,v,g)
370 local v = v or 40
371 local g = g or 9.81
372 local ppos=minetest.localplayer:get_pos()
373 local dir=vector.direction(ppos,tpos)
374 local yyaw=0;
375 local pitch=0;
376 if dir.x < 0 then
377 yyaw = math.atan2(-dir.x, dir.z) + (math.pi * 2)
378 else
379 yyaw = math.atan2(-dir.x, dir.z)
381 yyaw = ws.round2(math.deg(yyaw),2)
382 local y = dir.y
383 dir.y = 0
384 local x = vector.length(dir)
385 pitch=math.atan(math.pow(v, 2) / (g * x) + math.sqrt(math.pow(v, 4)/(math.pow(g, 2) * math.pow(x, 2)) - 2 * math.pow(v, 2) * y/(g * math.pow(x, 2)) - 1))
386 --pitch = ws.round2(math.deg(math.asin(-dir.y) * 1),2);
387 minetest.localplayer:set_yaw(yyaw)
388 minetest.localplayer:set_pitch(math.deg(pitch))
391 function ws.place(pos,nodename)
392 local it=ws.find_item(nodename)
393 if not it then return end
394 minetest.localplayer:set_wield_index(it)
395 --ws.switch_inv_or_echest(ws.find_item(nodem),1)
396 ws.c.place_node(pos)
399 function ws.dig(pos)
400 local nd=minetest.get_node_or_nil(pos)
401 if nd and minetest.get_node_def(nd.name).diggable then
402 ws.select_best_tool(pos)
403 minetest.dig_node(pos)
407 function ws.dignodes(poss)
408 for k,v in pairs(poss) do
409 ws.dig(v)