Reorganise game into modpacks

This commit is contained in:
rubenwardy 2019-01-11 15:45:27 +00:00
parent 86a5266bb5
commit b38a89c2fe
762 changed files with 9 additions and 8 deletions

View file

@ -0,0 +1,51 @@
# CTF Map
This mod handles multiple maps.
# Creating a new map
## 1. Dependencies
* Minetest 0.4.16 or later.
* Mods
* ctf_map (by copying the folder from this game to `minetest/mods`)
* worldedit and worldedit_commands.
## 2. Find an area
* Can use Minetest Game and any mapgen.
* It must be a cube, and the barrier will be in the exact center.
* It should be around 230x230 in surface area, but this can vary.
* Feel free to modify the area to your needs.
## 3. Select the area
There are multiple ways do this, this is the simplist in most cases.
* If you haven't modified the map at all, do the following to speed up barrier placement:
* Stop Minetest.
* Open up the world's world.mt
* Set backend to "dummy".
* Save.
* Using worldedit, select the area.
* Type /gui, and click "From WE" then "To WE".
* Check that the center location is the right place for the barrier to go.
* Check that the bounds extend far enough.
## 4. Place barriers
* Set the middle barrier direction. The barrier is a plane defined by a co-ordinate = 0.
If the barrier is X=0, then it will placed with every node of the barrier having X=0.
If the barrier is Z=0, then it will placed with every node of the barrier having Z=0.
* Click "place barrier". Note that this command does not have an undo.
## 5. Meta data
* Set the meta data
## 6. Export
* Click export, and wait until completion.
* Copy the two files from `worlddir/schemes/` to `ctf_map/maps/`.
* Rename the files so the two prefixed numbers are consistent to existing maps.
* Profit!

View file

