add crafttable for woodcutter

master
wzy2006 2020-04-23 21:47:24 +08:00
parent 6f73ce9e76
commit 29aff92ee8
20 changed files with 303 additions and 285 deletions

View File

@ -1,8 +1,8 @@
# minetest mod working_villages [![Build Status](https://travis-ci.org/theFox6/working_villages.svg?branch=master)](https://travis-ci.org/theFox6/working_villages)
# minetest mod smart_villages [![Build Status](https://travis-ci.org/theFox6/smart_villages.svg?branch=master)](https://travis-ci.org/theFox6/smart_villages)
This mod adds Villagers performing work.
The plan is to make villagers build up their own villages.
[working_villages forum page](https://forum.minetest.net/viewtopic.php?f=9&t=17429)
[smart_villages forum page](https://forum.minetest.net/viewtopic.php?f=9&t=17429)
Planned Features:
* Villagers

2
api.MD
View File

@ -4,7 +4,7 @@ for specific documentation look for the comments in the (api.lua)
To register a new job you use:
```
working_villages.register_job("[itemstring for the job item]", {
smart_villages.register_job("[itemstring for the job item]", {
description = "[description for the job item]",
inventory_image = "[texture for the job item]",
jobfunc = "[coroutine that is called every step]",

239
api.lua
View File

@ -1,4 +1,4 @@
working_villages.animation_frames = {
smart_villages.animation_frames = {
STAND = { x= 0, y= 79, },
LAY = { x=162, y=166, },
WALK = { x=168, y=187, },
@ -7,23 +7,23 @@ working_villages.animation_frames = {
SIT = { x= 81, y=160, },
}
working_villages.registered_villagers = {}
smart_villages.registered_villagers = {}
working_villages.registered_jobs = {}
smart_villages.registered_jobs = {}
working_villages.registered_eggs = {}
smart_villages.registered_eggs = {}
-- working_villages.is_job reports whether a item is a job item by the name.
function working_villages.is_job(item_name)
if working_villages.registered_jobs[item_name] then
-- smart_villages.is_job reports whether a item is a job item by the name.
function smart_villages.is_job(item_name)
if smart_villages.registered_jobs[item_name] then
return true
end
return false
end
-- working_villages.is_villager reports whether a name is villager's name.
function working_villages.is_villager(name)
if working_villages.registered_villagers[name] then
-- smart_villages.is_villager reports whether a name is villager's name.
function smart_villages.is_villager(name)
if smart_villages.registered_villagers[name] then
return true
end
return false
@ -31,39 +31,39 @@ end
---------------------------------------------------------------------
-- working_villages.villager represents a table that contains common methods
-- smart_villages.villager represents a table that contains common methods
-- for villager object.
-- this table must be contains by a metatable.__index of villager self tables.
-- minetest.register_entity set initial properties as a metatable.__index, so
-- this table's methods must be put there.
working_villages.villager = {}
smart_villages.villager = {}
-- working_villages.villager.get_inventory returns a inventory of a villager.
function working_villages.villager:get_inventory()
-- smart_villages.villager.get_inventory returns a inventory of a villager.
function smart_villages.villager:get_inventory()
return minetest.get_inventory {
type = "detached",
name = self.inventory_name,
}
end
-- working_villages.villager.get_job_name returns a name of a villager's current job.
function working_villages.villager:get_job_name()
-- smart_villages.villager.get_job_name returns a name of a villager's current job.
function smart_villages.villager:get_job_name()
local inv = self:get_inventory()
return inv:get_stack("job", 1):get_name()
end
-- working_villages.villager.get_job returns a villager's current job definition.
function working_villages.villager:get_job()
-- smart_villages.villager.get_job returns a villager's current job definition.
function smart_villages.villager:get_job()
local name = self:get_job_name()
if name ~= "" then
return working_villages.registered_jobs[name]
return smart_villages.registered_jobs[name]
end
return nil
end
-- working_villages.villager.get_nearest_player returns a player object who
-- smart_villages.villager.get_nearest_player returns a player object who
-- is the nearest to the villager.
function working_villages.villager:get_nearest_player(range_distance)
function smart_villages.villager:get_nearest_player(range_distance)
local player, min_distance = nil, range_distance
local position = self.object:getpos()
@ -84,7 +84,7 @@ end
-- woriking_villages.villager.get_nearest_item_by_condition returns the position of
-- an item that returns true for the condition
function working_villages.villager:get_nearest_item_by_condition(cond, range_distance)
function smart_villages.villager:get_nearest_item_by_condition(cond, range_distance)
local max_distance=range_distance
if type(range_distance) == "table" then
max_distance=math.max(math.max(range_distance.x,range_distance.y),range_distance.z)
@ -113,8 +113,8 @@ function working_villages.villager:get_nearest_item_by_condition(cond, range_dis
return item;
end
-- working_villages.villager.get_front returns a position in front of the villager.
function working_villages.villager:get_front()
-- smart_villages.villager.get_front returns a position in front of the villager.
function smart_villages.villager:get_front()
local direction = self:get_look_direction()
if math.abs(direction.x) >= 0.5 then
if direction.x > 0 then direction.x = 1 else direction.x = -1 end
@ -133,14 +133,14 @@ function working_villages.villager:get_front()
return vector.add(vector.round(self.object:getpos()), direction)
end
-- working_villages.villager.get_front_node returns a node that exists in front of the villager.
function working_villages.villager:get_front_node()
-- smart_villages.villager.get_front_node returns a node that exists in front of the villager.
function smart_villages.villager:get_front_node()
local front = self:get_front()
return minetest.get_node(front)
end
-- working_villages.villager.get_back returns a position behind the villager.
function working_villages.villager:get_back()
-- smart_villages.villager.get_back returns a position behind the villager.
function smart_villages.villager:get_back()
local direction = self:get_look_direction()
if math.abs(direction.x) >= 0.5 then
if direction.x > 0 then direction.x = -1
@ -161,24 +161,24 @@ function working_villages.villager:get_back()
return vector.add(vector.round(self.object:getpos()), direction)
end
-- working_villages.villager.get_back_node returns a node that exists behind the villager.
function working_villages.villager:get_back_node()
-- smart_villages.villager.get_back_node returns a node that exists behind the villager.
function smart_villages.villager:get_back_node()
local back = self:get_back()
return minetest.get_node(back)
end
-- working_villages.villager.get_look_direction returns a normalized vector that is
-- smart_villages.villager.get_look_direction returns a normalized vector that is
-- the villagers's looking direction.
function working_villages.villager:get_look_direction()
function smart_villages.villager:get_look_direction()
local yaw = self.object:getyaw()
return vector.normalize{x = -math.sin(yaw), y = 0.0, z = math.cos(yaw)}
end
-- working_villages.villager.set_animation sets the villager's animation.
-- smart_villages.villager.set_animation sets the villager's animation.
-- this method is wrapper for self.object:set_animation.
function working_villages.villager:set_animation(frame)
function smart_villages.villager:set_animation(frame)
self.object:set_animation(frame, 15, 0)
if frame == working_villages.animation_frames.LAY then
if frame == smart_villages.animation_frames.LAY then
local dir = self:get_look_direction()
local dirx = math.abs(dir.x)*0.5
local dirz = math.abs(dir.z)*0.5
@ -188,34 +188,34 @@ function working_villages.villager:set_animation(frame)
end
end
-- working_villages.villager.set_yaw_by_direction sets the villager's yaw
-- smart_villages.villager.set_yaw_by_direction sets the villager's yaw
-- by a direction vector.
function working_villages.villager:set_yaw_by_direction(direction)
function smart_villages.villager:set_yaw_by_direction(direction)
self.object:setyaw(math.atan2(direction.z, direction.x) - math.pi / 2)
end
-- working_villages.villager.get_wield_item_stack returns the villager's wield item's stack.
function working_villages.villager:get_wield_item_stack()
-- smart_villages.villager.get_wield_item_stack returns the villager's wield item's stack.
function smart_villages.villager:get_wield_item_stack()
local inv = self:get_inventory()
return inv:get_stack("wield_item", 1)
end
-- working_villages.villager.set_wield_item_stack sets villager's wield item stack.
function working_villages.villager:set_wield_item_stack(stack)
-- smart_villages.villager.set_wield_item_stack sets villager's wield item stack.
function smart_villages.villager:set_wield_item_stack(stack)
local inv = self:get_inventory()
inv:set_stack("wield_item", 1, stack)
end
-- working_villages.villager.add_item_to_main add item to main slot.
-- smart_villages.villager.add_item_to_main add item to main slot.
-- and returns leftover.
function working_villages.villager:add_item_to_main(stack)
function smart_villages.villager:add_item_to_main(stack)
local inv = self:get_inventory()
return inv:add_item("main", stack)
end
-- working_villages.villager.move_main_to_wield moves itemstack from main to wield.
-- smart_villages.villager.move_main_to_wield moves itemstack from main to wield.
-- if this function fails then returns false, else returns true.
function working_villages.villager:move_main_to_wield(pred)
function smart_villages.villager:move_main_to_wield(pred)
local inv = self:get_inventory()
local main_size = inv:get_size("main")
@ -231,13 +231,13 @@ function working_villages.villager:move_main_to_wield(pred)
return false
end
-- working_villages.villager.is_named reports the villager is still named.
function working_villages.villager:is_named()
-- smart_villages.villager.is_named reports the villager is still named.
function smart_villages.villager:is_named()
return self.nametag ~= ""
end
-- working_villages.villager.has_item_in_main reports whether the villager has item.
function working_villages.villager:has_item_in_main(pred)
-- smart_villages.villager.has_item_in_main reports whether the villager has item.
function smart_villages.villager:has_item_in_main(pred)
local inv = self:get_inventory()
local stacks = inv:get_list("main")
@ -249,8 +249,8 @@ function working_villages.villager:has_item_in_main(pred)
end
end
-- working_villages.villager.change_direction change direction to destination and velocity vector.
function working_villages.villager:change_direction(destination)
-- smart_villages.villager.change_direction change direction to destination and velocity vector.
function smart_villages.villager:change_direction(destination)
local position = self.object:getpos()
local direction = vector.subtract(destination, position)
direction.y = 0
@ -260,8 +260,8 @@ function working_villages.villager:change_direction(destination)
self:set_yaw_by_direction(direction)
end
-- working_villages.villager.change_direction_randomly change direction randonly.
function working_villages.villager:change_direction_randomly()
-- smart_villages.villager.change_direction_randomly change direction randonly.
function smart_villages.villager:change_direction_randomly()
local direction = {
x = math.random(0, 5) * 2 - 5,
y = 0,
@ -270,29 +270,29 @@ function working_villages.villager:change_direction_randomly()
local velocity = vector.multiply(vector.normalize(direction), 1.5)
self.object:setvelocity(velocity)
self:set_yaw_by_direction(direction)
self:set_animation(working_villages.animation_frames.WALK)
self:set_animation(smart_villages.animation_frames.WALK)
end
-- working_villages.villager.get_timer get the value of a counter.
function working_villages.villager:get_timer(timerId)
-- smart_villages.villager.get_timer get the value of a counter.
function smart_villages.villager:get_timer(timerId)
return self.time_counters[timerId]
end
-- working_villages.villager.set_timer set the value of a counter.
function working_villages.villager:set_timer(timerId,value)
-- smart_villages.villager.set_timer set the value of a counter.
function smart_villages.villager:set_timer(timerId,value)
assert(type(value)=="number","timers need to be countable")
self.time_counters[timerId]=value
end
-- working_villages.villager.clear_timers set all counters to 0.
function working_villages.villager:clear_timers()
-- smart_villages.villager.clear_timers set all counters to 0.
function smart_villages.villager:clear_timers()
for timerId,_ in pairs(self.time_counters) do
self.time_counters[timerId] = 0
end
end
-- working_villages.villager.count_timer count a counter up by 1.
function working_villages.villager:count_timer(timerId)
-- smart_villages.villager.count_timer count a counter up by 1.
function smart_villages.villager:count_timer(timerId)
if not self.time_counters[timerId] then
minetest.log("info","timer \""..timerId.."\" was not initialized")
self.time_counters[timerId] = 0
@ -300,15 +300,15 @@ function working_villages.villager:count_timer(timerId)
self.time_counters[timerId] = self.time_counters[timerId] + 1
end
-- working_villages.villager.count_timers count all counters up by 1.
function working_villages.villager:count_timers()
-- smart_villages.villager.count_timers count all counters up by 1.
function smart_villages.villager:count_timers()
for id, counter in pairs(self.time_counters) do
self.time_counters[id] = counter + 1
end
end
-- working_villages.villager.timer_exceeded if a timer exceeds the limit it will be reset and true is returned
function working_villages.villager:timer_exceeded(timerId,limit)
-- smart_villages.villager.timer_exceeded if a timer exceeds the limit it will be reset and true is returned
function smart_villages.villager:timer_exceeded(timerId,limit)
if self:get_timer(timerId)>=limit then
self:set_timer(timerId,0)
return true
@ -317,8 +317,8 @@ function working_villages.villager:timer_exceeded(timerId,limit)
end
end
-- working_villages.villager.update_infotext updates the infotext of the villager.
function working_villages.villager:update_infotext()
-- smart_villages.villager.update_infotext updates the infotext of the villager.
function smart_villages.villager:update_infotext()
local infotext = ""
local job_name = self:get_job()
@ -339,18 +339,18 @@ function working_villages.villager:update_infotext()
self.object:set_properties{infotext = infotext}
end
-- working_villages.villager.is_near checks if the villager is withing the radius of a position
function working_villages.villager:is_near(pos, distance)
-- smart_villages.villager.is_near checks if the villager is withing the radius of a position
function smart_villages.villager:is_near(pos, distance)
local p = self.object:getpos()
p.y = p.y + 0.5
return vector.distance(p, pos) < distance
end
--working_villages.villager.handle_obstacles(ignore_fence,ignore_doors)
--smart_villages.villager.handle_obstacles(ignore_fence,ignore_doors)
--if the villager hits a walkable he wil jump
--if ignore_fence is false and the villager hits a door he opens it
--if ignore_fence is false the villager will not jump over fences
function working_villages.villager:handle_obstacles(ignore_fence,ignore_doors)
function smart_villages.villager:handle_obstacles(ignore_fence,ignore_doors)
local velocity = self.object:getvelocity()
--local inside_node = minetest.get_node(self.object:getpos())
--if string.find(inside_node.name,"doors:door") and not ignore_doors then
@ -381,8 +381,8 @@ function working_villages.villager:handle_obstacles(ignore_fence,ignore_doors)
end
end
-- working_villages.villager.pickup_item pickup items placed and put it to main slot.
function working_villages.villager:pickup_item()
-- smart_villages.villager.pickup_item pickup items placed and put it to main slot.
function smart_villages.villager:pickup_item()
local pos = self.object:getpos()
local radius = 1.0
local all_objects = minetest.get_objects_inside_radius(pos, radius)
@ -407,14 +407,14 @@ function working_villages.villager:pickup_item()
end
end
-- working_villages.villager.is_active check if the villager is paused.
function working_villages.villager:is_active()
-- smart_villages.villager.is_active check if the villager is paused.
function smart_villages.villager:is_active()
return self.pause == "active"
end
dofile(working_villages.modpath.."/async_actions.lua") --load states
dofile(smart_villages.modpath.."/async_actions.lua") --load states
function working_villages.villager:set_state(id) --deprecated
function smart_villages.villager:set_state(id) --deprecated
if id == "idle" then
print("the idle state is deprecated")
elseif id == "goto_dest" then
@ -434,15 +434,15 @@ end
---------------------------------------------------------------------
-- working_villages.manufacturing_data represents a table that contains manufacturing data.
-- smart_villages.manufacturing_data represents a table that contains manufacturing data.
-- this table's keys are product names, and values are manufacturing numbers
-- that has been already manufactured.
working_villages.manufacturing_data = (function()
local file_name = minetest.get_worldpath() .. "/working_villages_data"
smart_villages.manufacturing_data = (function()
local file_name = minetest.get_worldpath() .. "/smart_villages_data"
minetest.register_on_shutdown(function()
local file = io.open(file_name, "w")
file:write(minetest.serialize(working_villages.manufacturing_data))
file:write(minetest.serialize(smart_villages.manufacturing_data))
file:close()
end)
@ -460,8 +460,8 @@ end) ()
-- register empty item entity definition.
-- this entity may be hold by villager's hands.
do
minetest.register_craftitem("working_villages:dummy_empty_craftitem", {
wield_image = "working_villages_dummy_empty_craftitem.png",
minetest.register_craftitem("smart_villages:dummy_empty_craftitem", {
wield_image = "smart_villages_dummy_empty_craftitem.png",
})
local function on_activate(self)
@ -470,9 +470,9 @@ do
for _, obj in ipairs(all_objects) do
local luaentity = obj:get_luaentity()
if working_villages.is_villager(luaentity.name) then
if smart_villages.is_villager(luaentity.name) then
self.object:set_attach(obj, "Arm_R", {x = 0.065, y = 0.50, z = -0.15}, {x = -45, y = 0, z = 0})
self.object:set_properties{textures={"working_villages:dummy_empty_craftitem"}}
self.object:set_properties{textures={"smart_villages:dummy_empty_craftitem"}}
return
end
end
@ -483,13 +483,13 @@ do
for _, obj in ipairs(all_objects) do
local luaentity = obj:get_luaentity()
if working_villages.is_villager(luaentity.name) then
if smart_villages.is_villager(luaentity.name) then
local stack = luaentity:get_wield_item_stack()
if stack:get_name() ~= self.itemname then
if stack:is_empty() then
self.itemname = ""
self.object:set_properties{textures={"working_villages:dummy_empty_craftitem"}}
self.object:set_properties{textures={"smart_villages:dummy_empty_craftitem"}}
else
self.itemname = stack:get_name()
self.object:set_properties{textures={self.itemname}}
@ -503,7 +503,7 @@ do
return
end
minetest.register_entity("working_villages:dummy_item", {
minetest.register_entity("smart_villages:dummy_item", {
hp_max = 1,
visual = "wielditem",
visual_size = {x = 0.025, y = 0.025},
@ -518,20 +518,25 @@ end
---------------------------------------------------------------------
-- working_villages.register_job registers a definition of a new job.
function working_villages.register_job(job_name, def)
working_villages.registered_jobs[job_name] = def
-- smart_villages.register_job registers a definition of a new job.
function smart_villages.register_job(job_name, def, recipe)
smart_villages.registered_jobs[job_name] = def
minetest.register_tool(job_name, {
stack_max = 1,
description = def.description,
inventory_image = def.inventory_image,
})
if recipe ~= nil then
minetest.register_craft({
output = job_name,
recipe = recipe
})
end
end
-- working_villages.register_egg registers a definition of a new egg.
function working_villages.register_egg(egg_name, def)
working_villages.registered_eggs[egg_name] = def
-- smart_villages.register_egg registers a definition of a new egg.
function smart_villages.register_egg(egg_name, def)
smart_villages.registered_eggs[egg_name] = def
minetest.register_tool(egg_name, {
description = def.description,
@ -556,13 +561,13 @@ function working_villages.register_egg(egg_name, def)
})
end
-- working_villages.register_villager registers a definition of a new villager.
function working_villages.register_villager(product_name, def)
working_villages.registered_villagers[product_name] = def
-- smart_villages.register_villager registers a definition of a new villager.
function smart_villages.register_villager(product_name, def)
smart_villages.registered_villagers[product_name] = def
-- initialize manufacturing number of a new villager.
if working_villages.manufacturing_data[product_name] == nil then
working_villages.manufacturing_data[product_name] = 0
if smart_villages.manufacturing_data[product_name] == nil then
smart_villages.manufacturing_data[product_name] = 0
end
-- create_inventory creates a new inventory, and returns it.
@ -572,7 +577,7 @@ function working_villages.register_villager(product_name, def)
on_put = function(_, listname, _, stack) --inv, listname, index, stack, player
if listname == "job" then
local job_name = stack:get_name()
local job = working_villages.registered_jobs[job_name]
local job = smart_villages.registered_jobs[job_name]
if type(job.on_start)=="function" then
job.on_start(self)
self.job_thread = coroutine.create(job.on_step)
@ -587,7 +592,7 @@ function working_villages.register_villager(product_name, def)
-- only jobs can put to a job inventory.
if listname == "main" then
return stack:get_count()
elseif listname == "job" and working_villages.is_job(stack:get_name()) then
elseif listname == "job" and smart_villages.is_job(stack:get_name()) then
return stack:get_count()
elseif listname == "wield_item" then
return 0
@ -598,7 +603,7 @@ function working_villages.register_villager(product_name, def)
on_take = function(_, listname, _, stack) --inv, listname, index, stack, player
if listname == "job" then
local job_name = stack:get_name()
local job = working_villages.registered_jobs[job_name]
local job = smart_villages.registered_jobs[job_name]
self.time_counters = {}
if job then
if type(job.on_stop)=="function" then
@ -622,7 +627,7 @@ function working_villages.register_villager(product_name, def)
--inv, from_list, from_index, to_list, to_index, count, player
if to_list == "job" or from_list == "job" then
local job_name = inv:get_stack(to_list, to_index):get_name()
local job = working_villages.registered_jobs[job_name]
local job = smart_villages.registered_jobs[job_name]
if to_list == "job" then
if type(job.on_start)=="function" then
@ -651,7 +656,7 @@ function working_villages.register_villager(product_name, def)
if to_list == "main" then
return count
elseif to_list == "job" and working_villages.is_job(inv:get_stack(from_list, from_index):get_name()) then
elseif to_list == "job" and smart_villages.is_job(inv:get_stack(from_list, from_index):get_name()) then
return count
end
@ -671,12 +676,12 @@ function working_villages.register_villager(product_name, def)
-- parse the staticdata, and compose a inventory.
if staticdata == "" then
self.product_name = product_name
self.manufacturing_number = working_villages.manufacturing_data[product_name]
working_villages.manufacturing_data[product_name] = working_villages.manufacturing_data[product_name] + 1
self.manufacturing_number = smart_villages.manufacturing_data[product_name]
smart_villages.manufacturing_data[product_name] = smart_villages.manufacturing_data[product_name] + 1
create_inventory(self)
-- attach dummy item to new villager.
minetest.add_entity(self.object:getpos(), "working_villages:dummy_item")
minetest.add_entity(self.object:getpos(), "smart_villages:dummy_item")
else
-- if static data is not empty string, this object has beed already created.
local data = minetest.deserialize(staticdata)
@ -787,12 +792,12 @@ function working_villages.register_villager(product_name, def)
-- on_rightclick is a callback function that is called when a player right-click them.
local function on_rightclick(self, clicker)
local wielded_stack = clicker:get_wielded_item()
if wielded_stack:get_name() == "working_villages:commanding_sceptre"
if wielded_stack:get_name() == "smart_villages:commanding_sceptre"
and clicker:get_player_name() == self.owner_name then
working_villages.forms.show_inv_formspec(self, clicker:get_player_name())
smart_villages.forms.show_inv_formspec(self, clicker:get_player_name())
else
working_villages.forms.show_talking_formspec(self, clicker:get_player_name())
smart_villages.forms.show_talking_formspec(self, clicker:get_player_name())
end
self:update_infotext()
end
@ -804,7 +809,7 @@ function working_villages.register_villager(product_name, def)
-- register a definition of a new villager.
local villager_def = table.copy(working_villages.villager)
local villager_def = table.copy(smart_villages.villager)
-- basic initial properties
villager_def.hp_max = def.hp_max
villager_def.weight = def.weight
@ -838,20 +843,20 @@ function working_villages.register_villager(product_name, def)
villager_def.get_staticdata = get_staticdata
-- home methods
villager_def.get_home = working_villages.get_home
villager_def.has_home = working_villages.is_valid_home
villager_def.get_home = smart_villages.get_home
villager_def.has_home = smart_villages.is_valid_home
minetest.register_entity(product_name, villager_def)
-- register villager egg.
working_villages.register_egg(product_name .. "_egg", {
smart_villages.register_egg(product_name .. "_egg", {
description = product_name .. " egg",
inventory_image = def.egg_image,
product_name = product_name,
})
end
function working_villages.random_texture(...)
function smart_villages.random_texture(...)
math.randomseed(os.time())
local args = { ... }
return args[math.random(1, #args)]

View File

@ -1,10 +1,10 @@
function working_villages.villager:go_to(pos)
function smart_villages.villager:go_to(pos)
self.destination=vector.round(pos)
if working_villages.func.walkable_pos(self.destination) then
self.destination=working_villages.pathfinder.get_ground_level(vector.round(self.destination))
if smart_villages.func.walkable_pos(self.destination) then
self.destination=smart_villages.pathfinder.get_ground_level(vector.round(self.destination))
end
local val_pos = working_villages.func.validate_pos(self.object:getpos())
self.path = working_villages.pathfinder.get_reachable(val_pos,self.destination,self)
local val_pos = smart_villages.func.validate_pos(self.object:getpos())
self.path = smart_villages.pathfinder.get_reachable(val_pos,self.destination,self)
self:set_timer("go_to:find_path",0) -- find path interval
self:set_timer("go_to:change_dir",0)
self:set_timer("go_to:give_up",0)
@ -15,20 +15,20 @@ function working_villages.villager:go_to(pos)
end
--print("the first waypiont on his path:" .. minetest.pos_to_string(self.path[1]))
self:change_direction(self.path[1])
self:set_animation(working_villages.animation_frames.WALK)
self:set_animation(smart_villages.animation_frames.WALK)
while #self.path ~= 0 do
self:count_timer("go_to:find_path")
self:count_timer("go_to:change_dir")
if self:timer_exceeded("go_to:find_path",100) then
val_pos = working_villages.func.validate_pos(self.object:getpos())
local path = working_villages.pathfinder.get_reachable(val_pos,self.destination,self)
val_pos = smart_villages.func.validate_pos(self.object:getpos())
local path = smart_villages.pathfinder.get_reachable(val_pos,self.destination,self)
if path == nil then
self:count_timer("go_to:give_up")
if self:timer_exceeded("go_to:give_up",3) then
self.destination=vector.round(self.destination)
if working_villages.func.walkable_pos(self.destination) then
self.destination=working_villages.pathfinder.get_ground_level(vector.round(self.destination))
if smart_villages.func.walkable_pos(self.destination) then
self.destination=smart_villages.pathfinder.get_ground_level(vector.round(self.destination))
end
print("villager can't find path")
--FIXME: we ought to give up at this point
@ -60,12 +60,12 @@ function working_villages.villager:go_to(pos)
end
self.object:setvelocity{x = 0, y = 0, z = 0}
self.path = nil
self:set_animation(working_villages.animation_frames.STAND)
self:set_animation(smart_villages.animation_frames.STAND)
end
function working_villages.villager:dig(pos)
function smart_villages.villager:dig(pos)
self.object:setvelocity{x = 0, y = 0, z = 0}
self:set_animation(working_villages.animation_frames.MINE)
self:set_animation(smart_villages.animation_frames.MINE)
self:set_yaw_by_direction(vector.subtract(pos, self.object:getpos()))
for _=0,30 do coroutine.yield() end --wait 30 steps
local destnode = minetest.get_node(pos)
@ -82,10 +82,10 @@ function working_villages.villager:dig(pos)
minetest.sound_play(sound,{object=self.object, max_hear_distance = 10})
end
end
self:set_animation(working_villages.animation_frames.STAND)
self:set_animation(smart_villages.animation_frames.STAND)
end
function working_villages.villager:place(item,pos)
function smart_villages.villager:place(item,pos)
if type(pos)~="table" then
error("no target position given")
end
@ -102,9 +102,9 @@ function working_villages.villager:place(item,pos)
if pred(wield_stack:get_name()) or self:move_main_to_wield(pred) then
--set animation
if self.object:getvelocity().x==0 and self.object:getvelocity().z==0 then
self:set_animation(working_villages.animation_frames.MINE)
self:set_animation(smart_villages.animation_frames.MINE)
else
self:set_animation(working_villages.animation_frames.WALK_MINE)
self:set_animation(smart_villages.animation_frames.WALK_MINE)
end
--turn to target
self:set_yaw_by_direction(vector.subtract(pos, self.object:getpos()))
@ -135,16 +135,16 @@ function working_villages.villager:place(item,pos)
end
--reset animation
if self.object:getvelocity().x==0 and self.object:getvelocity().z==0 then
self:set_animation(working_villages.animation_frames.STAND)
self:set_animation(smart_villages.animation_frames.STAND)
else
self:set_animation(working_villages.animation_frames.WALK)
self:set_animation(smart_villages.animation_frames.WALK)
end
else
minetest.chat_send_player(self.owner_name,"villager couldn't place item")
end
end
function working_villages.villager.wait_until_dawn()
function smart_villages.villager.wait_until_dawn()
local daytime = minetest.get_timeofday()
while (daytime < 0.2 or daytime > 0.76) do
coroutine.yield()
@ -153,20 +153,20 @@ function working_villages.villager.wait_until_dawn()
--print("wake up:"..daytime)
end
function working_villages.villager:sleep()
function smart_villages.villager:sleep()
minetest.log("action","a villager is laying down")
self.object:setvelocity{x = 0, y = 0, z = 0}
local bed_pos=self:get_home():get_bed()
local bed_top = working_villages.func.find_adjacent_pos(bed_pos,
local bed_top = smart_villages.func.find_adjacent_pos(bed_pos,
function(p) return string.find(minetest.get_node(p).name,"_top") end)
local bed_bottom = working_villages.func.find_adjacent_pos(bed_pos,
local bed_bottom = smart_villages.func.find_adjacent_pos(bed_pos,
function(p) return string.find(minetest.get_node(p).name,"_bottom") end)
if bed_top and bed_bottom then
self:set_yaw_by_direction(vector.subtract(bed_bottom, bed_top))
else
minetest.log("info","no bed found")
end
self:set_animation(working_villages.animation_frames.LAY)
self:set_animation(smart_villages.animation_frames.LAY)
self.object:setpos(bed_pos)
self.pause="sleeping"
self:update_infotext()
@ -176,21 +176,21 @@ function working_villages.villager:sleep()
local pos=self.object:getpos()
self.object:setpos({x=pos.x,y=pos.y+0.5,z=pos.z})
minetest.log("action","a villager gets up")
self:set_animation(working_villages.animation_frames.STAND)
self:set_animation(smart_villages.animation_frames.STAND)
self.pause="active"
self:update_infotext()
end
function working_villages.villager:goto_bed()
if working_villages.debug_logging then
function smart_villages.villager:goto_bed()
if smart_villages.debug_logging then
minetest.log("action",self.inventory_name.." is going home")
end
if not self:has_home() then
self:set_animation(working_villages.animation_frames.SIT)
self:set_animation(smart_villages.animation_frames.SIT)
self.pause="sleeping"
self:update_infotext()
self.wait_until_dawn()
self:set_animation(working_villages.animation_frames.STAND)
self:set_animation(smart_villages.animation_frames.STAND)
self.pause="active"
self:update_infotext()
else
@ -198,10 +198,10 @@ function working_villages.villager:goto_bed()
if not bed_pos then
minetest.log("warning","villager couldn't find his bed")
--perhaps go home
self:set_animation(working_villages.animation_frames.SIT)
self:set_animation(smart_villages.animation_frames.SIT)
self.wait_until_dawn()
else
if working_villages.debug_logging then
if smart_villages.debug_logging then
minetest.log("info","his bed is at:" .. bed_pos.x .. ",".. bed_pos.y .. ",".. bed_pos.z)
end
self:go_to(bed_pos)

View File

@ -1,11 +1,11 @@
minetest.register_tool("working_villages:commanding_sceptre", {
minetest.register_tool("smart_villages:commanding_sceptre", {
description = "villager commanding sceptre",
inventory_image = "working_villages_commanding_sceptre.png",
inventory_image = "smart_villages_commanding_sceptre.png",
on_use = function(itemstack, user, pointed_thing)
if (pointed_thing.type == "object") then
local obj = pointed_thing.ref
local luaentity = obj:get_luaentity()
if not working_villages.is_villager(luaentity.name) then
if not smart_villages.is_villager(luaentity.name) then
if luaentity.name == "__builtin:item" then
luaentity:on_punch(user)
end
@ -26,7 +26,7 @@ minetest.register_tool("working_villages:commanding_sceptre", {
job.on_pause(luaentity)
end
luaentity.object:setvelocity{x = 0, y = 0, z = 0}
luaentity:set_animation(working_villages.animation_frames.STAND)
luaentity:set_animation(smart_villages.animation_frames.STAND)
luaentity:update_infotext()
end
end

View File

@ -1,6 +1,12 @@
local func = working_villages.func
local func = smart_villages.func
smart_villages.hasbasic_materials = false
for key, value in ipairs(minetest.get_modnames()) do
if(value=="basic_materials") then
smart_villages.hasbasic_materials = true
end
end
function working_villages.func.villager_state_machine_job(job_name,job_description,actions, sprop)
function smart_villages.func.villager_state_machine_job(job_name,job_description,actions, sprop)
minetest.log("warning","old util jobdef should be replaced by jobfunc registration")
minetest.log("warning","old util jobdef: "..job_name)
@ -36,7 +42,7 @@ function working_villages.func.villager_state_machine_job(job_name,job_descripti
self_cond=true
end
if search_state.search_condition ~= nil and self_cond then
local target = working_villages.func.search_surrounding(
local target = smart_villages.func.search_surrounding(
self.object:getpos(), search_state.search_condition, sprop.searching_range)
if target ~= nil then
local destination = func.find_adjacent_clear(target)
@ -44,12 +50,12 @@ function working_villages.func.villager_state_machine_job(job_name,job_descripti
print("failure: no adjacent walkable found")
destination = target
end
local val_pos = working_villages.func.validate_pos(self.object:getpos())
if working_villages.debug_logging then
local val_pos = smart_villages.func.validate_pos(self.object:getpos())
if smart_villages.debug_logging then
minetest.log("info","looking for a path from " .. minetest.pos_to_string(val_pos) ..
" to " .. minetest.pos_to_string(destination))
end
if working_villages.pathfinder.get_reachable(val_pos,destination,self) then
if smart_villages.pathfinder.get_reachable(val_pos,destination,self) then
--print("path found to: " .. minetest.pos_to_string(destination))
if search_state.to_state then
search_state.to_state(self, destination, target)
@ -66,13 +72,13 @@ function working_villages.func.villager_state_machine_job(job_name,job_descripti
and distance.y<=sprop.searching_range.y
and distance.z<=sprop.searching_range.z then
local destination = working_villages.func.validate_pos(target)
local val_pos = working_villages.func.validate_pos(self.object:getpos())
if working_villages.debug_logging then
local destination = smart_villages.func.validate_pos(target)
local val_pos = smart_villages.func.validate_pos(self.object:getpos())
if smart_villages.debug_logging then
minetest.log("info","looking for a path from " .. minetest.pos_to_string(val_pos) ..
" to " .. minetest.pos_to_string(destination))
end
if working_villages.pathfinder.get_reachable(val_pos,destination,self) then
if smart_villages.pathfinder.get_reachable(val_pos,destination,self) then
--print("path found to: " .. minetest.pos_to_string(destination))
if search_state.to_state then
search_state.to_state(self, destination, target)
@ -106,7 +112,7 @@ function working_villages.func.villager_state_machine_job(job_name,job_descripti
local function to_walk_randomly(self)
self:set_timer(1,20)
self:set_timer(2,0)
self:set_animation(working_villages.animation_frames.WALK)
self:set_animation(smart_villages.animation_frames.WALK)
end
local function s_search_idle(self)
@ -123,15 +129,15 @@ function working_villages.func.villager_state_machine_job(job_name,job_descripti
self_cond=true
end
if search_state.search_condition ~= nil and self_cond then
local target = working_villages.func.search_surrounding(self.object:getpos(),
local target = smart_villages.func.search_surrounding(self.object:getpos(),
search_state.search_condition, sprop.searching_range)
if target ~= nil then
local destination = func.find_adjacent_clear(target)
if not(destination) then
destination = target
end
local val_pos = working_villages.func.validate_pos(self.object:getpos())
if working_villages.pathfinder.get_reachable(val_pos,destination,self) then
local val_pos = smart_villages.func.validate_pos(self.object:getpos())
if smart_villages.pathfinder.get_reachable(val_pos,destination,self) then
if search_state.to_state then
search_state.to_state(self, destination, target)
end
@ -157,7 +163,7 @@ function working_villages.func.villager_state_machine_job(job_name,job_descripti
self:set_timer(1,0)
self:set_timer(2,0)
self.object:setvelocity{x = 0, y = 0, z = 0}
self:set_animation(working_villages.animation_frames.STAND)
self:set_animation(smart_villages.animation_frames.STAND)
end
--sleeping states
@ -166,7 +172,7 @@ function working_villages.func.villager_state_machine_job(job_name,job_descripti
local pos=self.object:getpos()
self.object:setpos({x=pos.x,y=pos.y+0.5,z=pos.z})
minetest.log("action","a villager gets up")
self:set_animation(working_villages.animation_frames.STAND)
self:set_animation(smart_villages.animation_frames.STAND)
self.pause="active"
self:update_infotext()
return true
@ -177,22 +183,22 @@ function working_villages.func.villager_state_machine_job(job_name,job_descripti
minetest.log("action","a villager is laying down")
self.object:setvelocity{x = 0, y = 0, z = 0}
local bed_pos=self:get_home():get_bed()
local bed_top = working_villages.func.find_adjacent_pos(bed_pos,
local bed_top = smart_villages.func.find_adjacent_pos(bed_pos,
function(p) return string.find(minetest.get_node(p).name,"_top") end)
local bed_bottom = working_villages.func.find_adjacent_pos(bed_pos,
local bed_bottom = smart_villages.func.find_adjacent_pos(bed_pos,
function(p) return string.find(minetest.get_node(p).name,"_bottom") end)
if bed_top and bed_bottom then
self:set_yaw_by_direction(vector.subtract(bed_bottom, bed_top))
else
minetest.log("info","no bed found")
end
self:set_animation(working_villages.animation_frames.LAY)
self:set_animation(smart_villages.animation_frames.LAY)
self.object:setpos(vector.add(bed_pos,{x=0,y=1.5,z=0}))
self.pause="sleeping"
self:update_infotext()
end
local function to_walk_home(self)
if working_villages.debug_logging then
if smart_villages.debug_logging then
minetest.log("action","a villager is going home")
end
self.destination=self:get_home():get_bed()
@ -200,7 +206,7 @@ function working_villages.func.villager_state_machine_job(job_name,job_descripti
minetest.log("warning","villager couldn't find his bed")
return
end
if working_villages.debug_logging then
if smart_villages.debug_logging then
minetest.log("info","his bed is at:" .. self.destination.x .. ",".. self.destination.y .. ",".. self.destination.z)
end
self:set_state("goto_dest")
@ -221,7 +227,7 @@ function working_villages.func.villager_state_machine_job(job_name,job_descripti
newStates.GO_OUT = {number=1,
func=function() return true end,
to_state=function(self)
if working_villages.debug_logging then
if smart_villages.debug_logging then
minetest.log("action","a villager stood up and is going outside")
end
self.destination=self:get_home():get_door()
@ -271,7 +277,7 @@ function working_villages.func.villager_state_machine_job(job_name,job_descripti
self.job_state = nil
self.time_counters = nil
self.path = nil
self:set_animation(working_villages.animation_frames.STAND)
self:set_animation(smart_villages.animation_frames.STAND)
end
local function on_resume(self)
local job = self:get_job()
@ -283,7 +289,7 @@ function working_villages.func.villager_state_machine_job(job_name,job_descripti
local function on_pause(self)
self.object:setvelocity{x = 0, y = 0, z = 0}
self.job_state = nil
self:set_animation(working_villages.animation_frames.STAND)
self:set_animation(smart_villages.animation_frames.STAND)
end
local function on_step(self)
if self.job_state.next_state ~= nil then
@ -295,12 +301,12 @@ function working_villages.func.villager_state_machine_job(job_name,job_descripti
end
else
if self.job_state.func==nil or self.job_state.func(self) then
working_villages.func.get_back_to_searching(self)
smart_villages.func.get_back_to_searching(self)
end
end
end
working_villages.register_job("working_villages:"..job_name, {
description = "working_villages job : "..job_description,
smart_villages.register_job("smart_villages:"..job_name, {
description = "smart_villages job : "..job_description,
inventory_image = "default_paper.png^memorandum_letters.png",
on_start = on_start,
on_stop = on_stop,
@ -311,7 +317,7 @@ function working_villages.func.villager_state_machine_job(job_name,job_descripti
})
end
function working_villages.func.get_back_to_searching(self)
function smart_villages.func.get_back_to_searching(self)
local myJob = self:get_job()
if myJob and myJob.states and myJob.states.SEARCH then
self.job_state = myJob.states.SEARCH

View File

@ -1,6 +1,6 @@
working_villages.forms = {}
smart_villages.forms = {}
function working_villages.forms.show_inv_formspec(self, playername)
function smart_villages.forms.show_inv_formspec(self, playername)
local home_pos = {x = 0, y = 0, z = 0}
if self:has_home() then
home_pos = self:get_home():get_marker()
@ -22,7 +22,7 @@ function working_villages.forms.show_inv_formspec(self, playername)
minetest.show_formspec(playername,"villager:gui_inv_"..self.inventory_name, formstring)
end
function working_villages.forms.show_talking_formspec(self, playername)
function smart_villages.forms.show_talking_formspec(self, playername)
local jobname = self:get_job()
if jobname then
jobname = jobname.description
@ -64,12 +64,12 @@ minetest.register_on_player_receive_fields(
"do not exist in our coordinate system. Correct coordinates range from -30912 to 30927 in all axes.")
return
end
if minetest.get_node(coords).name ~= "working_villages:home_marker" then
if minetest.get_node(coords).name ~= "smart_villages:home_marker" then
minetest.chat_send_player(sender_name, 'No home marker could be found at the entered position.')
return
end
working_villages.set_home(inv_name,coords)
smart_villages.set_home(inv_name,coords)
minetest.chat_send_player(sender_name, 'Home set!')
if not minetest.get_meta(coords):get_string("bed") then

View File

@ -1,11 +1,11 @@
-- working_villages.homes represents a table that contains the villagers homes.
-- smart_villages.homes represents a table that contains the villagers homes.
-- This table's keys are inventory names, and values are home objects.
working_villages.homes = (function()
local file_name = minetest.get_worldpath() .. "/working_villages_homes"
smart_villages.homes = (function()
local file_name = minetest.get_worldpath() .. "/smart_villages_homes"
minetest.register_on_shutdown(function()
local save_data = {}
for k,v in pairs(working_villages.homes) do
for k,v in pairs(smart_villages.homes) do
save_data[k]={marker=v.marker}
end
local file = io.open(file_name, "w")
@ -32,8 +32,8 @@ local function out_of_limit(pos)
return true
end
minetest.register_node("working_villages:home_marker", {
description = "home marker for working_villages",
minetest.register_node("smart_villages:home_marker", {
description = "home marker for smart_villages",
drawtype = "nodebox",
tiles = {"default_sign_wall_wood.png"},
inventory_image = "default_sign_wood.png",
@ -127,21 +127,21 @@ minetest.register_node("working_villages:home_marker", {
})
-- home is a prototype home object
working_villages.home = {version = 1}
smart_villages.home = {version = 1}
-- get the home of a villager
function working_villages.get_home(self)
return working_villages.homes[self.inventory_name]
function smart_villages.get_home(self)
return smart_villages.homes[self.inventory_name]
end
-- check whether a villager has a home
function working_villages.is_valid_home(self)
local home = working_villages.get_home(self)
function smart_villages.is_valid_home(self)
local home = smart_villages.get_home(self)
if home == nil then
return false
end
if not home.version~=1 then --update home
for k, v in pairs(working_villages.home) do
for k, v in pairs(smart_villages.home) do
home[k] = v
end
end
@ -149,17 +149,17 @@ function working_villages.is_valid_home(self)
end
-- get the position of the home_marker
function working_villages.home:get_marker()
function smart_villages.home:get_marker()
return self.marker
end
function working_villages.home:get_marker_meta()
function smart_villages.home:get_marker_meta()
local home_marker_pos = self:get_marker()
if minetest.get_node(home_marker_pos).name == "ignore" then
minetest.get_voxel_manip():read_from_map(home_marker_pos, home_marker_pos)
end
if minetest.get_node(home_marker_pos).name ~= "working_villages:home_marker" then
if working_villages.debug_logging and not(vector.equals(home_marker_pos,{x=0,y=0,z=0})) then
if minetest.get_node(home_marker_pos).name ~= "smart_villages:home_marker" then
if smart_villages.debug_logging and not(vector.equals(home_marker_pos,{x=0,y=0,z=0})) then
minetest.log("warning", "The door position of an invalid home was requested.")
minetest.log("warning", "Given home position:" .. minetest.pos_to_string(home_marker_pos))
end
@ -169,14 +169,14 @@ function working_villages.home:get_marker_meta()
end
-- get the position that marks "outside"
function working_villages.home:get_door()
function smart_villages.home:get_door()
if self.door~=nil then
return self.door
end
local meta = self:get_marker_meta()
local door_pos = meta:get_string("door")
if not door_pos then
if working_villages.debug_logging then
if smart_villages.debug_logging then
local home_marker_pos = self:get_marker()
minetest.log("warning", "The position outside the house was not entered for the home at:" ..
minetest.pos_to_string(home_marker_pos))
@ -188,7 +188,7 @@ function working_villages.home:get_door()
end
-- get the bed of a villager
function working_villages.home:get_bed()
function smart_villages.home:get_bed()
if self.bed~=nil then
return self.bed
end
@ -196,7 +196,7 @@ function working_villages.home:get_bed()
local meta = self:get_marker_meta()
local bed_pos = meta:get_string("bed")
if not bed_pos then
if working_villages.debug_logging then
if smart_villages.debug_logging then
local home_marker_pos = self:get_marker()
minetest.log("warning", "The position of the bed was not entered for the home at:" ..
minetest.pos_to_string(home_marker_pos))
@ -208,7 +208,7 @@ function working_villages.home:get_bed()
end
-- set the home of a villager
function working_villages.set_home(inv_name,marker_pos)
working_villages.homes[inv_name] = table.copy(working_villages.home)
working_villages.homes[inv_name].marker = marker_pos
function smart_villages.set_home(inv_name,marker_pos)
smart_villages.homes[inv_name] = table.copy(smart_villages.home)
smart_villages.homes[inv_name].marker = marker_pos
end

View File

@ -5,34 +5,34 @@ else
print("[MOD] "..minetest.get_current_modname()..": loading")
end
working_villages={
modpath=minetest.get_modpath("working_villages"),
smart_villages={
modpath=minetest.get_modpath("smart_villages"),
debug_logging=true,
func = {}
}
--helpers
dofile(working_villages.modpath.."/pathfinder.lua")
dofile(working_villages.modpath.."/forms.lua")
dofile(working_villages.modpath.."/homes.lua")
dofile(smart_villages.modpath.."/pathfinder.lua")
dofile(smart_villages.modpath.."/forms.lua")
dofile(smart_villages.modpath.."/homes.lua")
--base
dofile(working_villages.modpath.."/api.lua")
dofile(working_villages.modpath.."/register.lua")
dofile(working_villages.modpath.."/commanding_sceptre.lua")
dofile(smart_villages.modpath.."/api.lua")
dofile(smart_villages.modpath.."/register.lua")
dofile(smart_villages.modpath.."/commanding_sceptre.lua")
dofile(working_villages.modpath.."/deprecated.lua")
dofile(smart_villages.modpath.."/deprecated.lua")
--jobs
dofile(working_villages.modpath.."/jobs/util.lua")
dofile(working_villages.modpath.."/jobs/empty.lua")
dofile(smart_villages.modpath.."/jobs/util.lua")
dofile(smart_villages.modpath.."/jobs/empty.lua")
dofile(working_villages.modpath.."/jobs/follow_player.lua")
dofile(working_villages.modpath.."/jobs/plant_collector.lua")
dofile(working_villages.modpath.."/jobs/woodcutter.lua")
dofile(smart_villages.modpath.."/jobs/follow_player.lua")
dofile(smart_villages.modpath.."/jobs/plant_collector.lua")
dofile(smart_villages.modpath.."/jobs/woodcutter.lua")
--testing jobs
dofile(working_villages.modpath.."/jobs/torcher.lua")
dofile(working_villages.modpath.."/jobs/snowclearer.lua")
dofile(smart_villages.modpath.."/jobs/torcher.lua")
dofile(smart_villages.modpath.."/jobs/snowclearer.lua")
--ready
local time_to_load= os.clock() - init

View File

@ -1,5 +1,5 @@
working_villages.register_job("working_villages:job_empty", {
description = "working_villages job : empty",
smart_villages.register_job("smart_villages:job_empty", {
description = "smart_villages job : empty",
inventory_image = "default_paper.png",
on_start = function() end,
on_stop = function() end,
@ -11,7 +11,7 @@ working_villages.register_job("working_villages:job_empty", {
-- only a recipe of the empty job is registered.
-- other job is created by writing on the empty job.
minetest.register_craft{
output = "working_villages:job_empty",
output = "smart_villages:job_empty",
recipe = {
{"default:paper", "default:obsidian"},
},

View File

@ -1,5 +1,5 @@
working_villages.register_job("working_villages:job_folow_player", {
description = "working_villages job : follower",
smart_villages.register_job("smart_villages:job_folow_player", {
description = "smart_villages job : follower",
inventory_image = "default_paper.png^memorandum_letters.png",
jobfunc = function(self)
while (not self:is_active()) do
@ -16,12 +16,12 @@ working_villages.register_job("working_villages:job_folow_player", {
local velocity = self.object:getvelocity()
if vector.length(direction) < 3 then
if velocity.x~=0 or velocity.y~=0 then
self:set_animation(working_villages.animation_frames.STAND)
self:set_animation(smart_villages.animation_frames.STAND)
self.object:setvelocity{x = 0, y = velocity.y, z = 0}
end
else
if velocity.x==0 and velocity.y==0 then
self:set_animation(working_villages.animation_frames.WALK)
self:set_animation(smart_villages.animation_frames.WALK)
end
self.object:setvelocity{x = direction.x, y = velocity.y, z = direction.z}
self:set_yaw_by_direction(direction)

View File

@ -1,7 +1,6 @@
working_villages.herbs={
smart_villages.herbs={
groups = {
"flora",
"leaves"
},
names = {
"default:apple",
@ -13,18 +12,18 @@ working_villages.herbs={
}
}
function working_villages.func.is_herb(node)
function smart_villages.func.is_herb(node)
local nname=node
if type(nname)=="table" then
nname=nname.name
end
for _, i in ipairs(working_villages.herbs.groups) do
for _, i in ipairs(smart_villages.herbs.groups) do
if minetest.get_item_group(nname, i) > 0 then
--print("found some "..i)
return true
end
end
for _, i in ipairs(working_villages.herbs.names) do
for _, i in ipairs(smart_villages.herbs.names) do
if nname==i then
--print("found a "..nname)
return true
@ -34,7 +33,7 @@ function working_villages.func.is_herb(node)
end
local function find_herb(p)
return working_villages.func.is_herb(minetest.get_node(p).name)
return smart_villages.func.is_herb(minetest.get_node(p).name)
end
local function is_night()
@ -43,8 +42,8 @@ end
local searching_range = {x = 10, y = 3, z = 10}
working_villages.register_job("working_villages:job_herbcollector", {
description = "working_villages job : herb collector",
smart_villages.register_job("smart_villages:job_herbcollector", {
description = "smart_villages job : herb collector",
inventory_image = "default_paper.png^memorandum_letters.png",
jobfunc = function(self)
if is_night() then
@ -54,7 +53,7 @@ working_villages.register_job("working_villages:job_herbcollector", {
self:count_timer("herbcollector:change_dir")
self:handle_obstacles()
if self:timer_exceeded("herbcollector:search",20) then
local sapling = self:get_nearest_item_by_condition(working_villages.func.is_herb, searching_range)
local sapling = self:get_nearest_item_by_condition(smart_villages.func.is_herb, searching_range)
if sapling ~= nil then
local pos = sapling:getpos()
--print("found a sapling at:".. minetest.pos_to_string(pos))
@ -64,9 +63,9 @@ working_villages.register_job("working_villages:job_herbcollector", {
self:pickup_item()
end
end
local target = working_villages.func.search_surrounding(self.object:getpos(), find_herb, searching_range)
local target = smart_villages.func.search_surrounding(self.object:getpos(), find_herb, searching_range)
if target ~= nil then
local destination = working_villages.func.find_adjacent_clear(target)
local destination = smart_villages.func.find_adjacent_clear(target)
if destination==false then
print("failure: no adjacent walkable found")
destination = target

View File

@ -2,8 +2,8 @@ local function is_night() return minetest.get_timeofday() < 0.2 or minetest.get_
local function find_snow(p) return minetest.get_node(p).name == "default:snow" end
local searching_range = {x = 10, y = 3, z = 10}
working_villages.register_job("working_villages:job_snowclearer", {
description = "working_villages job : snowclearer",
smart_villages.register_job("smart_villages:job_snowclearer", {
description = "smart_villages job : snowclearer",
inventory_image = "default_paper.png^memorandum_letters.png",
jobfunc = function(self)
if is_night() then
@ -13,9 +13,9 @@ working_villages.register_job("working_villages:job_snowclearer", {
self:count_timer("snowclearer:change_dir")
self:handle_obstacles()
if self:timer_exceeded("snowclearer:search",20) then
local target = working_villages.func.search_surrounding(self.object:getpos(), find_snow, searching_range)
local target = smart_villages.func.search_surrounding(self.object:getpos(), find_snow, searching_range)
if target ~= nil then
local destination = working_villages.func.find_adjacent_clear(target)
local destination = smart_villages.func.find_adjacent_clear(target)
if destination==false then
print("failure: no adjacent walkable found")
destination = target

View File

@ -3,8 +3,8 @@ local function is_dark(pos)
return light_level <= 5
end
working_villages.register_job("working_villages:job_torcher", {
description = "working_villages job : torcher",
smart_villages.register_job("smart_villages:job_torcher", {
description = "smart_villages job : torcher",
inventory_image = "default_paper.png^memorandum_letters.png",
jobfunc = function(self)
while (not self:is_active()) do
@ -28,12 +28,12 @@ working_villages.register_job("working_villages:job_torcher", {
local velocity = self.object:getvelocity()
if vector.length(direction) < 3 then
if velocity.x~=0 or velocity.y~=0 then
self:set_animation(working_villages.animation_frames.STAND)
self:set_animation(smart_villages.animation_frames.STAND)
self.object:setvelocity{x = 0, y = velocity.y, z = 0}
end
else
if velocity.x==0 and velocity.y==0 then
self:set_animation(working_villages.animation_frames.WALK)
self:set_animation(smart_villages.animation_frames.WALK)
end
self.object:setvelocity{x = direction.x, y = velocity.y, z = direction.z}
self:set_yaw_by_direction(direction)

View File

@ -1,4 +1,4 @@
function working_villages.func.validate_pos(pos)
function smart_villages.func.validate_pos(pos)
local resultp = vector.round(pos)
local node = minetest.get_node(resultp)
if minetest.registered_nodes[node.name].walkable then
@ -11,33 +11,33 @@ function working_villages.func.validate_pos(pos)
end
end
function working_villages.func.clear_pos(pos)
function smart_villages.func.clear_pos(pos)
local node=minetest.get_node(pos)
local above_node=minetest.get_node({x=pos.x,y=pos.y+1,z=pos.z})
return not(working_villages.pathfinder.walkable(node) or working_villages.pathfinder.walkable(above_node))
return not(smart_villages.pathfinder.walkable(node) or smart_villages.pathfinder.walkable(above_node))
end
function working_villages.func.walkable_pos(pos)
function smart_villages.func.walkable_pos(pos)
local node=minetest.get_node(pos)
return working_villages.pathfinder.walkable(node)
return smart_villages.pathfinder.walkable(node)
end
function working_villages.func.find_adjacent_clear(pos)
local found = working_villages.func.find_adjacent_pos(pos,working_villages.func.clear_pos)
function smart_villages.func.find_adjacent_clear(pos)
local found = smart_villages.func.find_adjacent_pos(pos,smart_villages.func.clear_pos)
if found~=false then
return found
end
found = vector.add(pos,{x=0,y=-2,z=0})
if working_villages.func.clear_pos(found) then
if smart_villages.func.clear_pos(found) then
return found
end
return false
end
local find_adjacent_clear = working_villages.func.find_adjacent_clear
local find_adjacent_clear = smart_villages.func.find_adjacent_clear
function working_villages.func.search_surrounding(pos, pred, searching_range)
function smart_villages.func.search_surrounding(pos, pred, searching_range)
pos = vector.round(pos)
local max_xz = math.max(searching_range.x, searching_range.z)
local mod_y
@ -94,7 +94,7 @@ function working_villages.func.search_surrounding(pos, pred, searching_range)
return nil
end
function working_villages.func.find_adjacent_pos(pos,pred)
function smart_villages.func.find_adjacent_pos(pos,pred)
local dest_pos
if pred(pos) then
return pos

View File

@ -1,19 +1,19 @@
working_villages.func is a table with several functions:
smart_villages.func is a table with several functions:
`function working_villages.func.validate_pos(pos)`
`function smart_villages.func.validate_pos(pos)`
returns the position rounded, if it is a slab/stair the position on top is given
for getting the position of the villager for pathfinding
`function working_villages.func.search_surrounding(pos, pred, searching_range)`
`function smart_villages.func.search_surrounding(pos, pred, searching_range)`
calls `pred(pos)` for every node within searching_range of pos
if `searching_range.h` is given the searching range will start h above pos
if `pred(pos)` returns true it will return the position
if `pred(pos)` doesn't return true at all nil will be returned
`function working_villages.func.get_back_to_searching(self)`
`function smart_villages.func.get_back_to_searching(self)`
makes a villager switch to the SEARCH state which is default for a state_machine_job
`function working_villages.func.find_adjacent_pos(pos,pred)`
`function smart_villages.func.find_adjacent_pos(pos,pred)`
calls `pred(pos)` for every node next to pos and for pos itself
if `pred(pos)` returns true it will return the position
if `pred(pos)` doesn't return true at all false will be returned

View File

@ -3,6 +3,9 @@ local function find_tree(p)
if minetest.get_item_group(adj_node.name, "tree") > 0 then
return true
end
if smart_villages.hasbasic_materials and minetest.get_item_group(adj_node.name, "leaves") > 0 then
return true
end
return false
end
@ -36,8 +39,8 @@ end
local searching_range = {x = 10, y = 10, z = 10, h = 5}
working_villages.register_job("working_villages:job_woodcutter", {
description = "working_villages job : woodcutter",
smart_villages.register_job("smart_villages:job_woodcutter", {
description = "smart_villages job : woodcutter",
inventory_image = "default_paper.png^memorandum_letters.png",
jobfunc = function(self)
if is_night() then
@ -59,12 +62,12 @@ working_villages.register_job("working_villages:job_woodcutter", {
end
local wield_stack = self:get_wield_item_stack()
if is_sapling(wield_stack:get_name()) or self:has_item_in_main(is_sapling) then
local target = working_villages.func.search_surrounding(self.object:getpos(), is_sapling_spot, searching_range)
local target = smart_villages.func.search_surrounding(self.object:getpos(), is_sapling_spot, searching_range)
self:place(is_sapling, target)
end
local target = working_villages.func.search_surrounding(self.object:getpos(), find_tree, searching_range)
local target = smart_villages.func.search_surrounding(self.object:getpos(), find_tree, searching_range)
if target ~= nil then
local destination = working_villages.func.find_adjacent_clear(target)
local destination = smart_villages.func.find_adjacent_clear(target)
if destination==false then
print("failure: no adjacent walkable found")
destination = target
@ -77,4 +80,8 @@ working_villages.register_job("working_villages:job_woodcutter", {
end
end
end,
},{
{"default:book", "default:book", "default:book"},
{"dye:black", "default:stick", "dye:black"},
{"", "dye:black", ""}
})

1
mod.conf Normal file
View File

@ -0,0 +1 @@
name = smart_villages

View File

@ -1,4 +1,4 @@
working_villages.pathfinder = {}
smart_villages.pathfinder = {}
--[[
minetest.get_content_id(name)
@ -96,7 +96,7 @@ local function get_neighbor_ground_level(pos, jump_height, fall_height)
end
end
function working_villages.pathfinder.find_path(pos, endpos, entity)
function smart_villages.pathfinder.find_path(pos, endpos, entity)
--print("searching for a path to:" .. minetest.pos_to_string(endpos))
local start_index = minetest.hash_node_position(pos)
local target_index = minetest.hash_node_position(endpos)
@ -280,18 +280,18 @@ function working_villages.pathfinder.find_path(pos, endpos, entity)
return {endpos}
end
working_villages.pathfinder.walkable = walkable
smart_villages.pathfinder.walkable = walkable
local function get_ground_level(pos)
return get_neighbor_ground_level(pos, 30927, 30927)
end
working_villages.pathfinder.get_ground_level = get_ground_level
smart_villages.pathfinder.get_ground_level = get_ground_level
function working_villages.pathfinder.get_reachable(pos, endpos, entity)
local path = working_villages.pathfinder.find_path(pos, endpos, entity)
function smart_villages.pathfinder.get_reachable(pos, endpos, entity)
local path = smart_villages.pathfinder.find_path(pos, endpos, entity)
if path == nil then
local corr_dest = get_ground_level({x=endpos.x,y=endpos.y-1,z=endpos.z})
path = working_villages.pathfinder.find_path(pos, corr_dest, entity)
path = smart_villages.pathfinder.find_path(pos, corr_dest, entity)
end
return path
end

View File

@ -1,14 +1,14 @@
working_villages.register_villager("working_villages:villager_male", {
smart_villages.register_villager("smart_villages:villager_male", {
hp_max = 30,
weight = 20,
mesh = "character.b3d",
textures = {working_villages.random_texture("villager_male.png")},
textures = {smart_villages.random_texture("villager_male.png")},
egg_image = "villager_male_egg.png",
})
working_villages.register_villager("working_villages:villager_female", {
smart_villages.register_villager("smart_villages:villager_female", {
hp_max = 20,
weight = 20,
mesh = "character.b3d",
textures = {working_villages.random_texture("villager_female.png","character_castaway_female.png","character_farmer_female.png","character_princess.png", "character_rogue_female.png")},
textures = {smart_villages.random_texture("villager_female.png","character_castaway_female.png","character_farmer_female.png","character_princess.png", "character_rogue_female.png")},
egg_image = "villager_female_egg.png",
})