add mod itself

This commit is contained in:
chmodsayshello 2022-10-03 10:30:47 +00:00
parent 07f830e2be
commit 37e7ee967f
5 changed files with 574 additions and 0 deletions

306
chatcmdbuilder.lua Normal file
View File

@ -0,0 +1,306 @@
ChatCmdBuilder = {}
function ChatCmdBuilder.new(name, func, def)
def = def or {}
local cmd = ChatCmdBuilder.build(func)
cmd.def = def
def.func = cmd.run
minetest.register_chatcommand(name, def)
return cmd
end
local STATE_READY = 1
local STATE_PARAM = 2
local STATE_PARAM_TYPE = 3
local bad_chars = {}
bad_chars["("] = true
bad_chars[")"] = true
bad_chars["."] = true
bad_chars["%"] = true
bad_chars["+"] = true
bad_chars["-"] = true
bad_chars["*"] = true
bad_chars["?"] = true
bad_chars["["] = true
bad_chars["^"] = true
bad_chars["$"] = true
local function escape(char)
if bad_chars[char] then
return "%" .. char
else
return char
end
end
local dprint = function() end
ChatCmdBuilder.types = {
pos = "%(? *(%-?[%d.]+) *, *(%-?[%d.]+) *, *(%-?[%d.]+) *%)?",
text = "(.+)",
number = "(%-?[%d.]+)",
int = "(%-?[%d]+)",
word = "([^ ]+)",
alpha = "([A-Za-z]+)",
modname = "([a-z0-9_]+)",
alphascore = "([A-Za-z_]+)",
alphanumeric = "([A-Za-z0-9]+)",
username = "([A-Za-z0-9-_]+)",
}
function ChatCmdBuilder.build(func)
local cmd = {
_subs = {}
}
function cmd:sub(route, func, def)
dprint("Parsing " .. route)
def = def or {}
if string.trim then
route = string.trim(route)
end
local sub = {
pattern = "^",
params = {},
func = func
}
-- End of param reached: add it to the pattern
local param = ""
local param_type = ""
local should_be_eos = false
local function finishParam()
if param ~= "" and param_type ~= "" then
dprint(" - Found param " .. param .. " type " .. param_type)
local pattern = ChatCmdBuilder.types[param_type]
if not pattern then
error("Unrecognised param_type=" .. param_type)
end
sub.pattern = sub.pattern .. pattern
table.insert(sub.params, param_type)
param = ""
param_type = ""
end
end
-- Iterate through the route to find params
local state = STATE_READY
local catching_space = false
local match_space = " " -- change to "%s" to also catch tabs and newlines
local catch_space = match_space.."+"
for i = 1, #route do
local c = route:sub(i, i)
if should_be_eos then
error("Should be end of string. Nothing is allowed after a param of type text.")
end
if state == STATE_READY then
if c == ":" then
dprint(" - Found :, entering param")
state = STATE_PARAM
param_type = "word"
catching_space = false
elseif c:match(match_space) then
print(" - Found space")
if not catching_space then
catching_space = true
sub.pattern = sub.pattern .. catch_space
end
else
catching_space = false
sub.pattern = sub.pattern .. escape(c)
end
elseif state == STATE_PARAM then
if c == ":" then
dprint(" - Found :, entering param type")
state = STATE_PARAM_TYPE
param_type = ""
elseif c:match(match_space) then
print(" - Found whitespace, leaving param")
state = STATE_READY
finishParam()
catching_space = true
sub.pattern = sub.pattern .. catch_space
elseif c:match("%W") then
dprint(" - Found nonalphanum, leaving param")
state = STATE_READY
finishParam()
sub.pattern = sub.pattern .. escape(c)
else
param = param .. c
end
elseif state == STATE_PARAM_TYPE then
if c:match(match_space) then
print(" - Found space, leaving param type")
state = STATE_READY
finishParam()
catching_space = true
sub.pattern = sub.pattern .. catch_space
elseif c:match("%W") then
dprint(" - Found nonalphanum, leaving param type")
state = STATE_READY
finishParam()
sub.pattern = sub.pattern .. escape(c)
else
param_type = param_type .. c
end
end
end
dprint(" - End of route")
finishParam()
sub.pattern = sub.pattern .. "$"
dprint("Pattern: " .. sub.pattern)
table.insert(self._subs, sub)
end
if func then
func(cmd)
end
cmd.run = function(name, param)
for i = 1, #cmd._subs do
local sub = cmd._subs[i]
local res = { string.match(param, sub.pattern) }
if #res > 0 then
local pointer = 1
local params = { name }
for j = 1, #sub.params do
local param = sub.params[j]
if param == "pos" then
local pos = {
x = tonumber(res[pointer]),
y = tonumber(res[pointer + 1]),
z = tonumber(res[pointer + 2])
}
table.insert(params, pos)
pointer = pointer + 3
elseif param == "number" or param == "int" then
table.insert(params, tonumber(res[pointer]))
pointer = pointer + 1
else
table.insert(params, res[pointer])
pointer = pointer + 1
end
end
if table.unpack then
-- lua 5.2 or later
return sub.func(table.unpack(params))
else
-- lua 5.1 or earlier
return sub.func(unpack(params))
end
end
end
return false, "Invalid command"
end
return cmd
end
local function run_tests()
if not (ChatCmdBuilder.build(function(cmd)
cmd:sub("bar :one and :two:word", function(name, one, two)
if name == "singleplayer" and one == "abc" and two == "def" then
return true
end
end)
end)).run("singleplayer", "bar abc and def") then
error("Test 1 failed")
end
local move = ChatCmdBuilder.build(function(cmd)
cmd:sub("move :target to :pos:pos", function(name, target, pos)
if name == "singleplayer" and target == "player1" and
pos.x == 0 and pos.y == 1 and pos.z == 2 then
return true
end
end)
end).run
if not move("singleplayer", "move player1 to 0,1,2") then
error("Test 2 failed")
end
if not move("singleplayer", "move player1 to (0,1,2)") then
error("Test 3 failed")
end
if not move("singleplayer", "move player1 to 0, 1,2") then
error("Test 4 failed")
end
if not move("singleplayer", "move player1 to 0 ,1, 2") then
error("Test 5 failed")
end
if not move("singleplayer", "move player1 to 0, 1, 2") then
error("Test 6 failed")
end
if not move("singleplayer", "move player1 to 0 ,1 ,2") then
error("Test 7 failed")
end
if not move("singleplayer", "move player1 to ( 0 ,1 ,2)") then
error("Test 8 failed")
end
if move("singleplayer", "move player1 to abc,def,sdosd") then
error("Test 9 failed")
end
if move("singleplayer", "move player1 to abc def sdosd") then
error("Test 10 failed")
end
if not (ChatCmdBuilder.build(function(cmd)
cmd:sub("does :one:int plus :two:int equal :three:int", function(name, one, two, three)
if name == "singleplayer" and one + two == three then
return true
end
end)
end)).run("singleplayer", "does 1 plus 2 equal 3") then
error("Test 11 failed")
end
local checknegint = ChatCmdBuilder.build(function(cmd)
cmd:sub("checknegint :x:int", function(name, x)
return x
end)
end).run
if checknegint("checker","checknegint -2") ~= -2 then
error("Test 12 failed")
end
local checknegnumber = ChatCmdBuilder.build(function(cmd)
cmd:sub("checknegnumber :x:number", function(name, x)
return x
end)
end).run
if checknegnumber("checker","checknegnumber -3.3") ~= -3.3 then
error("Test 13 failed")
end
local checknegpos = ChatCmdBuilder.build(function(cmd)
cmd:sub("checknegpos :pos:pos", function(name, pos)
return pos
end)
end).run
local negpos = checknegpos("checker","checknegpos (-13.3,-4.6,-1234.5)")
if negpos.x ~= -13.3 or negpos.y ~= -4.6 or negpos.z ~= -1234.5 then
error("Test 14 failed")
end
local checktypes = ChatCmdBuilder.build(function(cmd)
cmd:sub("checktypes :int:int :number:number :pos:pos :word:word :text:text", function(name, int, number, pos, word, text)
return int, number, pos.x, pos.y, pos.z, word, text
end)
end).run
local int, number, posx, posy, posz, word, text
int, number, posx, posy, posz, word, text = checktypes("checker","checktypes -1 -2.4 (-3,-5.3,6.12) some text to finish off with")
--dprint(int, number, posx, posy, posz, word, text)
if int ~= -1 or number ~= -2.4 or posx ~= -3 or posy ~= -5.3 or posz ~= 6.12 or word ~= "some" or text ~= "text to finish off with" then
error("Test 15 failed")
end
dprint("All tests passed")
end
if not minetest then
run_tests()
end

118
init.lua Normal file
View File

@ -0,0 +1,118 @@
--20221002_1a
local S = minetest.get_translator("the_bridge")
team_id_red = 1
team_id_blue = 2
local modpath = minetest.get_modpath("the_bridge")
minetest.register_privilege("the_bridge_admin", S("Is required in order to manage the bride games!"))
arena_lib.register_minigame("the_bridge", {
name = "The Bridge",
--icon = "magiccompass_the_bridge.png",
teams = { S("red"), S("blue") },
teams_color_overlay = { "crimson", "blue"},
celebration_time = 3,
load_time = 6,
prefix = "[TB] ",
queue_waiting_time = 20,
show_minimap = true,
join_while_in_progress=false,
properties = {
the_bridge_area_pos_1 = {x = 0, y = 0, z = 0},
the_bridge_area_pos_2 = {x = 0, y = 0, z = 0},
mapdata = nil,
},
in_game_physics = {
speed = player_speed,
jump = player_jump,
},
disabled_damage_types = {},
hotbar = {
slots = 8,
},
team_properties = {
goals = 0
},
})
if not minetest.get_modpath("lib_chatcmdbuilder") then
dofile(minetest.get_modpath("the_bridge") .. "/chatcmdbuilder.lua")
end
dofile(minetest.get_modpath("the_bridge") .. "/setup.lua")
dofile(minetest.get_modpath("the_bridge") .. "/the_bridge.lua")
ChatCmdBuilder.new("the_bridge", function(cmd)
-- create arena
cmd:sub("create :arena", function(name, arena_name)
arena_lib.create_arena(name, "the_bridge", arena_name)
end)
cmd:sub("create :arena :minplayers:int :maxplayers:int", function(name, arena_name, min_players, max_players)
arena_lib.create_arena(name, "the_bridge", arena_name, min_players, max_players)
end)
-- remove arena
cmd:sub("remove :arena", function(name, arena_name)
arena_lib.remove_arena(name, "the_bridge", arena_name)
end)
-- list of the arenas
cmd:sub("list", function(name)
arena_lib.print_arenas(name, "the_bridge")
end)
-- enter editor mode
cmd:sub("edit :arena", function(sender, arena)
arena_lib.enter_editor(sender, "the_bridge", arena)
end)
-- enable and disable arenas
cmd:sub("enable :arena", function(name, arena)
arena_lib.enable_arena(name, "the_bridge", arena)
end)
cmd:sub("disable :arena", function(name, arena)
arena_lib.disable_arena(name, "the_bridge", arena)
end)
end, {
description = [[
(/help the_bridge)
Use this to configure your arena:
- create <arena name> [min players] [max players]
- edit <arena name>
- enable <arena name>
Other commands:
- remove <arena name>
- disable <arena>
]],
privs = {
the_bridge_admin = true
},
})
arena_lib.on_enable("the_bridge", function(arena, p_name)
if #arena.the_bridge_area_pos_1 ~= #arena.the_bridge_area_pos_2 then
minetest.chat_send_player(p_name,"Missing params in the positions")
return false
end
return true
end)