@ -0,0 +1,270 @@
local c_stone = minetest.get_content_id("ctf_map:ind_stone")
local c_stone_red = minetest.get_content_id("ctf_map:ind_stone_red")
local c_glass = minetest.get_content_id("ctf_map:ind_glass")
local c_glass_red = minetest.get_content_id("ctf_map:ind_glass_red")
local c_map_ignore = minetest.get_content_id("ctf_map:ignore")
local c_actual_st = minetest.get_content_id("default:stone")
local c_water = minetest.get_content_id("default:water_source")
-- local c_water_f = minetest.get_content_id("default:water_flowing")
local c_air = minetest.get_content_id("air")
function ctf_map.remove_middle_barrier()
local r = ctf_map.map.r
local h = ctf_map.map.h
local min = vector.add(ctf_map.map.offset, {
x = -r + 1,
y = -h / 2,
z = -1
})
local max = vector.add(ctf_map.map.offset, {
x = r - 1,
y = h / 2,
z = 1
})
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map(min, max)
local a = VoxelArea:new{
MinEdge = emin,
MaxEdge = emax
}
local data = vm:get_data()
for x = min.x, max.x do
for y = min.y, max.y do
local vi = a:index(x, y, 0)
local adj1 = a:index(x, y, 1)
local adj2 = a:index(x, y, -1)
if data[vi] == c_glass_red then
-- If surrounding nodes are water, replace node with water
if data[adj1] == c_water and data[adj2] == c_water then
data[vi] = c_water
-- Else replace with air
else
data[vi] = c_air
end
elseif data[vi] == c_stone_red then
data[vi] = c_actual_st
end
end
end
vm:set_data(data)
vm:write_to_map(data)
vm:update_map()
end
function ctf_map.place_middle_barrier(center, r, h, direction)
assert(direction == "x" or direction == "z")
local min = {
x = -r + 1,
y = -h / 2 + 1,
z = -r + 1,
}
local max = {
x = r - 1,
y = h / 2 - 1,
z = r - 1,
}
local other = "z"
if direction == "z" then
other = "x"
end
min[direction] = -1
max[direction] = 1
min = vector.add(center, min)
max = vector.add(center, max)
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map(min, max)
local a = VoxelArea:new{
MinEdge = emin,
MaxEdge = emax
}
local data = vm:get_data()
for x = min[other], max[other] do
for y = min.y, max.y do
local vi
if other == "x" then
vi = a:index(x, y, center.z)
else
vi = a:index(center.x, y, x)
end
if data[vi] == c_air or data[vi] == c_water then
data[vi] = c_glass_red
end
end
end
vm:set_data(data)
vm:write_to_map(data)
vm:update_map()
end
function ctf_map.place_outer_barrier(center, r, h)
local minp = vector.subtract(center, r)
local maxp = vector.add(center, r)
minp.y = center.y - h / 2
maxp.y = center.y + h / 2
print("Loading data into LVM")
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map(minp, maxp)
local a = VoxelArea:new{
MinEdge = emin,
MaxEdge = emax
}
local data = vm:get_data()
print("Placing left wall")
-- Left
do
local x = center.x - r
for z = minp.z, maxp.z do
for y = minp.y, maxp.y do
local vi = a:index(x, y, z)
if data[vi] == c_air or data[vi] == c_glass or data[vi] == c_map_ignore then
data[vi] = c_glass
else
data[vi] = c_stone
end
end
end
end
print("Placing right wall")
-- Right
do
local x = center.x + r
for z = minp.z, maxp.z do
for y = minp.y, maxp.y do
local vi = a:index(x, y, z)
if data[vi] == c_air or data[vi] == c_glass or data[vi] == c_map_ignore then
data[vi] = c_glass
else
data[vi] = c_stone
end
end
end
end
print("Placing front wall")
-- Front
do
local z = center.z - r
for x = minp.x, maxp.x do
for y = minp.y, maxp.y do
local vi = a:index(x, y, z)
if data[vi] == c_air or data[vi] == c_glass or data[vi] == c_map_ignore then
data[vi] = c_glass
else
data[vi] = c_stone
end
end
end
end
print("Placing back wall")
-- Back
do
local z = center.z + r
for x = minp.x, maxp.x do
for y = minp.y, maxp.y do
local vi = a:index(x, y, z)
if data[vi] == c_air or data[vi] == c_glass or data[vi] == c_map_ignore then
data[vi] = c_glass
else
data[vi] = c_stone
end
end
end
end
print("Placing bedrock")
-- Bedrock
do
local y = minp.y
for x = minp.x, maxp.x do
for z = minp.z, maxp.z do
data[a:index(x, y, z)] = c_stone
end
end
end
print("Placing ceiling")
-- Ceiling
do
local y = maxp.y
for x = minp.x, maxp.x do
for z = minp.z, maxp.z do
data[a:index(x, y, z)] = c_glass
end
end
end
print("Writing to engine!")
vm:set_data(data)
vm:write_to_map(data)
vm:update_map()
end
if minetest.get_modpath("ctf") then
local old_is_protected = minetest.is_protected
function minetest.is_protected(pos, name)
if ctf_match.build_timer <= 0 then
return old_is_protected(pos, name)
end
local tname = ctf.player(name).team
if tname and
(tname == "blue" and pos.z >= 0) or (tname == "red" and pos.z <= 0) then
minetest.chat_send_player(name, "Can't dig beyond the barrier!")
return true
else
return old_is_protected(pos, name)
end
end
local function pos_check()
if ctf_match.build_timer <= 0 then
return
end
for _, player in pairs(minetest.get_connected_players()) do
local name = player:get_player_name()
local tname = ctf.player(name).team
local pos = player:get_pos()
local privs = minetest.get_player_privs(name)
if tname and not privs.fly and privs.interact then
if (tname == "blue" and pos.z >= 0) or
(tname == "red" and pos.z <= 0) then
minetest.chat_send_player(name, "Match hasn't started yet!")
ctf.move_to_spawn(name)
end
end
end
if ctf_match.build_timer > 0.2 then
minetest.after(0.2, pos_check)
end
end
ctf_match.register_on_build_time_start(function()
minetest.after(0.2, pos_check)
end)
end

View file

@ -0,0 +1,6 @@
default
ctf_team_base?
ctf?
ctf_match?
worldedit?
irc?

View file

