master
Auri 2021-12-21 15:58:20 -08:00
parent 33f1750a24
commit 523589897f
19 changed files with 237 additions and 139 deletions

View File

@ -1,4 +1,5 @@
time_speed = 0
active_block_range = 16
max_forceloaded_blocks = 10000
recent_chat_messages = 0
active_object_send_range_blocks = 8

View File

@ -202,7 +202,8 @@ for _, type in ipairs({ 'horizontal_start', 'horizontal_mid', 'horizontal_end',
groups = {
dig_game = 1,
conveyor = type:match('vertical') and 2 or 1,
not_in_creative_inventory = type ~= 'mono' and 1 or 0
not_in_creative_inventory = type ~= 'mono' and 1 or 0,
enemy_target = 70
},
_conveyor_function = conveyor_functions[type] or conveyor_functions.horizontal,
drop = '',

View File

@ -25,6 +25,7 @@ minetest.register_node('lexa_conveyor:distributor', {
groups = {
conveyor = 3,
dig_game = 1,
enemy_target = 70
},
_conveyor_function = function(node_pos, item, delta)
local node = minetest.get_node(node_pos)

View File

@ -24,6 +24,7 @@ minetest.register_node('lexa_conveyor:junction', {
groups = {
conveyor = 3,
dig_game = 1,
enemy_target = 70
},
_conveyor_function = function(node_pos, item, delta)
local obj_pos = item.object:get_pos()

View File

@ -13,26 +13,26 @@ minetest.register_entity('lexa_enemy:spider', {
self.object:remove()
end,
on_step = function(self, dtime, collision)
if not self.path then
if not navigation.graph then return end
-- if not self.path then
-- if not navigation.graph then return end
local start = minetest.get_us_time()
self.path = navigation.find_path(
navigation.graph, vector.round(self.object:get_pos()), navigation.graph.player_spawn)
minetest.chat_send_all('Pathfinding took ' .. (minetest.get_us_time() - start) / 1000)
-- local start = minetest.get_us_time()
-- self.path = navigation.find_path(
-- navigation.graph, vector.round(self.object:get_pos()), navigation.graph.player_spawn)
-- minetest.chat_send_all('Pathfinding took ' .. (minetest.get_us_time() - start) / 1000)
if not self.path then return end
self.path_index = #self.path - 1
-- if not self.path then return end
-- self.path_index = #self.path - 1
for _, node in ipairs(self.path) do
minetest.add_particle({
pos = node,
size = 16,
expirationtime = 3,
texture = 'navigation_indicator.png'
})
end
end
-- for _, node in ipairs(self.path) do
-- minetest.add_particle({
-- pos = node,
-- size = 16,
-- expirationtime = 3,
-- texture = 'navigation_indicator.png'
-- })
-- end
-- end
local pos_2d = self.object:get_pos()
pos_2d.y = 0

View File

@ -14,8 +14,35 @@ minetest.register_entity('lexa_factory:drill_entity', {
end
})
local function get_ores(pos)
local count = { copper = 0, titanium = 0, cobalt = 0 }
for _, pos in ipairs({
vector.add(pos, vector.new(0, -1, 0)),
vector.add(pos, vector.new(1, -1, 0)),
vector.add(pos, vector.new(0, -1, 1)),
vector.add(pos, vector.new(1, -1, 1))
}) do
local node = minetest.get_node(pos)
local def = minetest.registered_nodes[node.name]
if def and def._ore_type then count[def._ore_type] = count[def._ore_type] + 1 end
end
local max = count.copper > count.titanium and count.copper > count.cobalt and 'copper' or count.cobalt > count.titanium and 'titanium' or 'cobalt'
return max, count[max] / 4
end
local build_cost = { copper = 10 }
local spawn_offset = {
[0] = vector.new(0, 0, -0.6),
[1] = vector.new(-0.6, 0, 0),
[2] = vector.new(0, 0, 0.5),
[3] = vector.new(0.5, 0, 0)
}
minetest.register_node('lexa_factory:drill', {
description = 'Drill',
_cost = build_cost,
@ -39,7 +66,8 @@ minetest.register_node('lexa_factory:drill', {
sunlight_propagates = true,
groups = {
oddly_breakable_by_hand = 3,
dig_game = 1
dig_game = 1,
enemy_target = 70
},
drop = '',
on_place = lexa.materials.place(build_cost),
@ -49,17 +77,34 @@ minetest.register_node('lexa_factory:drill', {
minetest.chat_send_all(tostring(node.param2))
local entity_pos = table.copy(pos)
if node.param2 == 1 then entity_pos.z = entity_pos.z - 1 end
if node.param2 == 3 then entity_pos.z = entity_pos.x - 1 end
local base_pos = table.copy(pos)
if node.param2 == 1 or node.param2 == 2 then base_pos.z = base_pos.z - 1 end
if node.param2 == 3 or node.param2 == 2 then base_pos.x = base_pos.x - 1 end
minetest.add_entity(entity_pos, 'lexa_factory:drill_entity', minetest.serialize({ node_pos = pos }))
local type, count = get_ores(base_pos)
local meta = minetest.get_meta(pos)
meta:set_string('type', type)
if count > 0 then
local timer = minetest.get_node_timer(pos)
timer:start(3 - count * 2.5)
end
minetest.add_entity(base_pos, 'lexa_factory:drill_entity', minetest.serialize({ node_pos = pos }))
end,
on_timer = function(pos)
local node = minetest.get_node(pos)
local type = minetest.get_meta(pos):get_string('type')
minetest.add_entity(vector.add(pos, spawn_offset[node.param2]), 'lexa_conveyor:ore_chunk', type)
return true
end,
after_destruct = function(pos)
local entities = minetest.get_objects_in_area(pos, pos)
local entities = minetest.get_objects_in_area(vector.add(pos, vector.new(-1, -1, -1)), vector.add(pos, vector.new(1, 1, 1)))
for _, entity in ipairs(entities) do
local lua_entity = entity:get_luaentity()
if lua_entity and lua_entity.node_pos.x == pos.x and lua_entity.node_pos.y == pos.y
if lua_entity and lua_entity.node_pos and lua_entity.node_pos.x == pos.x and lua_entity.node_pos.y == pos.y
and lua_entity.node_pos.z == pos.z then
entity:remove()
end

View File

@ -9,16 +9,16 @@ lexa.text.register_glyph('count_wave_active', glyph_path .. 'lexa_hud_glyph_wave
local BAR_FULL_WIDTH = 239
-- The current wave status
local last_progress_pixel = 0
local last_status = nil
local status = {
wave = 1,
wave_max = 10,
wait = 180,
wait_max = 180,
enemies = 10,
enemies_max = 10
}
-- local last_progress_pixel = 0
-- local last_status = nil
-- local status = {
-- wave = 1,
-- wave_max = 10,
-- wait = 180,
-- wait_max = 180,
-- enemies = 10,
-- enemies_max = 10
-- }
-- Formats a time in seconds into a 0:00 format.
local function format_time(time)
@ -29,15 +29,18 @@ local function format_time(time)
end
-- Updates the necessary hud elements to keep the match status accurate.
local function refresh_hud(force)
function lexa.hud.refresh_bar(force)
if not lexa.match.state then return end
local status = lexa.match.state.status
for name, state in pairs(lexa.hud.state) do
local elems = state.elements
local player = minetest.get_player_by_name(name)
local wave_active_changed =
force or not last_status or
(status.wait == 0 and last_status.wait > 0) or
(status.wait > 0 and last_status.wait == 0)
-- local wave_active_changed =
-- force or not last_status or
-- (status.wait == 0 and last_status.wait > 0) or
-- (status.wait > 0 and last_status.wait == 0)
local wave_progress = math.min(math.max(status.wait == 0
and status.enemies / math.max(status.enemies_max, 1)
@ -45,35 +48,35 @@ local function refresh_hud(force)
local wave_progress_pixel = math.floor(wave_progress * BAR_FULL_WIDTH)
if wave_active_changed or wave_progress_pixel ~= last_progress_pixel then
-- if wave_active_changed or wave_progress_pixel ~= last_progress_pixel then
local image = '[combine:' .. wave_progress_pixel .. 'x16:0,0=' ..
(status.wait == 0 and 'lexa_hud_progress_bar_fill_active.png' or 'lexa_hud_progress_bar_fill.png')
player:hud_change(elems.match_bar_fill, 'text', image)
last_progress_pixel = wave_progress_pixel
end
-- end
--
-- local wave_status_changed = wave_active_changed or
-- force or not last_status or
-- (status.wait == 0 and status.enemies ~= last_status.enemies) or
-- (status.wait > 0 and math.floor(status.wait) ~= math.floor(last_status.wait))
local wave_status_changed = wave_active_changed or
force or not last_status or
(status.wait == 0 and status.enemies ~= last_status.enemies) or
(status.wait > 0 and math.floor(status.wait) ~= math.floor(last_status.wait))
if wave_status_changed then
-- if wave_status_changed then
player:hud_change(elems.match_wave_status, 'text', lexa.text.render_text(
(status.wait == 0 and ('[!count_enemies] ' .. status.enemies)
or ('[!count_time] ' .. format_time(math.floor(status.wait)))) .. ' Remaining...'))
end
-- end
local match_status_changed =
force or not last_status or
last_status.wave_max ~= status.wave_max or
last_status.wave ~= status.wave
-- local match_status_changed =
-- force or not last_status or
-- last_status.wave_max ~= status.wave_max or
-- last_status.wave ~= status.wave
if match_status_changed or wave_active_changed then
-- if match_status_changed or wave_active_changed then
player:hud_change(elems.match_match_status, 'text', lexa.text.render_text('[!count_wave' ..
(status.wait == 0 and '_active' or '') .. '] Wave ' .. status.wave ..
(status.wave_max and status.wave_max > 0 and ('/' .. status.wave_max) or '')))
end
-- end
last_status = table.copy(status)
end
@ -128,10 +131,5 @@ table.insert(lexa.hud.callbacks.register, function(player)
offset = { x = 336, y = 22 }
})
refresh_hud(true)
end)
minetest.register_globalstep(function(delta)
status.wait = math.max(0, status.wait - delta)
if not last_status or math.ceil(status.wait * 10) ~= math.ceil(last_status.wait * 10) then refresh_hud() end
lexa.hud.refresh_bar(true)
end)

View File

@ -1,4 +1,4 @@
return {
size = { x = 320, y = 153, z = 323 },
spawn = { x = 86, y = 39, z = 127 }
spawn = { x = 89, y = 39, z = 117 }
}

Binary file not shown.

View File

@ -67,38 +67,40 @@ lexa.match.start_match = function(def)
def.map = def.map or 'mountain'
local map_meta = dofile(map_root .. def.map .. '.meta.lua')
-- minetest.place_schematic(vector.new(0, 0, 0), map_root .. def.map .. '.mts')
minetest.place_schematic(vector.new(0, 0, 0), map_root .. def.map .. '.mts')
for _, player in ipairs(minetest.get_connected_players()) do player:set_pos(map_meta.spawn) end
lexa.nav.load_area(vector.new(0, 0, 0), map_meta.size, function()
for _, player in ipairs(minetest.get_connected_players()) do player:set_pos(map_meta.spawn) end
lexa.match.state = {
def = def,
map_meta = map_meta,
status = {
wave = 1,
wave_max = def.waves or 10,
wait = def.wait or 180,
wait_max = def.wait or 180,
enemies = 0,
enemies_max = 0
},
materials = def.materials or {},
graph = lexa.nav.build_graph(map_meta.spawn)
}
lexa.match.state = {
def = def,
map_meta = map_meta,
status = {
wave = 1,
wave_max = def.waves or 180,
wait = def.wait or 180,
wait_max = def.wait or 180,
enemies = 0,
enemies_max = 0
},
materials = def.materials or {},
graph = lexa.nav.build_graph(map_meta.spawn)
}
lexa.hud.update_materials(lexa.match.state.materials)
lexa.hud.update_materials(lexa.match.state.materials)
minetest.chat_send_all(' ')
minetest.chat_send_all('Match started, have fun!')
minetest.chat_send_all(' ')
minetest.after(5, function() minetest.chat_send_all(' ') end)
minetest.chat_send_all(' ')
minetest.chat_send_all('Match started, have fun!')
minetest.chat_send_all(' ')
minetest.after(5, function() minetest.chat_send_all(' ') end)
end)
end
minetest.register_on_joinplayer(function()
if lexa.match.state then return end
lexa.match.start_match({
waves = 10,
wait = 180,
wait = 10,
enemies_initial = 10,
enemies_mult = 5,
materials = {
@ -153,3 +155,26 @@ function lexa.match.use_materials(use)
lexa.match.set_materials(new)
return true
end
minetest.register_globalstep(function(delta)
if not lexa.match.state then return end
lexa.match.state.status.wait = math.max(0, lexa.match.state.status.wait - delta)
lexa.hud.refresh_bar()
if lexa.match.state.status.wait == 0 and lexa.match.state.status.enemies ~= 0 then
lexa.match.spawn_wave()
end
end)
function lexa.match.spawn_wave()
for _, spawn in lexa.match.status.graph.enemy_spawns do
local path = lexa.nav.find_path(lexa.match.state.graph, spawn, lexa.match.state.map_meta.spawn)
for i = 0, 10 do
minetest.after(i, function()
local ent = minetest.add_entity(spawn, 'lexa_enemy:spider', '')
ent.path = path
end)
end
end
end

View File

@ -2,5 +2,6 @@ lexa.materials = {}
lexa.require('ore')
lexa.require('chunk')
lexa.require('input')
lexa.require('helpers')
lexa.require('register')

View File

@ -0,0 +1,20 @@
minetest.register_node('lexa_materials:input', {
description = 'Input',
tiles = {
'lexa_materials_input_top.png',
'lexa_materials_input.png'
},
groups = {
dig_build = 1,
conveyor = 3,
enemy_target = 100
},
_conveyor_function = function(node_pos, item, delta)
local type = item.type
item.object:remove()
local new = table.copy(lexa.match.state.materials)
new[type] = new[type] + 1
lexa.match.set_materials(new)
end,
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -2,6 +2,7 @@ lexa.nav = {}
lexa.require('rpq')
lexa.require('astar')
lexa.require('load')
lexa.require('nodes')
lexa.require('graph')
@ -10,16 +11,18 @@ minetest.register_chatcommand('test_paths', {
privs = { cheats = true },
description = 'Graphs paths from enemy spawns to player spawn',
func = function(name)
if lexa.nav.graph == nil then
if lexa.match.state.graph == nil then
minetest.chat_send_all('Graph not initialized')
return
end
minetest.chat_send_all('Graphing paths.')
for i, spawn in ipairs(lexa.nav.graph.enemy_spawns) do
print(dump(lexa.match.state.graph))
for i, spawn in ipairs(lexa.match.state.graph.enemy_spawns) do
local start_time = minetest.get_us_time()
local path = lexa.nav.find_path(lexa.nav.graph, spawn, lexa.nav.graph.player_spawn, i + 4)
local path = lexa.nav.find_path(lexa.match.state.graph, spawn, lexa.match.state.graph.player_spawn, i + 4)
local duration = math.floor((minetest.get_us_time() - start_time) / 1000)
if path then

View File

@ -53,7 +53,7 @@ function lexa.nav.find_path(graph, from, to)
break
end
for adj, cost in pairs(navigation.adjacent_list) do
for adj, cost in pairs(lexa.nav.adjacent_list) do
local adj_pos = { x = lowest.pos.x + adj.x, y = lowest.pos.y + adj.y, z = lowest.pos.z + adj.z }
local adj_pos_str = serialize_pos(adj_pos)

View File

@ -1,59 +1,59 @@
-- -- The minimum max_forceloaded_blocks for the game to work
-- local REQUIRED_FORCELOADED_BLOCKS = 10000
-- The minimum max_forceloaded_blocks for the game to work
local REQUIRED_FORCELOADED_BLOCKS = 10000
-- -- If the max_forceloaded_blocks is less than what is required, prevent the game from being run.
-- local forceload_is_good = tonumber((minetest.settings:get('max_forceloaded_blocks') or 0)) >= REQUIRED_FORCELOADED_BLOCKS
-- If the max_forceloaded_blocks is less than what is required, prevent the game from being run.
local forceload_is_good = tonumber((minetest.settings:get('max_forceloaded_blocks') or 0)) >= REQUIRED_FORCELOADED_BLOCKS
-- if not forceload_is_good then
-- minetest.register_on_joinplayer(function(player)
-- minetest.kick_player(player:get_player_name(),
-- '\n\nThe server is misconfigured, please set max_forceloaded_blocks = 10000 in minetest.conf.')
-- end)
-- end
if not forceload_is_good then
minetest.register_on_joinplayer(function(player)
minetest.kick_player(player:get_player_name(),
'\n\nThe server is misconfigured, please set max_forceloaded_blocks = 10000 in minetest.conf.')
end)
end
-- --
-- -- Emerges and forceloads the area between min_pos and max_pos (inclusive)
-- -- When the load is complete, calls the callback function with three parameters:
-- -- A function to unload the loaded area, the number of blocks loaded, and the time it took to emerge the area in ms.
-- --
-- -- @param min_pos - The minimum position of the area to emerge
-- -- @param max_pos - The maximum position of the area to emerge
-- -- @param callback - The callback to call when the area is emerged.
-- --
--
-- Emerges and forceloads the area between min_pos and max_pos (inclusive)
-- When the load is complete, calls the callback function with three parameters:
-- A function to unload the loaded area, the number of blocks loaded, and the time it took to emerge the area in ms.
--
-- @param min_pos - The minimum position of the area to emerge
-- @param max_pos - The maximum position of the area to emerge
-- @param callback - The callback to call when the area is emerged.
--
-- function lexa.nav.load_area(min_pos, max_pos, cb)
-- local start_time = minetest.get_us_time()
function lexa.nav.load_area(min_pos, max_pos, cb)
local start_time = minetest.get_us_time()
-- local function free()
-- for x = math.floor(min_pos.x / 16), math.ceil(max_pos.x / 16) do
-- for z = math.floor(min_pos.y / 16), math.ceil(max_pos.y / 16) do
-- for y = math.floor(min_pos.z / 16), math.ceil(max_pos.z / 16) do
-- minetest.forceload_free_block({ x = x, y = y, z = z }, true)
-- end
-- end
-- end
-- end
local function free()
for x = math.floor(min_pos.x / 16), math.ceil(max_pos.x / 16) do
for z = math.floor(min_pos.y / 16), math.ceil(max_pos.y / 16) do
for y = math.floor(min_pos.z / 16), math.ceil(max_pos.z / 16) do
minetest.forceload_free_block({ x = x, y = y, z = z }, true)
end
end
end
end
-- local function forceload()
-- local loaded = 0
local function forceload()
local loaded = 0
-- for x = math.floor(min_pos.x / 16), math.ceil(max_pos.x / 16) do
-- for z = math.floor(min_pos.y / 16), math.ceil(max_pos.y / 16) do
-- for y = math.floor(min_pos.z / 16), math.ceil(max_pos.z / 16) do
-- local pos = { x = x, y = y, z = z }
-- if not minetest.forceload_block(pos, true) then
-- minetest.chat_send_all('[Error] Failed to forceload block at ' .. minetest.pos_to_string(pos) .. '.')
-- end
-- loaded = loaded + 1
-- end
-- end
-- end
for x = math.floor(min_pos.x / 16), math.ceil(max_pos.x / 16) do
for z = math.floor(min_pos.y / 16), math.ceil(max_pos.y / 16) do
for y = math.floor(min_pos.z / 16), math.ceil(max_pos.z / 16) do
local pos = { x = x, y = y, z = z }
if not minetest.forceload_block(pos, true) then
minetest.chat_send_all('[Error] Failed to forceload block at ' .. minetest.pos_to_string(pos) .. '.')
end
loaded = loaded + 1
end
end
end
-- local duration = math.floor((minetest.get_us_time() - start_time) / 1000)
-- cb(free, loaded, duration)
-- end
local duration = math.floor((minetest.get_us_time() - start_time) / 1000)
cb(free, loaded, duration)
end
-- minetest.emerge_area(min_pos, max_pos, function(_, _, remaining)
-- if remaining == 0 then forceload() end
-- end)
-- end
minetest.emerge_area(min_pos, max_pos, function(_, _, remaining)
if remaining == 0 then forceload() end
end)
end

View File

@ -24,6 +24,7 @@ minetest.register_node('lexa_turret:turret_base', {
groups = {
conveyor = 3,
dig_game = 1,
enemy_target = 70
},
drop = '',
on_place = lexa.materials.place(build_cost),

View File

@ -72,7 +72,8 @@ for _, type in ipairs({ 'copper', 'titanium', 'cobalt' }) do
groups = {
dig_game = 1,
wall_bottom = 1,
wall = 1
wall = 1,
enemy_target = 70
},
on_construct = function(pos)
minetest.set_node(vector.add(pos, vector.new(0, 1, 0)), { name = 'lexa_wall:top_' .. type })