Merge pull request #94 from tacigar/tacigar/farming

[WIP] Add Farming Core.
挙動がところどころ歪だがとりあえずマージ.
あとで Fix 入れる.
This commit is contained in:
tacigar 2016-12-23 12:06:07 +09:00 committed by GitHub
commit a4b0fb42c2
7 changed files with 370 additions and 3 deletions

View File

@ -132,21 +132,34 @@ function maidroid.maidroid.set_yaw_by_direction(self, direction)
self.object:setyaw(math.atan2(direction.z, direction.x) - math.pi / 2)
end
-- maidroid.maidroid.get_wield_item_info returns the maidroid's wield item's stack.
-- maidroid.maidroid.get_wield_item_stack returns the maidroid's wield item's stack.
function maidroid.maidroid.get_wield_item_stack(self)
local inv = self:get_inventory()
return inv:get_stack("wield_item", 1)
end
-- maidroid.maidroid.set_wield_item_stack sets maidroid's wield item stack.
function maidroid.maidroid.set_wield_item_stack(self, stack)
local inv = self:get_inventory()
inv:set_stack("wield_item", 1, stack)
end
-- maidroid.maidroid.add_item_to_main add item to main slot.
-- and returns leftover.
function maidroid.maidroid.add_item_to_main(self, stack)
local inv = self:get_inventory()
return inv:add_item("main", stack)
end
-- maidroid.maidroid.move_main_to_wield moves itemstack from main to wield.
-- if this function fails then returns false, else returns true.
function maidroid.maidroid.move_main_to_wield(self, itemname)
function maidroid.maidroid.move_main_to_wield(self, pred)
local inv = self:get_inventory()
local main_size = inv:get_size("main")
for i = 1, main_size do
local stack = inv:get_stack("main", i)
if stack:get_name() == itemname then
if pred(stack:get_name()) then
local wield_stack = inv:get_stack("wield_item", 1)
inv:set_stack("wield_item", 1, stack)
inv:set_stack("main", i, wield_stack)
@ -161,6 +174,42 @@ function maidroid.maidroid.is_named(self)
return self.nametag ~= ""
end
-- maidroid.maidroid.has_item_in_main reports whether the maidroid has item.
function maidroid.maidroid.has_item_in_main(self, pred)
local inv = self:get_inventory()
local stacks = inv:get_list("main")
for _, stack in ipairs(stacks) do
local itemname = stack:get_name()
if pred(itemname) then
return true
end
end
end
-- maidroid.maidroid.change_direction change direction to destination and velocity vector.
function maidroid.maidroid.change_direction(self, destination)
local position = self.object:getpos()
local direction = vector.subtract(destination, position)
direction.y = 0
local velocity = vector.multiply(vector.normalize(direction), 3)
self.object:setvelocity(velocity)
self:set_yaw_by_direction(direction)
end
-- maidroid.maidroid.change_direction_randomly change direction randonly.
function maidroid.maidroid.change_direction_randomly(self)
local direction = {
x = math.random(0, 5) * 2 - 5,
y = 0,
z = math.random(0, 5) * 2 - 5,
}
local velocity = vector.multiply(vector.normalize(direction), 3)
self.object:setvelocity(velocity)
self:set_yaw_by_direction(direction)
end
---------------------------------------------------------------------
-- maidroid.manufacturing_data represents a table that contains manufacturing data.
@ -545,8 +594,13 @@ function maidroid.register_maidroid(product_name, def)
set_animation = maidroid.maidroid.set_animation,
set_yaw_by_direction = maidroid.maidroid.set_yaw_by_direction,
get_wield_item_stack = maidroid.maidroid.get_wield_item_stack,
set_wield_item_stack = maidroid.maidroid.set_wield_item_stack,
add_item_to_main = maidroid.maidroid.add_item_to_main,
move_main_to_wield = maidroid.maidroid.move_main_to_wield,
is_named = maidroid.maidroid.is_named,
has_item_in_main = maidroid.maidroid.has_item_in_main,
change_direction = maidroid.maidroid.change_direction,
change_direction_randomly = maidroid.maidroid.change_direction_randomly,
})
-- register maidroid egg.

View File

@ -0,0 +1,20 @@
------------------------------------------------------------
-- Copyright (c) 2016 tacigar. All rights reserved.
-- https://github.com/tacigar/maidroid
------------------------------------------------------------
maidroid_core._aux = {}
function maidroid_core._aux.search_surrounding(pos, pred, searching_range)
for x = -searching_range.x, searching_range.x do
for y = -searching_range.y, searching_range.y do
for z = -searching_range.z, searching_range.z do
local p = vector.add(pos, {x = x, y = y, z = z})
if pred(p) then
return p
end
end
end
end
return nil
end

View File