@ -0,0 +1,33 @@
local function emergeblocks_callback(pos, action, num_calls_remaining, ctx)
if ctx.total_blocks == 0 then
ctx.total_blocks = num_calls_remaining + 1
ctx.current_blocks = 0
end
ctx.current_blocks = ctx.current_blocks + 1
if ctx.current_blocks == ctx.total_blocks then
if ctx.name then
minetest.chat_send_player(ctx.name,
string.format("Finished emerging %d blocks in %.2fms.",
ctx.total_blocks, (os.clock() - ctx.start_time) * 1000))
end
ctx:callback()
elseif ctx.progress then
ctx:progress()
end
end
function ctf_map.emerge_with_callbacks(name, pos1, pos2, callback, progress)
local context = {
current_blocks = 0,
total_blocks = 0,
start_time = os.clock(),
name = name,
callback = callback,
progress = progress
}
minetest.emerge_area(pos1, pos2, emergeblocks_callback, context)
end

View file

@ -0,0 +1,34 @@
give_initial_stuff = {}
setmetatable(give_initial_stuff, {
__call = function(self, player)
minetest.log("action", "Giving initial stuff to player "..player:get_player_name())
local inv = player:get_inventory()
inv:set_list("main", {})
inv:set_list("craft", {})
inv:set_size("craft", 1)
inv:set_size("craftresult", 0)
inv:set_size("hand", 0)
local items = give_initial_stuff.get_stuff()
for _, item in pairs(items) do
inv:add_item("main", item)
end
end
})
function give_initial_stuff.get_stuff()
return ctf_map.map and ctf_map.map.initial_stuff or {
"default:pick_wood",
"default:sword_wood",
"default:torch 3",
}
end
minetest.register_on_joinplayer(function(player)
player:set_hp(20)
give_initial_stuff(player)
end)
minetest.register_on_respawnplayer(give_initial_stuff)

16
mods/ctf/ctf_map/init.lua Normal file
View file

@ -0,0 +1,16 @@
ctf_map = {}
dofile(minetest.get_modpath("ctf_map") .. "/nodes.lua")
dofile(minetest.get_modpath("ctf_map") .. "/emerge.lua")
dofile(minetest.get_modpath("ctf_map") .. "/barrier.lua")
if minetest.get_modpath("ctf") then
dofile(minetest.get_modpath("ctf_map") .. "/schem_map.lua")
dofile(minetest.get_modpath("ctf_map") .. "/give_initial_stuff.lua")
assert(ctf_match)
ctf_match.register_on_build_time_end(ctf_map.remove_middle_barrier)
else
dofile(minetest.get_modpath("ctf_map") .. "/map_maker.lua")
end

View file