2
mod.conf Normal file
View File

@ -0,0 +1,2 @@
author = chmodsayshello
depends = arena_lib, walkover

58
setup.lua Normal file
View File

@ -0,0 +1,58 @@
local S = minetest.get_translator("the_bridge")
local function send_message(arena,num_str)
arena_lib.HUD_send_msg_all("title", arena, num_str, 1,nil,0xFF0000)
--arena_lib.HUD_send_msg_all(HUD_type, arena, msg, <duration>, <sound>, <color>)
end
function savemap(pos_min,pos_max,arena)
local manip = VoxelManip(pos_min,pos_max)
local emin, emax = manip:read_from_map(pos_min, pos_max)
local data = manip:get_data()
arena.mapdata = data
local a = VoxelArea:new{
MinEdge = emin,
MaxEdge = emax
}
for x = emin.x,emax.x do
for y = emin.y,emax.y do
for z = emin.z, emax.z do
local idx = a:index(x, y, z)
arena.mapdata[idx]=data[idx]
end
end
end
end
function restore_map(arena)
local manip = VoxelManip(arena.the_bridge_area_pos_1,arena.the_bridge_area_pos_2)
manip:set_data(arena.mapdata)
manip:write_to_map(true)
end
arena_lib.on_load("the_bridge", function(arena)
savemap(arena.the_bridge_area_pos_1,arena.the_bridge_area_pos_2,arena)--backup map
if not arena.teams_enabled then
send_message(arena,"cancelled!")
arena_lib.force_arena_ending("the_bridge", arena)
minetest.log("warning","The Bridge is not supposed to run without any teams!")
end --this game is not supposed to be used without teams!
send_message(arena,S("GO!"))
end)
arena_lib.on_enable("the_bridge", function(arena, p_name)
savemap(arena.the_bridge_area_pos_1,arena.the_bridge_area_pos_2,arena)
return true
end)
arena_lib.on_end("the_bridge", function(arena, players, winners, spectators, is_forced)
restore_map(arena)
end)
arena_lib.on_disable("the_bridge", function(arena, p_name)
restore_map(arena)
return true
end)

