Initial commit

master
rubenwardy 2018-02-11 20:30:26 +00:00
commit 570f2d2f4a
9 changed files with 359 additions and 0 deletions

111
.gitignore vendored Normal file
View File

@ -0,0 +1,111 @@
# Created by https://www.gitignore.io/api/lua,linux,macos,windows
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### Lua ###
# Compiled Lua sources
luac.out
# luarocks build files
*.src.rock
*.zip
*.tar.gz
# Object files
*.o
*.os
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
*.def
*.exp
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
### macOS ###
*.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Windows ###
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
# End of https://www.gitignore.io/api/lua,linux,macos,windows

15
.luacheckrc Normal file
View File

@ -0,0 +1,15 @@
unused_args = false
allow_defined_top = true
read_globals = {
"minetest",
string = {fields = {"split"}},
table = {fields = {"copy", "getn"}},
"vector", "default",
"ItemStack",
"crafting",
-- Testing
"describe",
"it",
}

71
api.lua Normal file
View File

@ -0,0 +1,71 @@
crafting = {
recipes = {}
}
function crafting.register_type(name)
crafting.recipes[name] = {}
end
function crafting.register_recipe(def)
assert(def.output, "Output needed in recipe definition")
assert(def.type, "Type needed in recipe definition")
assert(def.items, "Items needed in recipe definition")
local tab = crafting.recipes[def.type]
assert(tab, "Unknown craft type " .. def.type)
tab[#tab + 1] = def
end
function crafting.get_all(type, item_hash, unlocked)
assert(crafting.recipes[type], "No such craft type!")
local ret_craftable = {}
local ret_uncraftable = {}
for _, recipe in pairs(crafting.recipes[type]) do
local craftable = true
if recipe.always_known or unlocked[recipe.output] then
-- Check all ingredients are available
for _, item in pairs(recipe.items) do
item = ItemStack(item)
local available_count = item_hash[item:get_name()]
if not available_count or available_count < item:get_count() then
craftable = false
break
end
end
if craftable then
ret_craftable[#ret_craftable + 1] = recipe
else
ret_uncraftable[#ret_uncraftable + 1] = recipe
end
end
end
return ret_craftable, ret_uncraftable
end
function crafting.get_all_for_player(player, type)
local unlocked = {} -- TODO
-- Get items hashed
local item_hash = {}
local inv = player:get_inventory()
for _, stack in pairs(inv:get_list("main")) do
local itemname = stack:get_count()
item_hash[itemname] = (item_hash[itemname] or 0) + 1
local def = minetest.registered_items[itemname]
if def.groups then
for _, group in pairs(def.groups) do
local groupname = "group:" .. group
item_hash[groupname] = (item_hash[groupname] or 0) + 1
end
end
end
return crafting.get_all(type, item_hash, unlocked)
end

2
init.lua Normal file
View File

@ -0,0 +1,2 @@
dofile(minetest.get_modpath("crafting") .. "/api.lua")
dofile(minetest.get_modpath("crafting") .. "/recipes.lua")

8
recipes.lua Normal file
View File

@ -0,0 +1,8 @@
crafting.register_type("inv")
crafting.register_recipe({
type = "inv",
output = "default:torch",
items = { "default:stick", "default:coal" },
always_known = true,
})

76
tests/api_spec.lua Normal file
View File

@ -0,0 +1,76 @@
package.path = '../../?.lua;' .. -- tests root
'../?.lua;' .. -- mod root
package.path
require("crafting/tests/dummy")
require("crafting/api")
local crafting = _G.crafting -- Suppress mutating global warning
local recipe1 = {
type = "test",
output = "default:torch",
items = { "default:stick", "default:coal" },
always_known = true,
}
local recipe2 = {
type = "test",
output = "default:stone",
items = { "default:cobble" },
always_known = true,
}
describe("Recipes and types", function()
crafting.recipes = {}
it("can register type", function()
assert.is_nil(crafting.recipes["test"])
crafting.register_type("test")
assert.is_not_nil(crafting.recipes["test"])
end)
it("can register type", function()
assert(not crafting.recipes["test"][1])
crafting.register_recipe(recipe1)
assert.is_not_nil(crafting.recipes["test"][1])
assert.equals(crafting.recipes["test"][1].output, recipe1.output)
end)
end)
describe("Getting all outputs", function()
crafting.recipes = {}
crafting.register_type("test")
-- Recipe 1
crafting.register_recipe(recipe1)
assert.equals(#crafting.recipes["test"], 1)
assert.equals(crafting.recipes["test"][1].output, recipe1.output)
-- Recipe 2
crafting.register_recipe(recipe2)
assert.equals(#crafting.recipes["test"], 2)
assert.equals(crafting.recipes["test"][1].output, recipe1.output)
assert.equals(crafting.recipes["test"][2].output, recipe2.output)
it("get with no items", function()
local craftable, uncraftable = crafting.get_all("test", {}, {})
assert.equals(0, #craftable)
assert.equals(2, #uncraftable)
assert.equals(recipe1, uncraftable[1])
assert.equals(recipe2, uncraftable[2])
end)
it("get with right for one", function()
local items_hash = {}
items_hash["default:cobble"] = 1
local craftable, uncraftable = crafting.get_all("test", items_hash, {})
assert.equals(1, #craftable)
assert.equals(1, #uncraftable)
assert.equals(recipe2, craftable[1])
assert.equals(recipe1, uncraftable[1])
end)
end)

25
tests/dummy.lua Normal file
View File

@ -0,0 +1,25 @@
function ItemStack(obj)
local name, count
if obj.get_count then
name = obj:get_name()
count = obj:get_count()
else
name, count = string.match(obj, "^([A-Za-z0-9:]+) ([0-9]+)$")
if not name then
name = obj
end
count = tonumber(count or 1)
end
return {
get_name = function(self)
return name
end,
get_count = function(self)
return count
end,
set_count = function(self, v)
count = v
end,
}
end

34
tests/dummy_spec.lua Normal file
View File

@ -0,0 +1,34 @@
package.path = '../../?.lua;' .. -- tests root
'../?.lua;' .. -- mod root
package.path
require("crafting/tests/dummy")
describe("ItemStack", function()
it("parses simple", function()
local stack = ItemStack("default:stone")
assert.equals("default:stone", stack:get_name())
assert.equals(1, stack:get_count())
end)
it("parses dual string", function()
local stack = ItemStack("default:stone 11")
assert.equals("default:stone", stack:get_name())
assert.equals(11, stack:get_count())
end)
it("copies", function()
local stack1 = ItemStack("default:stone 11")
local stack2 = ItemStack(stack1)
assert.not_equals(stack1, stack2)
assert.is_true(stack1:get_name() == stack2:get_name())
assert.is_true(stack1:get_count() == stack2:get_count())
stack2:set_count(3)
assert.equals(11, stack1:get_count())
assert.equals(3, stack2:get_count())
assert.is_true(stack1:get_count() ~= stack2:get_count())
end)
end)

17
tests/recipes_spec.lua Normal file
View File

@ -0,0 +1,17 @@
package.path = '../../?.lua;' .. -- tests root
'../?.lua;' .. -- mod root
package.path
require("crafting/api")
require("crafting/recipes")
describe("Inv Crafttype", function()
it("exists", function()
assert.is_not_nil(crafting.recipes["inv"])
end)
it("has torch recipe", function()
assert.equals("default:torch", crafting.recipes["inv"][1].output)
end)
end)