Add towns
This commit is contained in:
parent
26ba673220
commit
7c08d3f61a
7 changed files with 456 additions and 29 deletions
|
|
@ -20,10 +20,13 @@ function ns.register_spawner(def)
|
|||
ns.spawners[def.plot] = def
|
||||
end
|
||||
|
||||
function ns.create_spawner(for_plot)
|
||||
function ns.create_spawner(for_plot, owner)
|
||||
local s = ItemStack("rgt_towns:spawner")
|
||||
local m = s:get_meta()
|
||||
m:set_string("plot", for_plot)
|
||||
if owner then
|
||||
m:set_string("owner", owner)
|
||||
end
|
||||
m:set_string("description", ns.spawners[for_plot].label)
|
||||
return s
|
||||
end
|
||||
|
|
@ -37,6 +40,8 @@ end
|
|||
thumbnail = "", -- Optional; defines the thumbnail shown in the guide.
|
||||
size = <vector>, -- The amount of space taken up by this plot, in grid squares.
|
||||
schematic = <schem> or {},
|
||||
ground_level = 5, -- The ground level relative to the bottom of the schematic, used by spawners to determine where to place the schematic relative to the player spawning it.
|
||||
constructors = {n = {5}, w = {5}, s = {5}, e = {5}}, -- The offset from the bottom of the plot at which to place each constructor (to allow for constructors at different Y levels). Defaults to one per horizontally adjoining grid space at y=`ground_level`.
|
||||
recipe = { -- 3x3 crafting recipe for this structure, as a flat list of ItemStack strings.
|
||||
"stone 60", "wood 10", "stone 60",
|
||||
"cobble 25", "diamond 3", "cobble 25",
|
||||
|
|
@ -69,5 +74,29 @@ function ns.register_plot(def)
|
|||
warn "A plot was registered without a name!"
|
||||
return
|
||||
end
|
||||
if not def.size then
|
||||
def.size = vector.new(1,1,1)
|
||||
end
|
||||
if not def.ground_level then def.ground_level = 5 end
|
||||
for i, x in ipairs(def.recipe) do
|
||||
if x ~= "" and not x:find ":" then
|
||||
def.recipe[i] = "red_glazed_terracotta:"..x
|
||||
end
|
||||
end
|
||||
if def.constructors then
|
||||
local x = def.constructors
|
||||
local out = {}
|
||||
else
|
||||
local out = {}
|
||||
for x = 1, def.size.x do
|
||||
out[#out +1] = vector.new((x -1) *15, def.ground_level,-7)
|
||||
out[#out +1] = vector.new((x -1) *15, def.ground_level, 7)
|
||||
end
|
||||
for y = 1, def.size.z do
|
||||
out[#out +1] = vector.new(-7, def.ground_level, (y -1) *15)
|
||||
out[#out +1] = vector.new( 7, def.ground_level, (y -1) *15)
|
||||
end
|
||||
def.constructors = out
|
||||
end
|
||||
ns.plots[def.name] = def
|
||||
end
|
||||
|
|
@ -1,5 +1,12 @@
|
|||
local ns = rgt_towns
|
||||
|
||||
ns.directions = {
|
||||
[0] = vector.new(0,0,1),
|
||||
vector.new(1,0,0),
|
||||
vector.new(0,0,-1),
|
||||
vector.new(-1,0,0)
|
||||
}
|
||||
|
||||
minetest.register_craftitem(":rgt_towns:spawner", {
|
||||
description = "Blank Plot Spawner (you shouldn't have this)",
|
||||
stack_max = 1,
|
||||
|
|
@ -15,17 +22,97 @@ minetest.register_craftitem(":rgt_towns:spawner", {
|
|||
on_place = function(s, p, pt)
|
||||
local m = s:get_meta()
|
||||
local owner = m:get("owner")
|
||||
if owner and owner ~= p:get_player_name() then
|
||||
if not owner then
|
||||
owner = p:get_player_name()
|
||||
elseif owner ~= p:get_player_name() then
|
||||
warn("<"..p:get_player_name().."> tried to use <"..owner..">'s '"..(m:get("description") or "Blank Plot Spawner").."' (and failed).")
|
||||
return
|
||||
end
|
||||
local plot = m:get("plot")
|
||||
if plot then
|
||||
ns.place_plot(plot, p:get_pos())
|
||||
local def = ns.plots[plot]
|
||||
local pos = p:get_pos():round()
|
||||
pos.y = pos.y -ns.plots[plot].ground_level
|
||||
local q = math.random()
|
||||
ns.create_grid(owner..":town"..q, pos:offset(0,def.size.y *7.5,0))
|
||||
if not ns.place_plot(owner..":town"..q, vector.zero(), plot, owner) then
|
||||
ns.delete_grid(owner..":town"..q)
|
||||
end
|
||||
else
|
||||
warn("<"..p:get_player_name().."> tried to use an uninitialized plot spawner.")
|
||||
end
|
||||
return ItemStack()
|
||||
end
|
||||
})
|
||||
|
||||
--[[
|
||||
+Z
|
||||
^
|
||||
|
|
||||
|
|
||||
|
|
||||
-X <----------+----------> +X
|
||||
|
|
||||
|
|
||||
|
|
||||
v
|
||||
-Z
|
||||
]]
|
||||
|
||||
function ns.check_recipe(inv, plot)
|
||||
local recipe = ns.plots[plot].recipe
|
||||
print(dump(recipe))
|
||||
for i = 1, 9 do
|
||||
print("Evaluating: "..inv:get_stack("main", i):to_string().." vs. "..ItemStack(recipe[i]):to_string())
|
||||
if inv:get_stack("main", i) ~= ItemStack(recipe[i]) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
minetest.register_node(":rgt_towns:constructor", {
|
||||
tiles = {"[fill:16x16:#8af"},
|
||||
on_construct = function(pos)
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
inv:set_size("main", 9)
|
||||
end,
|
||||
on_rightclick = function(pos, node, p, s)
|
||||
ns.show_constructor_interface(pos, p)
|
||||
end,
|
||||
on_punch = function(pos, node)
|
||||
local m = minetest.get_meta(pos)
|
||||
local grid = m:get_string("grid")
|
||||
local gpos = vector.from_string(m:get_string("build_pos"))
|
||||
local plot = m:get("plot") or "empty_plot"
|
||||
|
||||
local inv = m:get_inventory()
|
||||
|
||||
if not ns.check_recipe(inv, plot) then
|
||||
return
|
||||
end
|
||||
|
||||
ns.place_plot(grid, gpos, plot, tostring(node.param2 *90))
|
||||
|
||||
minetest.remove_node(pos)
|
||||
end
|
||||
})
|
||||
|
||||
function ns.show_constructor_interface(pos, p)
|
||||
local name = p:get_player_name()
|
||||
local fs = "\
|
||||
formspec_version[10]\
|
||||
size[12,10]\
|
||||
list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;1,1;3.5,3.5]\
|
||||
list[player:"..name..";main;1,5;10,4]\
|
||||
"
|
||||
minetest.show_formspec(name, "constructor:"..pos.x..","..pos.y..","..pos.z, fs)
|
||||
end
|
||||
|
||||
minetest.register_on_player_receive_fields(function(p, form, data)
|
||||
if form:sub(1, string.len("constructor:")) == "constructor:" then
|
||||
local x, y, z = form:match "constructor:(%d+),(%d+),(%d+)"
|
||||
if not (x and y and z) then return end
|
||||
|
||||
end
|
||||
end)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,288 @@
|
|||
local ns = rgt_towns
|
||||
local db = minetest.get_mod_storage()
|
||||
|
||||
function ns.get_grid()
|
||||
ns.grids = minetest.parse_json(db:get("grids") or "{}")
|
||||
|
||||
-- Calculates the Euclidean distance squared between two points (avoids sqrt for efficiency)
|
||||
local function distance_squared(p1, p2)
|
||||
local dx = p1.x - p2.x
|
||||
local dy = p1.y - p2.y
|
||||
local dz = p1.z - p2.z
|
||||
return dx * dx + dy * dy + dz * dz
|
||||
end
|
||||
|
||||
-- Returns the point in the AABB farthest from the given point
|
||||
-- aabb: table with {min = {x, y, z}, max = {x, y, z}}
|
||||
-- point: table with {x, y, z}
|
||||
-- Returns: table {x, y, z} representing the farthest corner
|
||||
local function get_farthest_point_in_aabb(aabb, point)
|
||||
-- Ensure input validity
|
||||
if not aabb or not aabb.min or not aabb.max or not point then
|
||||
error("Invalid input: aabb or point is missing required fields")
|
||||
end
|
||||
|
||||
-- List all eight corners of the AABB
|
||||
local corners = {
|
||||
{x = aabb.min.x, y = aabb.min.y, z = aabb.min.z},
|
||||
{x = aabb.min.x, y = aabb.min.y, z = aabb.max.z},
|
||||
{x = aabb.min.x, y = aabb.max.y, z = aabb.min.z},
|
||||
{x = aabb.min.x, y = aabb.max.y, z = aabb.max.z},
|
||||
{x = aabb.max.x, y = aabb.min.y, z = aabb.min.z},
|
||||
{x = aabb.max.x, y = aabb.min.y, z = aabb.max.z},
|
||||
{x = aabb.max.x, y = aabb.max.y, z = aabb.min.z},
|
||||
{x = aabb.max.x, y = aabb.max.y, z = aabb.max.z},
|
||||
}
|
||||
|
||||
local max_dist_sq = -1
|
||||
local farthest_point = nil
|
||||
|
||||
-- Iterate through corners to find the one with maximum distance
|
||||
for _, corner in ipairs(corners) do
|
||||
local dist_sq = distance_squared(point, corner)
|
||||
if dist_sq > max_dist_sq then
|
||||
max_dist_sq = dist_sq
|
||||
farthest_point = corner
|
||||
end
|
||||
end
|
||||
|
||||
return farthest_point
|
||||
end
|
||||
|
||||
function aabb_intersects_sphere(aabb, center, radius)
|
||||
-- Ensure input validity
|
||||
if not aabb or not aabb.min or not aabb.max or not center or not radius or radius < 0 then
|
||||
error("Invalid input: aabb, center, or radius is missing or invalid")
|
||||
end
|
||||
|
||||
-- Find the closest point in the AABB to the sphere's center
|
||||
local closest = {
|
||||
x = math.max(aabb.min.x, math.min(center.x, aabb.max.x)),
|
||||
y = math.max(aabb.min.y, math.min(center.y, aabb.max.y)),
|
||||
z = math.max(aabb.min.z, math.min(center.z, aabb.max.z))
|
||||
}
|
||||
|
||||
-- Check if the closest point is within the sphere's radius
|
||||
local dist_squared = distance_squared(center, closest)
|
||||
return dist_squared <= radius * radius
|
||||
end
|
||||
|
||||
AABB = setmetatable({
|
||||
intersects = function(a, b, c)
|
||||
if c then
|
||||
return a.min.x < c.x and a.max.x > b.x and
|
||||
a.min.y < c.y and a.max.y > b.y and
|
||||
a.min.z < c.z and a.max.z > b.z
|
||||
end
|
||||
return a.min.x < b.max.x and a.max.x > b.min.x and
|
||||
a.min.y < b.max.y and a.max.y > b.min.y and
|
||||
a.min.z < b.max.z and a.max.z > b.min.z
|
||||
end,
|
||||
intersects_2d = function(a, b, c)
|
||||
if c then
|
||||
return a.min.x < c.x and a.max.x > b.x and
|
||||
a.min.z < c.z and a.max.z > b.z
|
||||
end
|
||||
return a.min.x < b.max.x and a.max.x > b.min.x and
|
||||
a.min.z < b.max.z and a.max.z > b.min.z
|
||||
end
|
||||
}, {
|
||||
__call = function(_, min, max)
|
||||
min, max = vector.sort(min, max)
|
||||
return setmetatable({
|
||||
min = min,
|
||||
max = max
|
||||
}, {__index = AABB})
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
local repl = {
|
||||
-- ["default:dirt"] = "adrift:dirt",
|
||||
-- ["default:wood"] = "adrift:water"
|
||||
}
|
||||
|
||||
function ns.place_plot(plot, pos)
|
||||
minetest.place_schematic(pos, ns.plots[plot].schematic, nil, repl, true, {place_center_x = true, place_center_z = true})
|
||||
local function get_intersecting_grid_cells(aabb, origin, cell_size)
|
||||
-- Ensure input validity
|
||||
if not aabb or not aabb.min or not aabb.max or not origin or not cell_size then
|
||||
error("Invalid input: aabb, origin, or cell_size is missing required fields")
|
||||
end
|
||||
if cell_size.x <= 0 or cell_size.y <= 0 or cell_size.z <= 0 then
|
||||
error("Invalid input: cell_size components must be positive")
|
||||
end
|
||||
|
||||
-- Convert AABB min and max to cell coordinates (relative to origin)
|
||||
local min_cell = {
|
||||
x = math.floor((aabb.min.x - origin.x) / cell_size.x),
|
||||
y = math.floor((aabb.min.y - origin.y) / cell_size.y),
|
||||
z = math.floor((aabb.min.z - origin.z) / cell_size.z)
|
||||
}
|
||||
local max_cell = {
|
||||
x = math.floor((aabb.max.x - origin.x) / cell_size.x),
|
||||
y = math.floor((aabb.max.y - origin.y) / cell_size.y),
|
||||
z = math.floor((aabb.max.z - origin.z) / cell_size.z)
|
||||
}
|
||||
|
||||
-- Collect all cell positions in the range [min_cell, max_cell]
|
||||
local cells = {}
|
||||
for x = min_cell.x, max_cell.x do
|
||||
for y = min_cell.y, max_cell.y do
|
||||
for z = min_cell.z, max_cell.z do
|
||||
table.insert(cells, {x = x, y = y, z = z})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return cells
|
||||
end
|
||||
|
||||
local function mag_floor(a)
|
||||
return a < 0 and math.ceil(a) or math.floor(a)
|
||||
end
|
||||
local function mag_ceil(a)
|
||||
return a < 0 and math.floor(a) or math.ceil(a)
|
||||
end
|
||||
|
||||
function ns.can_build_plot(box, grid)
|
||||
local w = box.max.x -box.min.x
|
||||
local h = box.max.y -box.min.y
|
||||
local l = box.max.z -box.min.z
|
||||
for name, grid2 in pairs(ns.grids) do
|
||||
local i = aabb_intersects_sphere(box, grid2.origin, grid2.radius)
|
||||
if name == grid or i then
|
||||
ns.add_cube(box.min, box.max, {color = "#fff"})
|
||||
-- Translate box to grid2 local space and compute candidate cell range
|
||||
local min = vector.floor((box.min -grid2.origin) /15)
|
||||
local max = vector.ceil((box.max -grid2.origin) /15)
|
||||
|
||||
ns.add_cube(min *15 +grid2.origin, max *15 +grid2.origin)
|
||||
|
||||
if grid2.type == "3d" then
|
||||
-- TODO: implement
|
||||
else
|
||||
for x = min.x, max.x do
|
||||
for z = min.z, max.z do
|
||||
ns.add_point(vector.new(x,0,z) *15 +grid2.origin)
|
||||
-- print("Box: "..dump(box).."; min: "..min:to_string().."; max: "..max:to_string())
|
||||
local plot = db:get("plot:"..name.."_"..x.."_0_"..z)
|
||||
if plot then
|
||||
plot = minetest.parse_json(plot)
|
||||
if box:intersects_2d(plot.bb_min, plot.bb_max) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--[[
|
||||
Grid types:
|
||||
* "2d": A two-dimensional grid. Building multiple plots within the same horizontal space is not allowed, but plots may change Y level in any way.
|
||||
* "3d": A three-dimensional grid. Multiple plots can be constructed within the same column, but changes in Y level must be quantized to the size of the grid cells.
|
||||
* "2d_staggered": A staggered 2d grid. This is the same as "2d" except that the center of a given cell's edge will correspond to the top and bottom edges of the two neighboring cells.
|
||||
]]
|
||||
function ns.create_grid(grid, pos, type)
|
||||
ns.grids[grid] = {
|
||||
type = type,
|
||||
origin = pos,
|
||||
radius = 0
|
||||
}
|
||||
db:set_string("grids", minetest.write_json(ns.grids))
|
||||
end
|
||||
|
||||
function ns.delete_grid(grid)
|
||||
ns.grids[grid] = nil
|
||||
db:set_string("grids", minetest.write_json(ns.grids))
|
||||
end
|
||||
|
||||
--- @param grid: Grid in which to place the plot.
|
||||
--- @param pos: Position within `grid` at which to build the plot.
|
||||
function ns.place_plot(grid, pos, plot, owner, rot)
|
||||
local gpos
|
||||
if ns.grids[grid] then
|
||||
gpos = ns.grids[grid].origin
|
||||
else
|
||||
warn("Failed to place a plot on unknown grid `"..grid.."`.")
|
||||
return
|
||||
end
|
||||
local def = ns.plots[plot]
|
||||
local dst = (pos *15 +gpos):offset(-7,-def.size.y *7.5,-7)
|
||||
local box = AABB(dst, dst +def.size *15)
|
||||
|
||||
if not ns.can_build_plot(box, grid) then
|
||||
return
|
||||
end
|
||||
|
||||
db:set_string("plot:"..grid.."_"..pos.x.."_0_"..pos.z, minetest.write_json {
|
||||
bb_min = box.min,
|
||||
bb_max = box.max,
|
||||
owner = owner,
|
||||
type = plot,
|
||||
})
|
||||
|
||||
local g = ns.grids[grid]
|
||||
-- Expand the town's radius to include the new plot, if necessary.
|
||||
g.radius = math.max(g.radius, vector.distance(get_farthest_point_in_aabb(box, g.origin), g.origin))
|
||||
|
||||
local def = ns.plots[plot]
|
||||
|
||||
minetest.place_schematic(dst, def.schematic, rot, repl, true, {})
|
||||
|
||||
local p, gp, m
|
||||
|
||||
-- Place constructors along Z axis
|
||||
for x = 0, def.size.x -1 do
|
||||
gp = pos:offset(x, 0,-1)
|
||||
p = dst:offset(x *15 +7, def.ground_level, 0)
|
||||
if db:contains("plot:"..grid.."_"..gp.x.."_"..gp.y.."_"..gp.z) then
|
||||
-- Remove adjacent constructors, and don't place new ones.
|
||||
minetest.remove_node(p:offset(0,0,-1))
|
||||
else
|
||||
minetest.set_node(p, {name = "rgt_towns:constructor"})
|
||||
m = minetest.get_meta(p)
|
||||
m:set_string("grid", grid)
|
||||
m:set_string("build_pos", gp:to_string())
|
||||
end
|
||||
|
||||
gp = pos:offset(x, 0, 1)
|
||||
p = dst:offset(x *15 +7, def.ground_level, def.size.z *15 -1)
|
||||
if db:contains("plot:"..grid.."_"..gp.x.."_"..gp.y.."_"..gp.z) then
|
||||
minetest.remove_node(p:offset(0,0,1))
|
||||
else
|
||||
minetest.set_node(p, {name = "rgt_towns:constructor"})
|
||||
m = minetest.get_meta(p)
|
||||
m:set_string("grid", grid)
|
||||
m:set_string("build_pos", gp:to_string())
|
||||
end
|
||||
end
|
||||
|
||||
-- Place constructors along X axis
|
||||
for z = 0, def.size.z -1 do
|
||||
gp = pos:offset(-1, 0, z)
|
||||
p = dst:offset(0, def.ground_level, z *15 +7)
|
||||
if db:contains("plot:"..grid.."_"..gp.x.."_"..gp.y.."_"..gp.z) then
|
||||
minetest.remove_node(p:offset(-1,0,0))
|
||||
else
|
||||
minetest.set_node(p, {name = "rgt_towns:constructor"})
|
||||
m = minetest.get_meta(p)
|
||||
m:set_string("grid", grid)
|
||||
m:set_string("build_pos", pos:offset(-1, 0, z):to_string())
|
||||
end
|
||||
|
||||
gp = pos:offset(1, 0, z)
|
||||
p = dst:offset(def.size.x *15 -1, def.ground_level, z *15 +7)
|
||||
if db:contains("plot:"..grid.."_"..gp.x.."_"..gp.y.."_"..gp.z) then
|
||||
minetest.remove_node(p:offset(1,0,0))
|
||||
else
|
||||
minetest.set_node(p, {name = "rgt_towns:constructor"})
|
||||
m = minetest.get_meta(p)
|
||||
m:set_string("grid", grid)
|
||||
m:set_string("build_pos", pos:offset(1, 0, z):to_string())
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
|
@ -1,17 +1,35 @@
|
|||
local ns = rgt_towns
|
||||
|
||||
function ns.add_line(from, to)
|
||||
function ns.add_line(from, to, args)
|
||||
local dist = vector.distance(from, to)
|
||||
local vel = dist
|
||||
return minetest.add_particlespawner {
|
||||
local ps = {
|
||||
pos = from,
|
||||
vel = vector.direction(from, to) *vel,
|
||||
amount = dist *vel,
|
||||
time = 0,
|
||||
exptime = dist /vel,
|
||||
texture = "[fill:1x1:0,0:#35f",
|
||||
texture = "[fill:1x1:0,0:"..(args.color or "#35f"),
|
||||
glow = 14,
|
||||
}
|
||||
if args.attach then
|
||||
ps.attached = args.attach
|
||||
end
|
||||
return minetest.add_particlespawner(ps)
|
||||
end
|
||||
|
||||
function ns.add_point(point, args)
|
||||
minetest.add_particlespawner {
|
||||
pos = point,
|
||||
velocity = {
|
||||
min = vector.new(-1,-1,-1),
|
||||
max = vector.new(1,1,1)
|
||||
},
|
||||
texture = args and args.color or "[fill:1x1:0,0:#faa",
|
||||
time = 10,
|
||||
amount = 50,
|
||||
size = 5
|
||||
}
|
||||
end
|
||||
|
||||
--[[
|
||||
|
|
@ -32,7 +50,8 @@ end
|
|||
|
||||
7 8
|
||||
]]
|
||||
function ns.add_cube(from, to)
|
||||
function ns.add_cube(from, to, args)
|
||||
if not args then args = {} end
|
||||
local p1 = from
|
||||
local p2 = vector.new(to.x, from.y, from.z)
|
||||
local p3 = vector.new(from.x, to.y, from.z)
|
||||
|
|
@ -42,24 +61,24 @@ function ns.add_cube(from, to)
|
|||
local p7 = vector.new(from.x, to.y, to.z)
|
||||
local p8 = to
|
||||
return {
|
||||
ns.add_line(p1, p2),
|
||||
ns.add_line(p1, p3),
|
||||
ns.add_line(p1, p4),
|
||||
ns.add_line(p1, p2, args),
|
||||
ns.add_line(p1, p3, args),
|
||||
ns.add_line(p1, p4, args),
|
||||
|
||||
ns.add_line(p4, p6),
|
||||
ns.add_line(p4, p7),
|
||||
ns.add_line(p4, p6, args),
|
||||
ns.add_line(p4, p7, args),
|
||||
|
||||
ns.add_line(p2, p6),
|
||||
ns.add_line(p2, p6, args),
|
||||
|
||||
|
||||
ns.add_line(p8, p5),
|
||||
ns.add_line(p8, p6),
|
||||
ns.add_line(p8, p7),
|
||||
ns.add_line(p8, p5, args),
|
||||
ns.add_line(p8, p6, args),
|
||||
ns.add_line(p8, p7, args),
|
||||
|
||||
ns.add_line(p5, p2),
|
||||
ns.add_line(p5, p3),
|
||||
ns.add_line(p5, p2, args),
|
||||
ns.add_line(p5, p3, args),
|
||||
|
||||
ns.add_line(p7, p3),
|
||||
ns.add_line(p7, p3, args),
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ function ns.place_workspace(name, pos)
|
|||
pos = pos:round()
|
||||
ws = {
|
||||
pos = pos,
|
||||
size = vector.new(1,4,1)
|
||||
size = vector.new(1,2,1)
|
||||
}
|
||||
db:set_string("workspace:"..name, minetest.serialize(ws))
|
||||
minetest.add_entity(ns.get_workspace_center(pos, ws.size), "rgt_towns_editor:workspace", name)
|
||||
|
|
|
|||
|
|
@ -2,17 +2,20 @@ rgt_towns.main = {}
|
|||
ns = rgt_towns.main
|
||||
|
||||
ns.plots = {
|
||||
|
||||
"empty_plot"
|
||||
}
|
||||
|
||||
rgt_towns.register_spawner{
|
||||
plot = "covered_wagon",
|
||||
label = "Town Charter"
|
||||
rgt_towns.register_spawner {
|
||||
plot = "empty_plot",
|
||||
label = "Town Charter",
|
||||
on_spawn = function(p)
|
||||
|
||||
end
|
||||
}
|
||||
|
||||
minetest.register_chatcommand("charter", {
|
||||
func = function(name, args)
|
||||
minetest.get_player_by_name(name):get_inventory():add_item("main", rgt_towns.create_spawner("covered_wagon"))
|
||||
minetest.get_player_by_name(name):get_inventory():add_item("main", rgt_towns.create_spawner("empty_plot", name))
|
||||
end
|
||||
})
|
||||
|
||||
|
|
@ -21,5 +24,20 @@ rgt_towns.register_plot{
|
|||
label = "Covered Wagon",
|
||||
description = "Hello world",
|
||||
schematic = minetest.get_modpath(minetest.get_current_modname()).."/schems/covered_wagon.mts",
|
||||
recipe = {},
|
||||
can_build = ns.plots
|
||||
}
|
||||
|
||||
rgt_towns.register_plot{
|
||||
name = "empty_plot",
|
||||
label = "Empty Plot",
|
||||
description = "Hello world",
|
||||
schematic = minetest.get_modpath(minetest.get_current_modname()).."/schems/empty_plot.mts",
|
||||
recipe = {
|
||||
"", "", "",
|
||||
"dirt_grass 1", "dirt_grass 1", "dirt_grass 1",
|
||||
"dirt 1", "dirt 1", "dirt 1",
|
||||
},
|
||||
ground_level = 5,
|
||||
can_build = ns.plots
|
||||
}
|
||||
|
|
|
|||
BIN
mods/rgt_towns/rgt_towns_main/schems/empty_plot.mts
Normal file
BIN
mods/rgt_towns/rgt_towns_main/schems/empty_plot.mts
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue