Improve the API

This commit breaks retro-compatibility. (Although not too much)
This commit is contained in:
upsilon 2017-01-17 16:32:30 +01:00
parent 709bb4ec16
commit ba3838842b
3 changed files with 35 additions and 14 deletions

View File

@ -40,22 +40,28 @@ Groups: optional groups.
throwing.register_bow("bow_stone", "default:cobble", "Stone Bow", "throwing_bow_stone.png") throwing.register_bow("bow_stone", "default:cobble", "Stone Bow", "throwing_bow_stone.png")
function throwing.register_arrow(name, itemcraft, craft_quantity, description, tiles, on_hit_sound, on_hit[, groups]) function throwing.register_arrow(name, itemcraft, craft_quantity, description, tiles, on_hit_sound, on_hit[, on_throw[, groups]])
--[[ --[[
Name: Arrow name (in second part of the itemstring). Name: Arrow name (in second part of the itemstring).
Itemcraft: item used to craft the arrow (nil if uncraftable). Itemcraft: item used to craft the arrow (nil if uncraftable).
Craft_quantity: quantity of arrows in the craft output. Craft_quantity: quantity of arrows in the craft output.
Tiles: tiles of the arrow. Tiles: tiles of the arrow.
On_hit_sound: sound played when the arrow hits a node or an object (nil if no sound). On_hit_sound: sound played when the arrow hits a node or an object (nil if no sound).
On_hit: callback function: on_hit(pos, last_pos, node, object, hitter) where: On_hit: callback function: on_hit(pos, last_pos, node, object, hitter, self) where:
* Pos: the position of the hitted node or object * Pos: the position of the hitted node or object
* Last_pos: the last air node where the arrow was (used by the build_arrow, for example) * Last_pos: the last air node where the arrow was (used by the build_arrow, for example)
* Node and object: hitted node or object. Either node or object is nil, depending * Node and object: hit node or object. Either node or object is nil, depending
whether the arrow hitted a node or an object (you should always check for that). whether the arrow hit a node or an object (you should always check for that).
An object can be a player or a luaentity. An object can be a player or a luaentity.
* Hitter: the ObjectRef of the player who throwed the arrow. * Hitter: the ObjectRef of the player who threw the arrow.
* Self: the arrow entity table (it allows you to hack a lot!)
* When it fails, it should return: * When it fails, it should return:
false[, reason] false[, reason]
On_throw: option callback function: on_throw(pos, thrower, self) where:
* Pos: the position from where the arrow is throw (which a bit higher than the hitter position)
* Thrower: the ObjectRef of the thrower
* Self: the arrow entity table
* Should return false if the arrow should not be throw
]] ]]
-- Examples: -- Examples:

View File

@ -8,13 +8,20 @@ throwing.modname = minetest.get_current_modname()
local function shoot_arrow(itemstack, player) local function shoot_arrow(itemstack, player)
for _,arrow in ipairs(throwing.arrows) do for _,arrow in ipairs(throwing.arrows) do
if player:get_inventory():get_stack("main", player:get_wield_index()+1):get_name() == arrow then if player:get_inventory():get_stack("main", player:get_wield_index()+1):get_name() == arrow then
if not minetest.setting_getbool("creative_mode") then
player:get_inventory():remove_item("main", arrow)
end
local playerpos = player:getpos() local playerpos = player:getpos()
local obj = minetest.add_entity({x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}, arrow.."_entity") local pos = {x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}
local dir = player:get_look_dir() local obj = minetest.add_entity(pos, arrow.."_entity")
local luaentity = obj:get_luaentity()
luaentity.player = player:get_player_name()
if luaentity.on_throw then
if luaentity.on_throw(pos, player, luaentity) == false then
return false
end
end
local dir = player:get_look_dir()
local velocity_factor = tonumber(minetest.setting_get("throwing.velocity_factor")) or 19 local velocity_factor = tonumber(minetest.setting_get("throwing.velocity_factor")) or 19
local horizontal_acceleration_factor = tonumber(minetest.setting_get("throwing.horizontal_acceleration_factor")) or -3 local horizontal_acceleration_factor = tonumber(minetest.setting_get("throwing.horizontal_acceleration_factor")) or -3
local vertical_acceleration = tonumber(minetest.setting_get("throwing.vertical_acceleration")) or -10 local vertical_acceleration = tonumber(minetest.setting_get("throwing.vertical_acceleration")) or -10
@ -23,7 +30,11 @@ local function shoot_arrow(itemstack, player)
obj:setacceleration({x=dir.x*horizontal_acceleration_factor, y=vertical_acceleration, z=dir.z*horizontal_acceleration_factor}) obj:setacceleration({x=dir.x*horizontal_acceleration_factor, y=vertical_acceleration, z=dir.z*horizontal_acceleration_factor})
obj:setyaw(player:get_look_horizontal()-math.pi/2) obj:setyaw(player:get_look_horizontal()-math.pi/2)
minetest.sound_play("throwing_sound", {pos=playerpos, gain = 0.5}) minetest.sound_play("throwing_sound", {pos=playerpos, gain = 0.5})
obj:get_luaentity().player = player:get_player_name()
if not minetest.setting_getbool("creative_mode") then
player:get_inventory():remove_item("main", arrow)
end
return true return true
end end
end end
@ -73,7 +84,7 @@ local function arrow_step(self, dtime)
return return
end end
local ret, reason = self.on_hit(pos, self.last_pos, node, obj, player) local ret, reason = self.on_hit(pos, self.last_pos, node, obj, player, self)
if ret == false then if ret == false then
if reason then if reason then
logging(": on_hit function failed for reason: "..reason) logging(": on_hit function failed for reason: "..reason)
@ -132,8 +143,11 @@ on_hit(pos, last_pos, node, object, hitter)
Either node or object is nil, depending whether the arrow collided with an object (luaentity or player) or with a node. Either node or object is nil, depending whether the arrow collided with an object (luaentity or player) or with a node.
No log message is needed in this function (a generic log message is automatically emitted), except on error or warning. No log message is needed in this function (a generic log message is automatically emitted), except on error or warning.
Should return false or false, reason on failure. Should return false or false, reason on failure.
on_throw(pos, hitter)
Unlike on_hit, it is optional.
]] ]]
function throwing.register_arrow(name, itemcraft, craft_quantity, description, tiles, on_hit_sound, on_hit, groups) function throwing.register_arrow(name, itemcraft, craft_quantity, description, tiles, on_hit_sound, on_hit, on_throw, groups)
table.insert(throwing.arrows, throwing.modname..":"..name) table.insert(throwing.arrows, throwing.modname..":"..name)
local _groups = {dig_immediate = 3} local _groups = {dig_immediate = 3}
@ -197,6 +211,7 @@ function throwing.register_arrow(name, itemcraft, craft_quantity, description, t
collisionbox = {0, 0, 0, 0, 0, 0}, collisionbox = {0, 0, 0, 0, 0, 0},
on_hit = on_hit, on_hit = on_hit,
on_hit_sound = on_hit_sound, on_hit_sound = on_hit_sound,
on_throw = on_throw,
node = throwing.modname..":"..name, node = throwing.modname..":"..name,
player = "", player = "",
on_step = arrow_step on_step = arrow_step

View File

@ -61,7 +61,7 @@ if get_setting("dig_arrow_admin") then
return return
end end
minetest.remove_node(pos) minetest.remove_node(pos)
end, {not_in_creative_inventory = 1}) end, nil, {not_in_creative_inventory = 1})
end end
if get_setting("teleport_arrow") then if get_setting("teleport_arrow") then