@ -0,0 +1,409 @@
local randint = math.random(100)
-- Reload mapmaker context from mod_storage if it exists
local storage = minetest.get_mod_storage()
local mapname = storage:get_string("mapname")
local maptitle = storage:get_string("maptitle")
local mapauthor = storage:get_string("mapauthor")
local mapinitial = storage:get_string("mapinitial")
local center = storage:get_string("center")
local flag_positions = storage:get_string("flags")
local barrier_r = storage:get_int("barrier_r")
local center_barrier_rot = storage:get_int("center_barrier_rot")
if mapname == "" then
mapname = "ctf_" .. randint
end
if mapauthor == "" then
mapauthor = nil
end
if maptitle == "" then
maptitle = "Untitled Map " .. randint
end
if barrier_r == 0 then
barrier_r = 110
end
if center == "" then
center = { x = 0, y = 0, z = 0, r = 115, h = 140 }
else
center = minetest.parse_json(storage:get("center"))
end
if flag_positions == "" then
flag_positions = {}
else
flag_positions = minetest.parse_json(storage:get("flags"))
end
--------------------------------------------------------------------------------
minetest.register_on_joinplayer(function(player)
minetest.after(1, function(name)
minetest.chat_send_player(name, "*** CTF_MAP IS IN MAP MAKER MODE ***")
end, player:get_player_name())
end)
assert(minetest.get_modpath("worldedit") and
minetest.get_modpath("worldedit_commands"),
"worldedit and worldedit_commands are required!")
local function check_step()
for _, pos in pairs(flag_positions) do
if minetest.get_node(pos).name ~= "ctf_map:flag" then
minetest.set_node(pos, { name = "ctf_map:flag" })
end
end
minetest.after(1, check_step)
end
minetest.after(1, check_step)
minetest.register_node("ctf_map:flag", {
description = "Flag",
drawtype="nodebox",
paramtype = "light",
walkable = false,
tiles = {
"default_wood.png",
"default_wood.png",
"default_wood.png",
"default_wood.png",
"flag_grey2.png",
"flag_grey.png"
},
node_box = {
type = "fixed",
fixed = {
{ 0.250000,-0.500000,0.000000,0.312500,0.500000,0.062500},
{ -0.5,0,0.000000,0.250000,0.500000,0.062500}
}
},
groups = {oddly_breakable_by_hand=1,snappy=3},
on_place = function(_, _, pthing)
local node = minetest.get_node(pthing.under).name
local ndef = minetest.registered_nodes[node]
local pos = (ndef and ndef.buildable_to) and pthing.under or pthing.above
table.insert(flag_positions, vector.new(pos))
storage:set_string("flags", minetest.write_json(flag_positions))
end,
on_destruct = function(pos)
for i, v in pairs(flag_positions) do
if vector.equals(pos, v) then
flag_positions[i] = nil
return
end
end
end,
})
local function to_2pos()
return {
x = center.x - center.r,
y = center.y - center.h / 2,
z = center.z - center.r,
}, {
x = center.x + center.r,
y = center.y + center.h / 2,
z = center.z + center.r,
}
end
local function max(a, b)
if a > b then
return a
else
return b
end
end
local function we_select(name)
local pos1, pos2 = to_2pos()
worldedit.pos1[name] = pos1
worldedit.mark_pos1(name)
worldedit.player_notify(name, "position 1 set to " .. minetest.pos_to_string(pos1))
worldedit.pos2[name] = pos2
worldedit.mark_pos2(name)
worldedit.player_notify(name, "position 2 set to " .. minetest.pos_to_string(pos2))
end
local function we_import(name)
local pos1 = worldedit.pos1[name]
local pos2 = worldedit.pos2[name]
if pos1 and pos2 then
local size = vector.subtract(pos2, pos1)
local r = max(size.x, size.z) / 2
center = vector.divide(vector.add(pos1, pos2), 2)
center.r = r
center.h = size.y
storage:set_string("center", minetest.write_json(center))
end
end
local function get_flags()
local negative = nil
local positive = nil
for _, pos in pairs(flag_positions) do
pos = vector.subtract(pos, center)
if center_barrier_rot == 0 and pos.x < 0 or pos.z < 0 then
negative = pos
end
if center_barrier_rot == 0 and pos.x > 0 or pos.z > 0 then
positive = pos
end
end
return negative, positive
end
local function get_flag_status()
if #flag_positions > 2 then
return "Too many flags! (" .. #flag_positions .. "/2)"
elseif #flag_positions < 2 then
return "Place more flags (" .. #flag_positions .. "/2)"
else
local negative, positive = get_flags()
if positive and negative then
return "Flags placed (" .. #flag_positions .. "/2)"
else
return "Place one flag on each side of the barrier."
end
end
end
local function show_gui(name)
if not mapauthor then
mapauthor = name
storage:set_string("mapauthor", mapauthor)
end
local formspec = {
"size[9,9.5]",
"bgcolor[#080808BB;true]",
default.gui_bg,
default.gui_bg_img,
"label[0,0;1. Select Area]",
"field[0.4,1;1,1;posx;X;", center.x, "]",
"field[1.4,1;1,1;posy;Y;", center.y, "]",
"field[2.4,1;1,1;posz;Z;", center.z, "]",
"field[0.4,2;1.5,1;posr;R;", center.r, "]",
"field[1.9,2;1.5,1;posh;H;", center.h, "]",
"button[4.3,0.7;1.75,1;set_center;Player Pos]",
"button[6.05,0.7;1.5,1;towe;To WE]",
"button[7.55,0.7;1.5,1;fromwe;From WE]",
"button[4.3,1.7;4.75,1;emerge;Emerge Area]",
"box[0,2.65;8.85,0.05;#111111BB]",
"label[0,2.8;2. Place Barriers]",
"label[0.1,3.3;This may take a few minutes.]",
"field[0.4,4.3;1,1;barrier_r;R;", barrier_r, "]",
"dropdown[1.15,4.05;1,1;center_barrier_rot;X=0,Z=0;", center_barrier_rot + 1, "]",
"button[2.3,4;2,1;place_barrier;Place Barriers]",
"box[4.4,2.8;0.05,2.2;#111111BB]",
"label[4.8,2.8;3. Place Flags]",
"label[4.8,3.3;", minetest.formspec_escape(get_flag_status()), "]",
"button[4.8,4;3.5,1;giveme;Giveme Flags]",
"box[0,5.06;8.85,0.05;#111111BB]",
"label[0,5.15;4. Meta Data]",
"field[0.4,6.2;8.5,1;title;Title;", minetest.formspec_escape(maptitle), "]",
"field[0.4,7.3;8.5,1;initial;Stuff to give on (re)spawn, comma-separated itemstrings;",
minetest.formspec_escape(mapinitial), "]",
"field[0.4,8.4;4.25,1;name;File Name;" , minetest.formspec_escape(mapname), "]",
"field[4.625,8.4;4.25,1;author;Author;", minetest.formspec_escape(mapauthor), "]",
"button_exit[1.3,9;3,1;close;Close]",
"button_exit[4.3,9;3,1;export;Export]",
}
formspec = table.concat(formspec, "")
minetest.show_formspec(name, "ctf_map:tool", formspec)
end
local function show_progress_formspec(name, text)
minetest.show_formspec(name, "ctf_map:progress",
"size[6,1]bgcolor[#080808BB;true]" ..
default.gui_bg ..
default.gui_bg_img .. "label[0,0;" ..
minetest.formspec_escape(text) .. "]")
end
local function emerge_progress(ctx)
show_progress_formspec(ctx.name, string.format("Emerging Area - %d/%d blocks emerged (%.1f%%)",
ctx.current_blocks, ctx.total_blocks,
(ctx.current_blocks / ctx.total_blocks) * 100))
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "ctf_map:tool" then
return
end
if fields.posx then
center.x = tonumber(fields.posx)
center.y = tonumber(fields.posy)
center.z = tonumber(fields.posz)
center.r = tonumber(fields.posr)
center.h = tonumber(fields.posh)
storage:set_string("center", minetest.write_json(center))
end
fields.barrier_r = tonumber(fields.barrier_r)
if fields.barrier_r and fields.barrier_r ~= barrier_r then
barrier_r = fields.barrier_r
storage:set_int("barrier_r", barrier_r)
end
if fields.title and fields.title ~= maptitle then
maptitle = fields.title
storage:set_string("maptitle", maptitle)
end
if fields.author and fields.author ~= mapauthor then
mapauthor = fields.author
storage:set_string("mapauthor", mapauthor)
end
if fields.name and fields.name ~= mapname then
mapname = fields.name
storage:set_string("mapname", mapname)
end
if fields.initial and fields.initial ~= mapinitial then
mapinitial = fields.initial
storage:set_string("mapinitial", mapinitial)
end
if fields.center_barrier_rot and fields.center_barrier_rot ~= "" then
center_barrier_rot = fields.center_barrier_rot == "X=0" and 0 or 1
storage:set_int("center_barrier_rot", center_barrier_rot)
end
if fields.set_center then
local r = center.r
local h = center.h
center = vector.floor(player:get_pos())
center.r = r
center.h = h
storage:set_string("center", minetest.write_json(center))
end
if fields.giveme then
player:get_inventory():add_item("main", "ctf_map:flag 2")
end
local player_name = player:get_player_name()
if fields.emerge then
local pos1, pos2 = to_2pos()
show_progress_formspec(player_name, "Emerging area...")
ctf_map.emerge_with_callbacks(player_name, pos1, pos2, function()
show_gui(player_name)
end, emerge_progress)
return true
end
if fields.place_barrier then
local pos1, pos2 = to_2pos()
show_progress_formspec(player_name, "Emerging area...")
ctf_map.emerge_with_callbacks(player_name, pos1, pos2, function()
show_progress_formspec(player_name, "Placing center barrier, this may take a while...")
minetest.after(0.1, function()
ctf_map.place_middle_barrier(center, barrier_r, center.h, (center_barrier_rot == 0) and "x" or "z")
show_progress_formspec(player_name, "Placing outer barriers, this may take a while...")
minetest.after(0.1, function()
ctf_map.place_outer_barrier(center, barrier_r, center.h)
show_gui(player_name)
end)
end)
end, emerge_progress)
return true
end
if fields.towe then
we_select(player_name)
end
if fields.fromwe then
we_import(player_name)
end
if fields.export then
if #flag_positions ~= 2 then
minetest.chat_send_all("You need to place two flags!")
return
end
we_select(player_name)
show_progress_formspec(player_name, "Exporting...")
local path = minetest.get_worldpath() .. "/schems/"
minetest.mkdir(path)
-- Reset mod_storage
storage:set_string("center", "")
storage:set_string("maptitle", "")
storage:set_string("mapauthor", "")
storage:set_string("mapname", "")
storage:set_string("mapinitial", "")
storage:set_string("center_barrier_rot", "")
storage:set_string("barrier_r", "")
-- Write to .conf
local meta = Settings(path .. mapname .. ".conf")
meta:set("name", maptitle)
meta:set("author", mapauthor)
meta:set("initial_stuff", mapinitial)
meta:set("rotation", center_barrier_rot == 0 and "x" or "z")
meta:set("r", center.r)
meta:set("h", center.h)
for _, flags in pairs(flag_positions) do
local pos = vector.subtract(flags, center)
if center_barrier_rot == 0 then
local old = vector.new(pos)
pos.x = old.z
pos.z = -old.x
end
local idx = pos.z > 0 and 1 or 2
meta:set("team." .. idx, pos.z > 0 and "red" or "blue")
meta:set("team." .. idx .. ".color", pos.z > 0 and "red" or "blue")
meta:set("team." .. idx .. ".pos", minetest.pos_to_string(pos))
end
meta:write()
minetest.after(0.1, function()
local filepath = path .. mapname .. ".mts"
if minetest.create_schematic(worldedit.pos1[player_name],
worldedit.pos2[player_name], worldedit.prob_list[player_name],
filepath) then
minetest.chat_send_all("Exported " .. mapname .. " to " .. path)
minetest.close_formspec(player_name, "")
else
minetest.chat_send_all("Failed!")
show_gui(player_name)
end
end)
return
end
if not fields.quit then
show_gui(player_name)
end
end)
minetest.register_chatcommand("gui", {
func = function(name)
show_gui(name)
return true
end
})

View file

@ -0,0 +1,81 @@
minetest.register_node("ctf_map:ignore", {
description = "Artificial Ignore", -- this may need to be given a more appropriate name
drawtype = "airlike",
paramtype = "light",
sunlight_propagates = true,
walkable = true,
pointable = false,
diggable = false,
buildable_to = false,
air_equivalent = true,
drop = "",
groups = {not_in_creative_inventory=1}
})
minetest.register_node("ctf_map:ind_glass", {
description = "Indestructible Glass",
drawtype = "glasslike_framed_optional",
tiles = {"default_glass.png", "default_glass_detail.png"},
inventory_image = minetest.inventorycube("default_glass.png"),
paramtype = "light",
sunlight_propagates = true,
is_ground_content = false,
walkable = true,
buildable_to = false,
pointable = false,
groups = {immortal = 1},
sounds = default.node_sound_glass_defaults()
})
minetest.register_node("ctf_map:ind_stone", {
description = "Indestructible Stone",
groups = {immortal = 1},
tiles = {"default_stone.png"},
is_ground_content = false
})
minetest.register_node("ctf_map:ind_dirt", {
description = "Indestructible Dirt",
groups = {immortal = 1},
tiles = {"default_dirt.png"},
is_ground_content = false,
sounds = default.node_sound_dirt_defaults({
footstep = {name = "default_grass_footstep", gain = 0.25}
}),
})
minetest.register_node("ctf_map:ind_dirt_with_grass", {
description = "Indestructible Dirt with Grass",
groups = {immortal = 1},
tiles = {"default_grass.png", "default_dirt.png",
{name = "default_dirt.png^default_grass_side.png",
tileable_vertical = false}},
is_ground_content = false,
sounds = default.node_sound_dirt_defaults({
footstep = {name = "default_grass_footstep", gain = 0.25},
}),
})
minetest.register_node("ctf_map:ind_stone_red", {
description = "Indestructible Red Stone",
groups = {immortal = 1},
tiles = {"ctf_map_stone_red.png"},
is_ground_content = false
})
minetest.register_node("ctf_map:ind_glass_red", {
description = "Indestructible Red Glass",
drawtype = "glasslike",
tiles = {"ctf_map_glass_red.png"},
inventory_image = minetest.inventorycube("default_glass.png"),
paramtype = "light",
sunlight_propagates = true,
is_ground_content = false,
walkable = true,
buildable_to = false,
use_texture_alpha = false,
alpha = 0,
pointable = false,
groups = {immortal = 1},
sounds = default.node_sound_glass_defaults()
})