90
the_bridge.lua Normal file
View File

@ -0,0 +1,90 @@
local S = minetest.get_translator("the_bridge")
local function after_goal(arena)
local players_team_red = arena_lib.get_players_in_team(arena, team_id_red, true)
local players_team_blue = arena_lib.get_players_in_team(arena, team_id_blue, true)
for player_index in ipairs(players_team_red) do
local player = players_team_red[player_index]
player:set_hp(20)
player:set_pos(arena_lib.get_random_spawner(arena, team_id_red))
end
for player_index in ipairs(players_team_blue) do
local player = players_team_blue[player_index]
player:set_hp(20)
player:set_pos(arena_lib.get_random_spawner(arena, team_id_blue))
end
end
local goalfunc = function(pos, node, player)
minetest.log("check!")
if not player then return end
arena = arena_lib.get_arena_by_player(player:get_player_name())
if not arena then return end
minetest.log("check passed!")
nodename = node.name
if nodename == "the_bridge:goal_area_red" then
arena.teams[team_id_red].goals = arena.teams[team_id_red].goals +1
if arena.teams[team_id_red].goals >= 5 and arena.in_game then
arena_lib.load_celebration("the_bridge", arena, team_id_red)
return
end
after_goal(arena)
elseif nodename == "the_bridge:goal_area_blue" then
arena.teams[team_id_blue].goals = arena.teams[team_id_blue].goals +1
if arena.teams[team_id_blue].goals >= 5 and arena.in_game then
arena_lib.load_celebration("the_bridge", arena, team_id_blue)
return
end
after_goal(arena)
end
end
-- __________________
--__________________/Node Registration\____________
minetest.register_node("the_bridge:goal_area_red",{
description = S("Red Goal"),
drawtype = "glasslike",
tiles = {"^[colorize:#d9405e"},
paramtype = "light",
sunlight_propagates = true,
walkable = true,
pointable = true,
diggable = false,
buildable_to = false,
drop = "",
on_walk_over=goalfunc,
})
minetest.register_node("the_bridge:goal_area_blue",{
description = S("Blue Goal"),
drawtype = "glasslike",
tiles = {"^[colorize:#3548da"},
paramtype = "light",
sunlight_propagates = true,
walkable = true,
pointable = true,
diggable = false,
buildable_to = false,
drop = "",
on_walk_over=goalfunc,
})
minetest.register_node("the_bridge:void", {
description = S("The Bridge void"),
drawtype = "airlike",
paramtype = "light",
sunlight_propagates = true,
walkable = true,
pointable = true,
diggable = false,
buildable_to = false,
drop = "",
damage_per_second = 40,
})