Refactor datapack code
parent
67dd48b06c
commit
0de53a9dcb
|
@ -0,0 +1,45 @@
|
||||||
|
local Object = {}
|
||||||
|
|
||||||
|
function Object:__define_getter(name, cached, get, cmp)
|
||||||
|
local key = "_" .. name
|
||||||
|
self[name] = function (self, expected)
|
||||||
|
local value
|
||||||
|
|
||||||
|
if cached then
|
||||||
|
value = self[key]
|
||||||
|
end
|
||||||
|
|
||||||
|
if not value then
|
||||||
|
value = get(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
if cached then
|
||||||
|
self[key] = value
|
||||||
|
end
|
||||||
|
|
||||||
|
if expected ~= nil then
|
||||||
|
if cmp then
|
||||||
|
return cmp(value, expected)
|
||||||
|
else
|
||||||
|
return value == expected
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function class(super)
|
||||||
|
return setmetatable({}, {
|
||||||
|
__call = function(_class, ...)
|
||||||
|
local instance = setmetatable({}, {
|
||||||
|
__index = _class,
|
||||||
|
})
|
||||||
|
if instance.constructor then
|
||||||
|
instance:constructor(...)
|
||||||
|
end
|
||||||
|
return instance
|
||||||
|
end,
|
||||||
|
__index = super or Object,
|
||||||
|
})
|
||||||
|
end
|
|
@ -0,0 +1,3 @@
|
||||||
|
name = class
|
||||||
|
author = Fleckenstein
|
||||||
|
description = A class system for MineClone2
|
|
@ -1,27 +0,0 @@
|
||||||
mcl_numbers.register_provider = mcl_util.registration_function(mcl_numbers.providers)
|
|
||||||
|
|
||||||
function mcl_numbers.get_number(provider, data)
|
|
||||||
return mcl_util.switch_type(provider, {
|
|
||||||
["number"] = function()
|
|
||||||
return provider
|
|
||||||
end,
|
|
||||||
["table"] = function()
|
|
||||||
local func = mcl_numbers.providers[data.type]
|
|
||||||
return func(provider, data)
|
|
||||||
end,
|
|
||||||
}, "number provider")
|
|
||||||
end
|
|
||||||
|
|
||||||
function mcl_numbers.check_bounds(actual, expected, data)
|
|
||||||
return mcl_util.switch_type(actual, {
|
|
||||||
["nil"] = function()
|
|
||||||
return true
|
|
||||||
end,
|
|
||||||
["number"] = function()
|
|
||||||
return actual == expected
|
|
||||||
end,
|
|
||||||
["table"] = function()
|
|
||||||
return actual <= mcl_numbers.get_number(expected.max, data) and actual >= mcl_numbers.get_number(expected.min, data)
|
|
||||||
end,
|
|
||||||
}, "range")
|
|
||||||
end
|
|
|
@ -1,84 +0,0 @@
|
||||||
mcl_predicates.register_predicate = mcl_util.registration_function(mcl_predicates.predicates)
|
|
||||||
|
|
||||||
function mcl_predicates.get_predicate(id)
|
|
||||||
return mcl_util.switch_type(id, {
|
|
||||||
["function"] = function(v)
|
|
||||||
return v,
|
|
||||||
end,
|
|
||||||
["string"] = function(v)
|
|
||||||
return mcl_predicates.predicates[v]
|
|
||||||
end,
|
|
||||||
}, "predicate")
|
|
||||||
end
|
|
||||||
|
|
||||||
function mcl_predicates.do_predicates(predicates, data, or_mode)
|
|
||||||
or_mode = or_mode or false
|
|
||||||
for _, def in ipairs() do
|
|
||||||
local func = mcl_predicates.get_predicate(def.condition)
|
|
||||||
local failure = func and not func(def, data) or false
|
|
||||||
if or_mode ~= failure then
|
|
||||||
return or_mode
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return not or_mode or #predicates == 0
|
|
||||||
end
|
|
||||||
|
|
||||||
function mcl_predicates.match_block(location, block, properties)
|
|
||||||
local node = minetest.get_node(location)
|
|
||||||
if node.name ~= block then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
if properties then
|
|
||||||
local meta = minetest.get_meta(location)
|
|
||||||
for k, v in pairs(properties) do
|
|
||||||
if meta:get_string(k) ~= v then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function mcl_predicates.match_tool(itemstack, predicate)
|
|
||||||
itemstack = itemstack or ItemStack()
|
|
||||||
|
|
||||||
local itemname = itemstack:get_name()
|
|
||||||
|
|
||||||
local expected_name = predicate.item
|
|
||||||
|
|
||||||
if expected_name and itemname ~= expected_name then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local tag = predicate.tag
|
|
||||||
|
|
||||||
if tag and minetest.get_item_group(itemname, predicate) == 0 then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
if not mcl_numbers.check_bounds(itemstack:get_count(), predicate.count, data) then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ToDo: Durability, needs research, needs abstraction ?
|
|
||||||
-- ToDo: potions, "nbt" aka metadata
|
|
||||||
|
|
||||||
local enchantments, stored_enchantments = predicate.enchantments, predicate.stored_enchantments
|
|
||||||
|
|
||||||
if enchantments and stored_enchantments then
|
|
||||||
enchantments = table.copy(enchantments)
|
|
||||||
table.insert_all(enchantments, stored_enchantments)
|
|
||||||
elseif stored_enchantments then
|
|
||||||
enchantments = stored_enchantments
|
|
||||||
end
|
|
||||||
if enchantments then
|
|
||||||
local actual_enchantments = mcl_enchanting.get_enchantments(itemstack)
|
|
||||||
for _, def in ipairs(actual_enchantments) do
|
|
||||||
local level = actual_enchantments[def.enchantment]
|
|
||||||
if not mcl_numbers.check_bounds(level, def.levels or {min = 1, max = math.huge}, data) then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,4 +0,0 @@
|
||||||
name = mcl_predicates
|
|
||||||
author = Fleckenstein
|
|
||||||
description = Provides MC-like predicates
|
|
||||||
depends = mcl_util, mcl_number
|
|
|
@ -9,21 +9,6 @@ mcl_loottables.register_table = mcl_util.registration_function(mcl_loottables.ta
|
||||||
set_parents(def)
|
set_parents(def)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
function mcl_loottables.get_table(def)
|
|
||||||
return mcl_util.switch_type(def, {
|
|
||||||
["nil"] = function()
|
|
||||||
return {}
|
|
||||||
end,
|
|
||||||
["string"] = function()
|
|
||||||
return mcl_loottables.tables[def], "table"
|
|
||||||
end,
|
|
||||||
["table"] = function()
|
|
||||||
return def
|
|
||||||
end,
|
|
||||||
}, "loot table")
|
|
||||||
end
|
|
||||||
|
|
||||||
function mcl_loottables.get_entry_type(entry)
|
function mcl_loottables.get_entry_type(entry)
|
||||||
return mcl_loottables.entries[entry.type]
|
return mcl_loottables.entries[entry.type]
|
||||||
end
|
end
|
||||||
|
@ -32,7 +17,7 @@ function mcl_loottables.get_candidates(entries, data, func)
|
||||||
local candidates = {}
|
local candidates = {}
|
||||||
for _, entry in ipairs(entries) do
|
for _, entry in ipairs(entries) do
|
||||||
local success = mcl_predicates.do_predicates(entry.conditions, data)
|
local success = mcl_predicates.do_predicates(entry.conditions, data)
|
||||||
|
|
||||||
if success then
|
if success then
|
||||||
local children = entry.children
|
local children = entry.children
|
||||||
|
|
||||||
|
@ -52,7 +37,7 @@ end
|
||||||
|
|
||||||
function mcl_loottables.do_item_modifiers(itemstack, node, data)
|
function mcl_loottables.do_item_modifiers(itemstack, node, data)
|
||||||
if node then
|
if node then
|
||||||
mcl_functions.do_item_modifiers(itemstack, node.functions, data)
|
mcl_item_modifiers.do_item_modifiers(itemstack, node.functions, data)
|
||||||
mcl_loottables.do_item_modifiers(itemstack, node.parent, data)
|
mcl_loottables.do_item_modifiers(itemstack, node.parent, data)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -61,8 +46,8 @@ function mcl_loottables.do_pools(pools, functions, data)
|
||||||
local luck = data.luck or 0
|
local luck = data.luck or 0
|
||||||
local stacks = {}
|
local stacks = {}
|
||||||
for _, pool in ipairs(pools or {}) do
|
for _, pool in ipairs(pools or {}) do
|
||||||
if mcl_conditions.do_conditions(pool.conditions, data) do
|
if mcl_predicates.do_predicates(pool.conditions, data) do
|
||||||
local rolls = mcl_loottables.get_number(pool.rolls, data) + mcl_loottables.get_number(pool.bonus_rolls, data) * luck
|
local rolls = mcl_numbers.get_number(pool.rolls, data) + mcl_numbers.get_number(pool.bonus_rolls, data) * luck
|
||||||
for i = 1, rolls do
|
for i = 1, rolls do
|
||||||
local candidates = mcl_loottables.get_candidates(pool.entries, data)
|
local candidates = mcl_loottables.get_candidates(pool.entries, data)
|
||||||
|
|
||||||
|
@ -73,7 +58,7 @@ function mcl_loottables.do_pools(pools, functions, data)
|
||||||
total_weight = total_weight + math.floor((candidate.weight or 1) + (candidate.quality or 0) * luck)
|
total_weight = total_weight + math.floor((candidate.weight or 1) + (candidate.quality or 0) * luck)
|
||||||
table.insert(weights, total_weight)
|
table.insert(weights, total_weight)
|
||||||
end
|
end
|
||||||
|
|
||||||
local selected
|
local selected
|
||||||
local rnd = mcl_util.rand(data.pr, 0, weight - 1)
|
local rnd = mcl_util.rand(data.pr, 0, weight - 1)
|
||||||
for i, w in ipairs(weights) do
|
for i, w in ipairs(weights) do
|
||||||
|
@ -82,14 +67,13 @@ function mcl_loottables.do_pools(pools, functions, data)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local func = mcl_loottables.get_entry_type(entry).process
|
|
||||||
local stacks = func(selected, data)
|
|
||||||
|
|
||||||
for _, stack in ipairs(stacks) do
|
local pool_stacks = mcl_loottables.get_entry_type(entry).process(selected, data)
|
||||||
|
|
||||||
|
for _, stack in ipairs(pool_stacks) do
|
||||||
mcl_item_modifiers.do_item_modifiers(stack, selected, data)
|
mcl_item_modifiers.do_item_modifiers(stack, selected, data)
|
||||||
end
|
end
|
||||||
table.insert_all(stacks, stack)
|
table.insert_all(stacks, pool_stacks)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -98,7 +82,9 @@ function mcl_loottables.do_pools(pools, functions, data)
|
||||||
end
|
end
|
||||||
|
|
||||||
function mcl_loottables.get_loot(def, data)
|
function mcl_loottables.get_loot(def, data)
|
||||||
def = mcl_loottables.get_table(def)
|
if type(def) == "string" then
|
||||||
|
def = mcl_loottables.tables[def]
|
||||||
|
end
|
||||||
return mcl_loottables.do_pools(def.pools)
|
return mcl_loottables.do_pools(def.pools)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -113,7 +99,3 @@ function mcl_loottables.drop_loot(def, data)
|
||||||
end
|
end
|
||||||
return loot
|
return loot
|
||||||
end
|
end
|
||||||
|
|
||||||
function mcl_loottables.fill_chest(def, data)
|
|
||||||
local loot = mcl_loottables.get_loot(def, data)
|
|
||||||
end
|
|
|
@ -1,4 +1,4 @@
|
||||||
name = mcl_loot
|
name = mcl_loot
|
||||||
author = Fleckenstein
|
author = Fleckenstein
|
||||||
description = Provides Minecraft-like loot table definitions
|
description = Provides Minecraft-like loot table definitions
|
||||||
depends = mcl_util, mcl_predicates, mcl_item_modifiers
|
depends = mcl_util, mcl_predicates, mcl_item_modifiers, mcl_groupcache
|
|
@ -0,0 +1,19 @@
|
||||||
|
mcl_numbers.register_provider = mcl_util.registration_function(mcl_numbers.providers)
|
||||||
|
|
||||||
|
function mcl_numbers.get_number(provider, data)
|
||||||
|
if type(provider) == "number" then
|
||||||
|
return provider
|
||||||
|
else
|
||||||
|
mcl_numbers.providers[data.type](provider, data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_numbers.match_bounds(actual, expected, data)
|
||||||
|
if type(expected) == "table" then
|
||||||
|
expected = {
|
||||||
|
min = mcl_numbers.get_number(expected.min, data),
|
||||||
|
max = mcl_numbers.get_number(expected.max, data)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
return mcl_util.match_bounds(actual, expected)
|
||||||
|
end
|
|
@ -0,0 +1,15 @@
|
||||||
|
mcl_predicates.register_predicate = mcl_util.registration_function(mcl_predicates.predicates)
|
||||||
|
|
||||||
|
function mcl_predicates.do_predicates(predicates, data, or_mode)
|
||||||
|
or_mode = or_mode or false
|
||||||
|
for _, func in ipairs(predicates) do
|
||||||
|
if type(func) == "string" then
|
||||||
|
func = mcl_predicates.predicates[func]
|
||||||
|
end
|
||||||
|
local failure = func and not func(def, data) or false
|
||||||
|
if or_mode ~= failure then
|
||||||
|
return or_mode
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return not or_mode or #predicates == 0
|
||||||
|
end
|
|
@ -10,8 +10,8 @@ mcl_predicates.register_predicate("alternative", function(predicate, data)
|
||||||
return mcl_predicates.do_predicates(predicate.terms, data, true)
|
return mcl_predicates.do_predicates(predicate.terms, data, true)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
mcl_predicates.register_predicate("block_state_property", function(predicate, data)
|
mcl_predicates.register_predicate("match_node", function(predicate, data)
|
||||||
return mcl_predicates.match_block(predicate.block, predicate.properties, data.location)
|
return mcl_types.match_node(data.node or minetest.get_node(data.pos), predicate, data.pos, data.nodemeta)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
mcl_predicates.register_predicate("damage_source_properties", function(predicate, data)
|
mcl_predicates.register_predicate("damage_source_properties", function(predicate, data)
|
||||||
|
@ -24,7 +24,7 @@ mcl_predicates.register_predicate("entity_properties", function(predicate, data)
|
||||||
if not entity or (entity ~= "this" and entity ~= "killer" and entity ~= "killer_player") then
|
if not entity or (entity ~= "this" and entity ~= "killer" and entity ~= "killer_player") then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
local ref = data[entity]
|
local ref = data[entity]
|
||||||
if not ref then
|
if not ref then
|
||||||
return false
|
return false
|
||||||
|
@ -48,14 +48,8 @@ mcl_predicates.register_predicate("killed_by_player", function(predicate, data)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
mcl_predicates.register_predicate("location_check", function(predicate, data)
|
mcl_predicates.register_predicate("location_check", function(predicate, data)
|
||||||
local location = vector.new(data.location)
|
local pos = vector.add(data.pos), vector.new(predicate.offset_x or 0, predicate.offset_y or 0, predicate.offset_z or 0))
|
||||||
|
return mcl_location(pos, data.nodemeta):match(predicate.predicate)
|
||||||
location.x = location.x + (data.offsetX or 0)
|
|
||||||
location.y = location.y + (data.offsetY or 0)
|
|
||||||
location.z = location.z + (data.offsetZ or 0)
|
|
||||||
|
|
||||||
-- ToDo, needs abstraction?
|
|
||||||
return nil
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
mcl_predicates.register_predicate("match_tool", function(predicate, data)
|
mcl_predicates.register_predicate("match_tool", function(predicate, data)
|
||||||
|
@ -94,7 +88,7 @@ end)
|
||||||
|
|
||||||
mcl_predicates.register_predicate("weather_check", function(predicate, data)
|
mcl_predicates.register_predicate("weather_check", function(predicate, data)
|
||||||
local weather = mcl_weather.get_weather()
|
local weather = mcl_weather.get_weather()
|
||||||
|
|
||||||
if predicate.thundering then
|
if predicate.thundering then
|
||||||
return weather == "thunder"
|
return weather == "thunder"
|
||||||
elseif predicate.raining then
|
elseif predicate.raining then
|
|
@ -0,0 +1,4 @@
|
||||||
|
name = mcl_predicates
|
||||||
|
author = Fleckenstein
|
||||||
|
description = Provides MC-like predicates
|
||||||
|
depends = mcl_util, mcl_numbers
|
|
@ -0,0 +1,88 @@
|
||||||
|
mcl_types = {}
|
||||||
|
|
||||||
|
function mcl_types.match_bounds(actual, expected)
|
||||||
|
if type(expected) == "table" then
|
||||||
|
return actual <= expected.max and actual >= expected.min
|
||||||
|
else
|
||||||
|
return actual == expected
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_types.match_meta(actual, expected)
|
||||||
|
for k, v in pairs(expected) do
|
||||||
|
if actual:get_string(k) ~= v then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_types.match_vector(actual, expected)
|
||||||
|
for k, v in pairs(expected) do
|
||||||
|
if not mcl_types.match_bounds(actual[k], expected[k]) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_types.match_enchantments(actual, expected)
|
||||||
|
for _, v in ipairs(expected) do
|
||||||
|
if not mcl_types.match_bounds(actual[v.enchantment] or 0, v.levels or {min = 1, max = math.huge}) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_util.match_item(actual, expected)
|
||||||
|
actual = actual or ItemStack()
|
||||||
|
|
||||||
|
if expected.item and actual:get_name() ~= expected.item then
|
||||||
|
return false
|
||||||
|
elseif expected.group and minetest.get_item_group(actual:get_name(), expected.group) == 0 then
|
||||||
|
return false
|
||||||
|
elseif expected.count and not mcl_types.match_bounds(actual:get_count(), expected.count) then
|
||||||
|
return false
|
||||||
|
elseif expected.wear and not mcl_types.match_bounds(actual:get_wear(), expected.wear) then
|
||||||
|
return false
|
||||||
|
elseif expected.enchantments and not mcl_types.match_enchantments(mcl_enchanting.get_enchantments(actual), expected.enchantments) then
|
||||||
|
return false
|
||||||
|
elseif expected.meta and not mcl_types.match_meta(actual:get_meta(), expected.meta) then
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_util.match_node(actual, expected, pos, meta)
|
||||||
|
if expected.node and actual.name ~= expected.node then
|
||||||
|
return false
|
||||||
|
elseif expected.group and minetest.get_item_group(actual.name, expected.group) == 0 then
|
||||||
|
return false
|
||||||
|
elseif expected.param1 and actual.param1 ~= compare.param1 then
|
||||||
|
return false
|
||||||
|
elseif expected.param2 and actual.param2 ~= compare.param2 then
|
||||||
|
return false
|
||||||
|
elseif expected.meta and not mcl_types.match_meta(meta or minetest.get_meta(pos), expected.meta) then
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_types.match_pos(actual, expected, meta)
|
||||||
|
if expected.pos and not mcl_types.match_vector(actual, expected.pos) then
|
||||||
|
return false
|
||||||
|
elseif expected.dimension and mcl_worlds.pos_to_dimension(actual) ~= expected.dimension then
|
||||||
|
return false
|
||||||
|
elseif expected.biome and minetest.get_biome_name(minetest.get_biome_data(actual).biome) ~= expected.biome then
|
||||||
|
return false
|
||||||
|
elseif expected.node and not mcl_types.match_node(minetest.get_node(actual), expected.node, actual, meta)
|
||||||
|
return false
|
||||||
|
elseif expected.light and not mcl_types.match_bounds(minetest.get_node_light(actual), expected.light) then
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,3 @@
|
||||||
|
name = mcl_types
|
||||||
|
author = Fleckenstein
|
||||||
|
description = Offers compare functions for many types, used for MineClone2 datapacks
|
|
@ -0,0 +1,2 @@
|
||||||
|
name = DATA
|
||||||
|
description = Meta-modpack containing the datapack system for MineClone 2
|
Loading…
Reference in New Issue