View file

@ -0,0 +1,287 @@
assert(minetest.get_mapgen_setting("mg_name") == "singlenode", "singlenode mapgen is required.")
minetest.register_alias("mapgen_singlenode", "ctf_map:ignore")
minetest.register_alias("ctf_map:flag", "air")
minetest.register_alias("flowers:mushroom_red", "air")
minetest.register_alias("flowers:mushroom_brown", "air")
minetest.register_alias("flowers:waterlily", "air")
minetest.register_alias("flowers:rose", "air")
minetest.register_alias("flowers:tulip", "air")
minetest.register_alias("flowers:dandelion_yellow", "air")
minetest.register_alias("flowers:geranium", "air")
minetest.register_alias("flowers:viola", "air")
minetest.register_alias("flowers:dandelion_white", "air")
minetest.register_alias("flowers:chrysanthemum_green", "air")
minetest.register_alias("default:grass_1", "air")
minetest.register_alias("default:grass_2", "air")
minetest.register_alias("default:grass_3", "air")
minetest.register_alias("default:grass_4", "air")
minetest.register_alias("default:sand_with_kelp", "default:sand")
minetest.register_alias("default:grass_5", "air")
minetest.register_alias("default:bush_leaves", "air")
minetest.register_alias("default:bush_stem", "air")
minetest.register_alias("default:stone_with_gold", "default:stone")
local max_r = 120
local mapdir = minetest.get_modpath("ctf_map") .. "/maps/"
ctf_map.map = nil
local next_idx
minetest.register_chatcommand("set_next", {
privs = { ctf_admin = true },
func = function(name, param)
for i, mname in pairs(ctf_map.available_maps) do
if mname:lower():find(param, 1, true) then
next_idx = i
return true, "Selected " .. mname
end
end
end,
})
local function search_for_maps()
local files_hash = {}
local dirs = minetest.get_dir_list(mapdir, true)
table.insert(dirs, ".")
for _, dir in pairs(dirs) do
if dir ~= ".git" then
local files = minetest.get_dir_list(mapdir .. dir, false)
for i=1, #files do
local parts = files[i]:split(".")
local filename = parts[1]
local extension = parts[2]
if extension == "mts" then
files_hash[dir .. "/" .. filename] = true
else
if extension ~= "conf" and extension ~= "md"
and files[i] ~= ".git" then
error("Map extension is not '.mts': " .. files[i])
end
end
end
end
end
ctf_map.available_maps = {}
for key, _ in pairs(files_hash) do
local conf = Settings(mapdir .. "/" .. key .. ".conf")
minetest.log("error", "ctf.maps." .. key:gsub("%./", ""):gsub("/", "."))
local val = minetest.settings:get("ctf.maps." .. key:gsub("%./", ""):gsub("/", "."))
if not conf:get_bool("disabled", false) and val ~= "false" then
table.insert(ctf_map.available_maps, key)
end
end
if next(ctf_map.available_maps) == nil then
error("No maps found in directory " .. mapdir)
end
return ctf_map.available_maps
end
search_for_maps()
minetest.register_chatcommand("maps_reload", {
privs = { ctf_admin = true },
func = function(name, param)
local maps = search_for_maps()
next_idx = nil
return true, #maps .. " maps found: " .. table.concat(maps, ", ")
end,
})
function ctf_map.place_map(map)
ctf_map.emerge_with_callbacks(nil, map.pos1, map.pos2, function()
local schempath = mapdir .. map.schematic
local res = minetest.place_schematic(map.pos1, schempath,
map.rotation == "z" and "0" or "90")
assert(res)
for _, value in pairs(ctf_map.map.teams) do
ctf_team_base.place(value.color, value.pos)
end
local seed = minetest.get_mapgen_setting("seed")
for _, chestzone in pairs(ctf_map.map.chests) do
minetest.log("warning", "Placing " .. chestzone.n .. " chests from " ..
minetest.pos_to_string(chestzone.from) .. " to "..
minetest.pos_to_string(chestzone.to))
place_chests(chestzone.from, chestzone.to, seed, chestzone.n)
end
minetest.after(2, function()
local msg = "Map: " .. map.name .. " by " .. map.author
if map.hint then
msg = msg .. "\n" .. map.hint
end
minetest.chat_send_all(msg)
if minetest.global_exists("irc") and irc.connected then
irc:say("Map: " .. map.name)
end
end)
minetest.after(10, function()
minetest.fix_light(ctf_map.map.pos1, ctf_map.map.pos2)
end)
end, nil)
end
function ctf_match.load_map_meta(idx, name)
local offset = vector.new(600 * idx, 0, 0)
local conf_path = mapdir .. name .. ".conf"
local meta = Settings(conf_path)
if meta:get("r") == nil then
error("Map was not properly configured " .. conf_path)
end
local initial_stuff = meta:get("initial_stuff")
local map = {
idx = idx,
name = meta:get("name"),
author = meta:get("author"),
hint = meta:get("hint"),
rotation = meta:get("rotation"),
schematic = name .. ".mts",
initial_stuff = initial_stuff and initial_stuff:split(","),
r = tonumber(meta:get("r")),
h = tonumber(meta:get("h")),
offset = offset,
teams = {},
chests = {},
}
assert(map.r <= max_r)
map.pos1 = vector.add(offset, { x = -map.r, y = -map.h / 2, z = -map.r })
map.pos2 = vector.add(offset, { x = map.r, y = map.h / 2, z = map.r })
-- Read teams from config
local i = 1
while meta:get("team." .. i) do
local tname = meta:get("team." .. i)
local tcolor = meta:get("team." .. i .. ".color")
local tpos = minetest.string_to_pos(meta:get("team." .. i .. ".pos"))
map.teams[tname] = {
color = tcolor,
pos = vector.add(offset, tpos),
}
i = i + 1
end
-- Read custom chest zones from config
i = 1
while meta:get("chests." .. i .. ".from") do
local from = minetest.string_to_pos(meta:get("chests." .. i .. ".from"))
local to = minetest.string_to_pos(meta:get("chests." .. i .. ".to"))
assert(from and to, "Positions needed for chest zone " .. i .. " in map " .. map.name)
map.chests[i] = {
from = vector.add(offset, from),
to = vector.add(offset, to),
n = tonumber(meta:get("chests." .. i .. ".n") or "23"),
}
minetest.log("warning", dump(map.chests[i]))
i = i + 1
end
-- Add default chest zones if none given
if i == 1 then
while meta:get("team." .. i) do
local chests1
if i == 1 then
chests1 = vector.add(offset, { x = -map.r, y = -map.h / 2, z = 0 })
elseif i == 2 then
chests1 = map.pos1
end
local chests2
if i == 1 then
chests2 = map.pos2
elseif i == 2 then
chests2 = vector.add(offset, { x = map.r, y = map.h / 2, z = 0 })
end
map.chests[i] = {
from = chests1,
to = chests2,
n = 23,
}
i = i + 1
end
end
return map
end
ctf_match.register_on_new_match(function()
minetest.clear_objects({ mode = "quick" })
-- Choose next map index, but don't select the same one again
local idx
if next_idx then
idx = next_idx
elseif ctf_map.map then
idx = math.random(#ctf_map.available_maps - 1)
if idx >= ctf_map.map.idx then
idx = idx + 1
end
else
idx = math.random(#ctf_map.available_maps)
end
next_idx = (idx % #ctf_map.available_maps) + 1
-- Load meta data
local name = ctf_map.available_maps[idx]
ctf_map.map = ctf_match.load_map_meta(idx, name)
-- Place map
ctf_map.place_map(ctf_map.map)
end)
function ctf_match.create_teams()
for key, value in pairs(ctf_map.map.teams) do
local name = key
local color = value.color
local flag = value.pos
if name and color and flag then
print(" - creating " .. key)
ctf.team({
name = name,
color = color,
add_team = true
})
ctf_flag.add(name, flag)
minetest.after(0, function()
ctf_flag.assert_flag(flag)
end)
else
minetest.log("error", " - Failed to create " .. key)
end
end
end
minetest.register_on_joinplayer(function(player)
local map = ctf_map.map
if not map then
return
end
local msg = "Map: " .. map.name .. " by " .. map.author
if map.hint then
msg = msg .. "\n" .. map.hint
end
minetest.chat_send_player(player:get_player_name(), msg)
end)

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B