diff --git a/mods/ENTITIES/pyutest_vehicles/api.lua b/mods/ENTITIES/pyutest_vehicles/api.lua new file mode 100644 index 0000000..1d8976b --- /dev/null +++ b/mods/ENTITIES/pyutest_vehicles/api.lua @@ -0,0 +1,204 @@ +-- Based on: https://github.com/minetest/minetest_game/blob/master/mods/boats/init.lua + +local function get_velocity(v, yaw, y) + local x = -math.sin(yaw) * v + local z = math.cos(yaw) * v + return {x = x * 8, y = y * 8, z = z * 8} +end + +local function get_v(v) + return math.sqrt(v.x ^ 2 + v.z ^ 2) +end + +local class = { + driver = nil, + v = 0, + last_v = 0, + removed = false, + auto = false, +} + +function class:on_rightclick(clicker) + if not clicker or not clicker:is_player() then + return + end + + local name = clicker:get_player_name() + if self.driver and name == self.driver then + clicker:set_detach() + + local pos = clicker:get_pos() + pos = {x = pos.x, y = pos.y + 0.2, z = pos.z} + core.after(0.1, function() + clicker:set_pos(pos) + end) + elseif not self.driver then + clicker:set_attach(self.object, "", + {x = 0.5, y = 1, z = -3}, {x = 0, y = 0, z = 0}) + + self.driver = name + + clicker:set_look_horizontal(self.object:get_yaw()) + end +end + +function class:on_detach_child(child) + if child and child:get_player_name() == self.driver then + self.driver = nil + self.auto = false + end +end + +function class:on_activate(staticdata, dtime_s) + self.object:set_armor_groups({immortal = 1}) + if staticdata then + self.v = tonumber(staticdata) + end + self.last_v = self.v +end + +function class:get_staticdata() + return tostring(self.v) +end + +function class:on_punch(puncher) + if not puncher or not puncher:is_player() or self.removed then + return + end + + local name = puncher:get_player_name() + if self.driver and name == self.driver then + self.driver = nil + puncher:set_detach() + end + if not self.driver then + self.removed = true + local inv = puncher:get_inventory() + if not core.is_creative_enabled(name) + or not inv:contains_item("main", self.name) then + + local leftover = inv:add_item("main", self.name) + if not leftover:is_empty() then + core.add_item(self.object:get_pos(), leftover) + end + end + + core.after(0.1, function() + self.object:remove() + end) + end +end + +function class:on_step(dtime) + self.v = get_v(self.object:get_velocity()) * math.sign(self.v) + if self.driver then + local driver_objref = core.get_player_by_name(self.driver) + if driver_objref then + local ctrl = driver_objref:get_player_control() + if ctrl.up and ctrl.down then + if not self.auto then + self.auto = true + core.chat_send_player(self.driver, Translate("Auto mode on")) + end + elseif ctrl.down then + self.v = self.v - dtime * 2.0 + if self.auto then + self.auto = false + core.chat_send_player(self.driver, Translate("Auto mode off")) + end + elseif ctrl.up or self.auto then + self.v = self.v + dtime * 2.0 + end + if ctrl.left then + if self.v < -0.001 then + self.object:set_yaw(self.object:get_yaw() - dtime * 0.9) + else + self.object:set_yaw(self.object:get_yaw() + dtime * 0.9) + end + elseif ctrl.right then + if self.v < -0.001 then + self.object:set_yaw(self.object:get_yaw() + dtime * 0.9) + else + self.object:set_yaw(self.object:get_yaw() - dtime * 0.9) + end + end + end + end + local velo = self.object:get_velocity() + if not self.driver and + self.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then + self.object:set_pos(self.object:get_pos()) + return + end + -- We need to preserve velocity sign to properly apply drag force + -- while moving backward + local drag = dtime * math.sign(self.v) * (0.01 + 0.0796 * self.v * self.v) + -- If drag is larger than velocity, then stop horizontal movement + if math.abs(self.v) <= math.abs(drag) then + self.v = 0 + else + self.v = self.v - drag + end + + local p = self.object:get_pos() + p.y = p.y - 0.5 + local new_velo + local new_acce = {x = 0, y = 0, z = 0} + p.y = p.y + 1 + local y = self.object:get_velocity().y + if y >= 5 then + y = 5 + end + new_velo = get_velocity(self.v, self.object:get_yaw(), y) + self.object:set_pos(self.object:get_pos()) + self.object:set_velocity(new_velo) + self.object:set_acceleration(new_acce) +end + +PyuTest.create_vehicle = function(name, desc, properties, image, craft) + local options = setmetatable(properties, { __index = class}) + options.name = name + + core.register_entity(name, properties) + + PyuTest.make_item(name, desc, { + vehicle = 1 + }, image, { + liquids_pointable = true, + on_place = function (itemstack, placer, pointed_thing) + local under = pointed_thing.under + local node = core.get_node(under) + local udef = core.registered_nodes[node.name] + if udef and udef.on_rightclick and + not (placer and placer:is_player() and + placer:get_player_control().sneak) then + return udef.on_rightclick(under, node, placer, itemstack, + pointed_thing) or itemstack + end + + if pointed_thing.type ~= "node" then + return itemstack + end + + pointed_thing.under.y = pointed_thing.under.y + 0.5 + local vehicle = core.add_entity(pointed_thing.under, name) + if vehicle then + if placer then + vehicle:set_yaw(placer:get_look_horizontal()) + end + local player_name = placer and placer:get_player_name() or "" + if not core.is_creative_enabled(player_name) then + itemstack:take_item() + end + end + return itemstack + end + }) + + if craft then + core.register_craft({ + output = name, + recipe = craft + }) + end +end diff --git a/mods/ENTITIES/pyutest_vehicles/init.lua b/mods/ENTITIES/pyutest_vehicles/init.lua new file mode 100644 index 0000000..83536ce --- /dev/null +++ b/mods/ENTITIES/pyutest_vehicles/init.lua @@ -0,0 +1,13 @@ +local modpath = core.get_modpath(core.get_current_modname()) + +dofile(modpath .. "/api.lua") + +PyuTest.create_vehicle("pyutest_vehicles:test", "Test Vehicle", { + initial_properties = { + physical = false, + collisionbox = PyuTest.NODEBOX_DEFAULT.fixed, + visual = "cube", + textures = {"pyutest-wood.png", "pyutest-wood.png", "pyutest-wood.png", + "pyutest-wood.png", "pyutest-wood.png", "pyutest-wood.png"} + } +}, "pyutest-wood.png") diff --git a/mods/ENTITIES/pyutest_vehicles/mod.conf b/mods/ENTITIES/pyutest_vehicles/mod.conf new file mode 100644 index 0000000..f136755 --- /dev/null +++ b/mods/ENTITIES/pyutest_vehicles/mod.conf @@ -0,0 +1 @@ +depends = pyutest_blocks,pyutest_tools