@ -0,0 +1,290 @@
------------------------------------------------------------
-- Copyright (c) 2016 tacigar. All rights reserved.
-- https://github.com/tacigar/maidroid
------------------------------------------------------------
local state = {
WALK_RANDOMLY = 0,
WALK_TO_PLANT = 1,
WALK_TO_MOW = 2,
PLANT = 3,
MOW = 4,
}
local target_plants = {
"farming:cotton_8",
"farming:wheat_8",
}
local _aux = maidroid_core._aux
local FIND_PATH_TIME_INTERVAL = 20
local CHANGE_DIRECTION_TIME_INTERVAL = 30
local MAX_WALK_TIME = 120
-- is_plantable_place reports whether maidroid can plant any seed.
local function is_plantable_place(pos)
local node = minetest.get_node(pos)
local lpos = vector.add(pos, {x = 0, y = -1, z = 0})
local lnode = minetest.get_node(lpos)
return node.name == "air"
and minetest.get_item_group(lnode.name, "wet") > 0
end
-- is_mowable_place reports whether maidroid can mow.
local function is_mowable_place(pos)
local node = minetest.get_node(pos)
for _, plant in ipairs(target_plants) do
if plant == node.name then
return true
end
end
return false
end
local walk_randomly, walk_to_plant_and_mow_common, plant, mow
local to_walk_randomly, to_walk_to_plant, to_walk_to_mow, to_plant, to_mow
local function on_start(self)
self.object:setacceleration{x = 0, y = -10, z = 0}
self.object:setvelocity{x = 0, y = 0, z = 0}
self.state = state.WALK_RANDOMLY
self.time_counters = {}
self.path = nil
to_walk_randomly(self)
end
local function on_stop(self)
self.object:setvelocity{x = 0, y = 0, z = 0}
self.state = nil
self.time_counters = nil
self.path = nil
self:set_animation(maidroid.animation_frames.STAND)
end
local function is_near(self, pos, distance)
local p = self.object:getpos()
-- p.y = p.y + 0.5
return vector.distance(p, pos) < distance
end
local searching_range = {x = 5, y = 2, z = 5}
walk_randomly = function(self, dtime)
if self.time_counters[1] >= FIND_PATH_TIME_INTERVAL then
self.time_counters[1] = 0
self.time_counters[2] = self.time_counters[2] + 1
local wield_stack = self:get_wield_item_stack()
if minetest.get_item_group(wield_stack:get_name(), "seed") > 0
or self:has_item_in_main(function(itemname) return (minetest.get_item_group(itemname, "seed") > 0) end) then
local destination = _aux.search_surrounding(self.object:getpos(), is_plantable_place, searching_range)
if destination ~= nil then
local path = minetest.find_path(self.object:getpos(), destination, 10, 1, 1, "A*")
if path ~= nil then -- to walk to plant state.
to_walk_to_plant(self, path, destination)
return
end
end
end
-- if couldn't find path to plant, try to mow.
local destination = _aux.search_surrounding(self.object:getpos(), is_mowable_place, searching_range)
if destination ~= nil then
local path = minetest.find_path(self.object:getpos(), destination, 10, 1, 1, "A*")
if path ~= nil then -- to walk to mow state.
to_walk_to_mow(self, path, destination)
return
end
end
-- else do nothing.
return
elseif self.time_counters[2] >= CHANGE_DIRECTION_TIME_INTERVAL then
self.time_counters[1] = self.time_counters[1] + 1
self.time_counters[2] = 0
self:change_direction_randomly()
return
else
self.time_counters[1] = self.time_counters[1] + 1
self.time_counters[2] = self.time_counters[2] + 1
local velocity = self.object:getvelocity()
if velocity.y == 0 then
local front_node = self:get_front_node()
if front_node.name ~= "air" and minetest.registered_nodes[front_node.name].walkable
and not (minetest.get_item_group(front_node.name, "fence") > 0) then
self.object:setvelocity{x = velocity.x, y = 6, z = velocity.z}
end
end
return
end
end
to_walk_randomly = function(self)
self.state = state.WALK_RANDOMLY
self.time_counters[1] = 0
self.time_counters[2] = 0
self:change_direction_randomly()
self:set_animation(maidroid.animation_frames.WALK)
end
to_walk_to_plant = function(self, path, destination)
self.state = state.WALK_TO_PLANT
self.path = path
self.destination = destination
self.time_counters[1] = 0 -- find path interval
self.time_counters[2] = 0
self:change_direction(self.path[1])
self:set_animation(maidroid.animation_frames.WALK)
end
to_walk_to_mow = function(self, path, destination)
self.state = state.WALK_TO_MOW
self.path = path
self.destination = destination
self.time_counters[1] = 0 -- find path interval
self.time_counters[2] = 0
self:change_direction(self.path[1])
self:set_animation(maidroid.animation_frames.WALK)
end
to_plant = function(self)
local wield_stack = self:get_wield_item_stack()
if minetest.get_item_group(wield_stack:get_name(), "seed") > 0
or self:move_main_to_wield(function(itemname) return (minetest.get_item_group(itemname, "seed") > 0) end) then
self.state = state.PLANT
self.time_counters[1] = 0
self.object:setvelocity{x = 0, y = 0, z = 0}
self:set_animation(maidroid.animation_frames.MINE)
return
else
to_walk_randomly(self)
return
end
end
to_mow = function(self)
self.state = state.MOW
self.time_counters[1] = 0
self.object:setvelocity{x = 0, y = 0, z = 0}
self:set_animation(maidroid.animation_frames.MINE)
end
walk_to_plant_and_mow_common = function(self, dtime)
if is_near(self, self.destination, 1.5) then
if self.state == state.WALK_TO_PLANT then
to_plant(self)
return
elseif self.state == state.WALK_TO_MOW then
to_mow(self)
return
end
end
if self.time_counters[2] >= MAX_WALK_TIME then -- time over.
to_walk_randomly(self)
return
end
self.time_counters[1] = self.time_counters[1] + 1
self.time_counters[2] = self.time_counters[2] + 1
if self.time_counters[1] >= FIND_PATH_TIME_INTERVAL then
self.time_counters[1] = 0
local path = minetest.find_path(self.object:getpos(), self.destination, 10, 1, 1, "A*")
if path == nil then
to_walk_randomly(self)
return
end
self.path = path
end
-- follow path
if is_near(self, self.path[1], 0.5) then
table.remove(self.path, 1)
if #self.path == 0 then -- end of path
if self.state == state.WALK_TO_PLANT then
to_plant(self)
return
elseif self.state == state.WALK_TO_MOW then
to_mow(self)
return
end
else -- else next step, follow next path.
self:change_direction(self.path[1])
end
else
-- self:change_direction(self.path[1])
-- if maidroid is stopped by obstacles, the maidroid must jump.
-- self:change_direction(self.path[1])
local velocity = self.object:getvelocity()
if velocity.y == 0 then
local front_node = self:get_front_node()
if front_node.name ~= "air" and minetest.registered_nodes[front_node.name].walkable
and not (minetest.get_item_group(front_node.name, "fence") > 0) then
self.object:setvelocity{x = velocity.x, y = 6, z = velocity.z}
end
end
end
end
plant = function(self, dtime)
if self.time_counters[1] >= 15 then
if is_plantable_place(self.destination) then
local stack = self:get_wield_item_stack()
local itemname = stack:get_name()
minetest.add_node(self.destination, {name = itemname, param2 = 1})
stack:take_item(1)
self:set_wield_item_stack(stack)
end
to_walk_randomly(self)
return
else
self.time_counters[1] = self.time_counters[1] + 1
end
end
mow = function(self, dtime)
if self.time_counters[1] >= 15 then
if is_mowable_place(self.destination) then
local destnode = minetest.get_node(self.destination)
minetest.remove_node(self.destination)
local stacks = minetest.get_node_drops(destnode.name)
for _, stack in ipairs(stacks) do
local leftover = self:add_item_to_main(stack)
minetest.add_item(self.destination, leftover)
end
end
to_walk_randomly(self)
return
else
self.time_counters[1] = self.time_counters[1] + 1
end
end
local function on_step(self, dtime)
if self.state == state.WALK_RANDOMLY then
walk_randomly(self, dtime)
elseif self.state == state.WALK_TO_PLANT or self.state == state.WALK_TO_MOW then
walk_to_plant_and_mow_common(self, dtime)
elseif self.state == state.PLANT then
plant(self, dtime)
elseif self.state == state.MOW then
mow(self, dtime)
end
end
maidroid.register_core("maidroid_core:farming", {
description = "maidroid core : farming",
inventory_image = "maidroid_core_farming.png",
on_start = on_start,
on_stop = on_stop,
on_resume = on_start,
on_pause = on_stop,
on_step = on_step,
})

View File

@ -8,5 +8,7 @@ maidroid_core = {}
maidroid_core.modname = "maidroid_core"
maidroid_core.modpath = minetest.get_modpath(maidroid_core.modname)
dofile(maidroid_core.modpath .. "/cores/_aux.lua")
dofile(maidroid_core.modpath .. "/cores/empty.lua")
dofile(maidroid_core.modpath .. "/cores/basic.lua")
dofile(maidroid_core.modpath .. "/cores/farming.lua")

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 B

Binary file not shown.

View File

@ -7,6 +7,7 @@ do -- register core writer
local dye_item_map = {
["dye:red"] = "maidroid_core:basic",
["dye:green"] = "maidroid_core:farming",
}
local node_box = {