forked from Mineclonia/Mineclonia
Make portals branch fully playable (reduce y scale to 2), fix critical bugs
This commit is contained in:
parent
60fc57d878
commit
ef395af838
|
@ -16,7 +16,7 @@ local sub = vector.subtract
|
||||||
local W_MIN, W_MAX = 4, 23
|
local W_MIN, W_MAX = 4, 23
|
||||||
local H_MIN, H_MAX = 5, 23
|
local H_MIN, H_MAX = 5, 23
|
||||||
local N_MIN, N_MAX = 6, (W_MAX-2) * (H_MAX-2)
|
local N_MIN, N_MAX = 6, (W_MAX-2) * (H_MAX-2)
|
||||||
local TRAVEL_X, TRAVEL_Y, TRAVEL_Z = 8, 10, 8
|
local TRAVEL_X, TRAVEL_Y, TRAVEL_Z = 8, 2, 8
|
||||||
local LIM_MIN, LIM_MAX = mcl_vars.mapgen_edge_min, mcl_vars.mapgen_edge_max
|
local LIM_MIN, LIM_MAX = mcl_vars.mapgen_edge_min, mcl_vars.mapgen_edge_max
|
||||||
local PLAYER_COOLOFF, MOB_COOLOFF = 3, 14 -- for this many seconds they won't teleported again
|
local PLAYER_COOLOFF, MOB_COOLOFF = 3, 14 -- for this many seconds they won't teleported again
|
||||||
local TOUCH_CHATTER_TIME = 1 -- prevent multiple teleportation attempts caused by multiple portal touches, for this number of seconds
|
local TOUCH_CHATTER_TIME = 1 -- prevent multiple teleportation attempts caused by multiple portal touches, for this number of seconds
|
||||||
|
@ -49,9 +49,21 @@ local queue = {}
|
||||||
local chunks = {}
|
local chunks = {}
|
||||||
|
|
||||||
local storage = minetest.get_mod_storage()
|
local storage = minetest.get_mod_storage()
|
||||||
local exits = minetest.deserialize(storage:get_string("nether_exits") or "return {}") or {}
|
local exits = {}
|
||||||
|
local keys = minetest.deserialize(storage:get_string("nether_exits_keys") or "return {}") or {}
|
||||||
|
for _, key in pairs(keys) do
|
||||||
|
local n = tonumber(key)
|
||||||
|
if n then
|
||||||
|
exits[key] = minetest.deserialize(storage:get_string("nether_exits_"..key) or "return {}") or {}
|
||||||
|
end
|
||||||
|
end
|
||||||
minetest.register_on_shutdown(function()
|
minetest.register_on_shutdown(function()
|
||||||
storage:set_string("nether_exits", minetest.serialize(exits))
|
local keys={}
|
||||||
|
for key, data in pairs(exits) do
|
||||||
|
storage:set_string("nether_exits_"..tostring(key), minetest.serialize(data))
|
||||||
|
keys[#keys+1] = key
|
||||||
|
end
|
||||||
|
storage:set_string("nether_exits_keys", minetest.serialize(keys))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
mcl_portals.get_node = function(pos)
|
mcl_portals.get_node = function(pos)
|
||||||
|
@ -101,7 +113,7 @@ local function add_exit(p)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
e[#e] = p
|
e[#e+1] = p
|
||||||
log("action", "[mcl_portals] Exit added at " .. pos_to_string(p))
|
log("action", "[mcl_portals] Exit added at " .. pos_to_string(p))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -114,9 +126,8 @@ local function remove_exit(p)
|
||||||
local p = {x = x, y = y, z = z}
|
local p = {x = x, y = y, z = z}
|
||||||
local e = exits[k]
|
local e = exits[k]
|
||||||
if e then
|
if e then
|
||||||
for i = 1, #e do
|
for i, t in pairs(e) do
|
||||||
local t = e[i]
|
if t and t.x == x and t.y == y and t.z == z then
|
||||||
if t.x == p.x and t.y == p.y and t.z == p.z then
|
|
||||||
e[i] = nil
|
e[i] = nil
|
||||||
log("action", "[mcl_portals] Nether portal removed from " .. pos_to_string(p))
|
log("action", "[mcl_portals] Nether portal removed from " .. pos_to_string(p))
|
||||||
return
|
return
|
||||||
|
@ -142,7 +153,7 @@ local function find_exit(p, dx, dy, dz)
|
||||||
if e then
|
if e then
|
||||||
for i = 1, #e do
|
for i = 1, #e do
|
||||||
local t0 = e[i]
|
local t0 = e[i]
|
||||||
local d0 = dist(p, t)
|
local d0 = dist(p, t0)
|
||||||
if not d or d>d0 then
|
if not d or d>d0 then
|
||||||
d = d0
|
d = d0
|
||||||
t = t0
|
t = t0
|
||||||
|
@ -289,7 +300,7 @@ local function light_frame(x1, y1, z1, x2, y2, z2, name)
|
||||||
set_node(pos, {name = OBSIDIAN})
|
set_node(pos, {name = OBSIDIAN})
|
||||||
else
|
else
|
||||||
set_node(pos, {name = PORTAL, param2 = orientation})
|
set_node(pos, {name = PORTAL, param2 = orientation})
|
||||||
add_exit(pos)
|
add_exit({x=pos.x, y=pos.y-1, z=pos.z})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -308,20 +319,35 @@ function build_nether_portal(pos, width, height, orientation, name)
|
||||||
for x = pos.x - orientation, pos.x + orientation + (width - 1) * (1 - orientation), 1 + orientation do
|
for x = pos.x - orientation, pos.x + orientation + (width - 1) * (1 - orientation), 1 + orientation do
|
||||||
for z = pos.z - 1 + orientation, pos.z + 1 - orientation + (width - 1) * orientation, 2 - orientation do
|
for z = pos.z - 1 + orientation, pos.z + 1 - orientation + (width - 1) * orientation, 2 - orientation do
|
||||||
local pp = {x = x, y = pos.y - 1, z = z}
|
local pp = {x = x, y = pos.y - 1, z = z}
|
||||||
|
local pp_1 = {x = x, y = pos.y - 2, z = z}
|
||||||
local nn = get_node(pp).name
|
local nn = get_node(pp).name
|
||||||
log("warning", "[mcl_portals] pos=" .. pos_to_string(pp) .. " nn=" .. nn .. " name=" .. name .. " width=" .. tostring(width) .. " height=" .. tostring(height).." orientation=" ..tostring(orientation).." for obsidian platform:")
|
local nn_1 = get_node(pp_1).name
|
||||||
if not registered_nodes[nn].is_ground_content and not is_protected(pp, name) then
|
log("warning", "[mcl_portals] pos=" .. pos_to_string(pp) .. " nn=" .. nn .. " name=" .. name .. " width=" .. tostring(width) .. " height=" .. tostring(height).." orientation=" ..tostring(orientation).." gc="..tostring(registered_nodes[nn].is_ground_content) .." for obsidian platform:")
|
||||||
|
if ((nn=="air" and nn_1 == "air") or not registered_nodes[nn].is_ground_content) and not is_protected(pp, name) then
|
||||||
set_node(pp, {name = OBSIDIAN})
|
set_node(pp, {name = OBSIDIAN})
|
||||||
minetest.log("warning", "set!")
|
minetest.log("warning", "set!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
log("action", "[mcl_portal] Destination Nether portal generated at "..pos_to_string(pos).."!")
|
log("action", "[mcl_portals] Destination Nether portal generated at "..pos_to_string(pos).."!")
|
||||||
|
|
||||||
return pos
|
return pos
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function mcl_portals.spawn_nether_portal(pos, rot, pr, name)
|
||||||
|
if not pos then return end
|
||||||
|
local o = 0
|
||||||
|
if rot then
|
||||||
|
if rot == "270" or rot=="90" then
|
||||||
|
o = 1
|
||||||
|
elseif rot == "random" then
|
||||||
|
o = random(0,1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
build_nether_portal(pos, nil, nil, o, name)
|
||||||
|
end
|
||||||
|
|
||||||
-- Teleportation cooloff for some seconds, to prevent back-and-forth teleportation
|
-- Teleportation cooloff for some seconds, to prevent back-and-forth teleportation
|
||||||
local function stop_teleport_cooloff(o)
|
local function stop_teleport_cooloff(o)
|
||||||
cooloff[o] = nil
|
cooloff[o] = nil
|
||||||
|
@ -342,7 +368,6 @@ local function finalize_teleport(obj, exit)
|
||||||
|
|
||||||
local objpos = obj:get_pos()
|
local objpos = obj:get_pos()
|
||||||
if not objpos then return end
|
if not objpos then return end
|
||||||
log("warning", "[mcl_portal] 3")
|
|
||||||
|
|
||||||
local is_player = obj:is_player()
|
local is_player = obj:is_player()
|
||||||
local name
|
local name
|
||||||
|
@ -365,9 +390,9 @@ local function finalize_teleport(obj, exit)
|
||||||
if is_player then
|
if is_player then
|
||||||
mcl_worlds.dimension_change(obj, dim)
|
mcl_worlds.dimension_change(obj, dim)
|
||||||
minetest.sound_play("mcl_portals_teleport", {pos=exit, gain=0.5, max_hear_distance = 16}, true)
|
minetest.sound_play("mcl_portals_teleport", {pos=exit, gain=0.5, max_hear_distance = 16}, true)
|
||||||
log("action", "[mcl_portal] player "..name.." teleported to Nether portal at "..pos_to_string(exit)..".")
|
log("action", "[mcl_portals] player "..name.." teleported to Nether portal at "..pos_to_string(exit)..".")
|
||||||
else
|
else
|
||||||
log("action", "[mcl_portal] entity teleported to Nether portal at "..pos_to_string(exit)..".")
|
log("action", "[mcl_portals] entity teleported to Nether portal at "..pos_to_string(exit)..".")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -390,8 +415,10 @@ local function create_portal_2(pos1, name, obj)
|
||||||
chunks[cn] = nil
|
chunks[cn] = nil
|
||||||
if queue[cn] then
|
if queue[cn] then
|
||||||
for next_obj, _ in pairs(queue[cn]) do
|
for next_obj, _ in pairs(queue[cn]) do
|
||||||
|
if next_obj ~= obj then
|
||||||
finalize_teleport(next_obj, exit)
|
finalize_teleport(next_obj, exit)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
queue[cn] = nil
|
queue[cn] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -403,7 +430,7 @@ local function ecb_scan_area(blockpos, action, calls_remaining, param)
|
||||||
-- loop in a spiral around pos
|
-- loop in a spiral around pos
|
||||||
local cs, x, z, dx, dz, p0x, p0z, p1x, p1y, p1z, p2x, p2y, p2z = mcl_vars.chunk_size_in_nodes, 0, 0, 0, -1, pos.x, pos.z, pos1.x, pos1.y, pos1.z, pos2.x, pos2.y, pos2.z
|
local cs, x, z, dx, dz, p0x, p0z, p1x, p1y, p1z, p2x, p2y, p2z = mcl_vars.chunk_size_in_nodes, 0, 0, 0, -1, pos.x, pos.z, pos1.x, pos1.y, pos1.z, pos2.x, pos2.y, pos2.z
|
||||||
local i_max = (cs*2-1) * (cs*2-1)
|
local i_max = (cs*2-1) * (cs*2-1)
|
||||||
log("action", "[mcl_portal] Area for destination Nether portal emerged! We about to iterate " .. tostring(i_max) .. " positions of spiral around "..pos_to_string(pos))
|
log("action", "[mcl_portals] Area for destination Nether portal emerged! We about to iterate " .. tostring(i_max) .. " positions of spiral around "..pos_to_string(pos))
|
||||||
|
|
||||||
local backup_pos, bnc = nil, 0 -- 'better than nothing'
|
local backup_pos, bnc = nil, 0 -- 'better than nothing'
|
||||||
|
|
||||||
|
@ -412,12 +439,12 @@ local function ecb_scan_area(blockpos, action, calls_remaining, param)
|
||||||
for i = 1, i_max do
|
for i = 1, i_max do
|
||||||
local px, pz = p0x + x, p0z + z
|
local px, pz = p0x + x, p0z + z
|
||||||
if ((i%100) == 1) then
|
if ((i%100) == 1) then
|
||||||
log("action", "[mcl_portal] i=" ..tostring(i) .." px=" .. tostring(px) .." pz=" .. tostring(pz) .. " x:"..tostring(p1x) .."-"..tostring(p2x) .. " z:"..tostring(p1z) .."-"..tostring(p2z))
|
log("action", "[mcl_portals] i=" ..tostring(i) .." px=" .. tostring(px) .." pz=" .. tostring(pz) .. " x:"..tostring(p1x) .."-"..tostring(p2x) .. " z:"..tostring(p1z) .."-"..tostring(p2z))
|
||||||
end
|
end
|
||||||
if px >= p1x and pz >= p1z and px <= p2x and pz <= p2z then
|
if px >= p1x and pz >= p1z and px <= p2x and pz <= p2z then
|
||||||
p1.x, p2.x, p1.z, p2.z = px, px, pz, pz
|
p1.x, p2.x, p1.z, p2.z = px, px, pz, pz
|
||||||
local nodes = find_nodes_in_area_under_air(p1, p2, {"group:building_block"})
|
local nodes = find_nodes_in_area_under_air(p1, p2, {"group:building_block"})
|
||||||
log("action", "[mcl_portal] check " .. pos_to_string(p1) .. "-" .. pos_to_string(p2) .. ": " .. tostring(nodes and #nodes))
|
log("action", "[mcl_portals] check " .. pos_to_string(p1) .. "-" .. pos_to_string(p2) .. ": " .. tostring(nodes and #nodes))
|
||||||
if nodes and #nodes > 0 then
|
if nodes and #nodes > 0 then
|
||||||
for j = 1, #nodes do
|
for j = 1, #nodes do
|
||||||
local node = nodes[j]
|
local node = nodes[j]
|
||||||
|
@ -432,14 +459,14 @@ local function ecb_scan_area(blockpos, action, calls_remaining, param)
|
||||||
node2.z = node2.z + 2
|
node2.z = node2.z + 2
|
||||||
nodes_j = find_nodes_in_area(node, node2, {"air"})
|
nodes_j = find_nodes_in_area(node, node2, {"air"})
|
||||||
if #nodes_j == 36 then
|
if #nodes_j == 36 then
|
||||||
log("action", "[mcl_portal] found space at pos "..pos_to_string(node).." - creating a portal")
|
log("action", "[mcl_portals] found space at pos "..pos_to_string(node).." - creating a portal")
|
||||||
create_portal_2(node, name, obj)
|
create_portal_2(node, name, obj)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
elseif nc > bnc then
|
elseif nc > bnc then
|
||||||
bnc = nc
|
bnc = nc
|
||||||
backup_pos = {x = node.x, y = node.y-2, z = node.z}
|
backup_pos = {x = node.x, y = node.y-2, z = node.z}
|
||||||
log("action", "[mcl_portal] set backup pos "..pos_to_string(backup_pos).." with "..tostring(nc).." air node(s)")
|
log("action", "[mcl_portals] set backup pos "..pos_to_string(backup_pos).." with "..tostring(nc).." air node(s)")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -453,11 +480,11 @@ local function ecb_scan_area(blockpos, action, calls_remaining, param)
|
||||||
px, pz = p0x + x, p0z + z
|
px, pz = p0x + x, p0z + z
|
||||||
end
|
end
|
||||||
if backup_pos then -- several nodes of air might be better than lava lake, right?
|
if backup_pos then -- several nodes of air might be better than lava lake, right?
|
||||||
log("action", "[mcl_portal] using backup pos "..pos_to_string(backup_pos).." to create a portal")
|
log("action", "[mcl_portals] using backup pos "..pos_to_string(backup_pos).." to create a portal")
|
||||||
create_portal_2(backup_pos, name, obj)
|
create_portal_2(backup_pos, name, obj)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
log("action", "[mcl_portal] found no space, reverting to target pos "..pos_to_string(pos).." - creating a portal")
|
log("action", "[mcl_portals] found no space, reverting to target pos "..pos_to_string(pos).." - creating a portal")
|
||||||
create_portal_2(pos, name, obj)
|
create_portal_2(pos, name, obj)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -469,24 +496,24 @@ local function ecb_scan_area_2(blockpos, action, calls_remaining, param)
|
||||||
if nodes then
|
if nodes then
|
||||||
local nc = #nodes
|
local nc = #nodes
|
||||||
if nc > 0 then
|
if nc > 0 then
|
||||||
log("action", "[mcl_portal] Area for destination Nether portal emerged! Found " .. tostring(nc) .. " nodes under the air around "..pos_to_string(pos))
|
log("action", "[mcl_portals] Area for destination Nether portal emerged! Found " .. tostring(nc) .. " nodes under the air around "..pos_to_string(pos))
|
||||||
for i=1,nc do
|
for i=1,nc do
|
||||||
local node = nodes[i]
|
local node = nodes[i]
|
||||||
local node1 = {x=node.x, y=node.y+2, z=node.z }
|
local node1 = {x=node.x, y=node.y+1, z=node.z }
|
||||||
local node2 = {x=node.x+2, y=node.y+3, z=node.z+2}
|
local node2 = {x=node.x+2, y=node.y+3, z=node.z+2}
|
||||||
local nodes2 = find_nodes_in_area(node1, node2, {"air"})
|
local nodes2 = find_nodes_in_area(node1, node2, {"air"})
|
||||||
if nodes2 then
|
if nodes2 then
|
||||||
local nc2 = #nodes2
|
local nc2 = #nodes2
|
||||||
log("action", "[mcl_portal] nc2=" .. tostring(nc2))
|
log("action", "[mcl_portals] nc2=" .. tostring(nc2))
|
||||||
if nc2 == 18 and not is_area_protected(node, node2, name) then
|
if nc2 == 27 and not is_area_protected(node, node2, name) then
|
||||||
local distance0 = dist(pos, node)
|
local distance0 = dist(pos, node)
|
||||||
if distance0 < 2 then
|
if distance0 < 2 then
|
||||||
log("action", "[mcl_portal] found space at pos "..pos_to_string(node).." - creating a portal")
|
log("action", "[mcl_portals] found space at pos "..pos_to_string(node).." - creating a portal")
|
||||||
create_portal_2(node, name, obj)
|
create_portal_2(node, name, obj)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if not distance or distance0 < distance then
|
if not distance or distance0 < distance then
|
||||||
log("action", "[mcl_portal] found distance "..tostring(distance0).." at pos "..pos_to_string(node))
|
log("action", "[mcl_portals] found distance "..tostring(distance0).." at pos "..pos_to_string(node))
|
||||||
distance = distance0
|
distance = distance0
|
||||||
pos0 = {x=node.x, y=node.y, z=node.z}
|
pos0 = {x=node.x, y=node.y, z=node.z}
|
||||||
end
|
end
|
||||||
|
@ -496,11 +523,11 @@ local function ecb_scan_area_2(blockpos, action, calls_remaining, param)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if distance then -- several nodes of air might be better than lava lake, right?
|
if distance then -- several nodes of air might be better than lava lake, right?
|
||||||
log("action", "[mcl_portal] using backup pos "..pos_to_string(pos0).." to create a portal")
|
log("action", "[mcl_portals] using backup pos "..pos_to_string(pos0).." to create a portal")
|
||||||
create_portal_2(pos0, name, obj)
|
create_portal_2(pos0, name, obj)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
log("action", "[mcl_portal] found no space, reverting to target pos "..pos_to_string(pos).." - creating a portal")
|
log("action", "[mcl_portals] found no space, reverting to target pos "..pos_to_string(pos).." - creating a portal")
|
||||||
create_portal_2(pos, name, obj)
|
create_portal_2(pos, name, obj)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -786,7 +813,7 @@ minetest.override_item(OBSIDIAN, {
|
||||||
mcl_portals.light_nether_portal({x = x, y = y - 1, z = z}) or mcl_portals.light_nether_portal({x = x, y = y + 1, z = z}) or
|
mcl_portals.light_nether_portal({x = x, y = y - 1, z = z}) or mcl_portals.light_nether_portal({x = x, y = y + 1, z = z}) or
|
||||||
mcl_portals.light_nether_portal({x = x, y = y, z = z - 1}) or mcl_portals.light_nether_portal({x = x, y = y, z = z + 1})
|
mcl_portals.light_nether_portal({x = x, y = y, z = z - 1}) or mcl_portals.light_nether_portal({x = x, y = y, z = z + 1})
|
||||||
if portals_placed then
|
if portals_placed then
|
||||||
log("action", "[mcl_portal] Nether portal activated at "..pos_to_string({x=x,y=y,z=z})..".")
|
log("action", "[mcl_portals] Nether portal activated at "..pos_to_string({x=x,y=y,z=z})..".")
|
||||||
if minetest.get_modpath("doc") then
|
if minetest.get_modpath("doc") then
|
||||||
doc.mark_entry_as_revealed(user:get_player_name(), "nodes", PORTAL)
|
doc.mark_entry_as_revealed(user:get_player_name(), "nodes", PORTAL)
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ local function add_chunk(pos)
|
||||||
end
|
end
|
||||||
prev = d
|
prev = d
|
||||||
end
|
end
|
||||||
chunks[#chunks] = {n, n}
|
chunks[#chunks+1] = {n, n}
|
||||||
end
|
end
|
||||||
function mcl_mapgen_core.is_generated(pos)
|
function mcl_mapgen_core.is_generated(pos)
|
||||||
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
|
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
|
||||||
|
|
|
@ -534,7 +534,7 @@ end
|
||||||
|
|
||||||
-- Debug command
|
-- Debug command
|
||||||
minetest.register_chatcommand("spawnstruct", {
|
minetest.register_chatcommand("spawnstruct", {
|
||||||
params = "desert_temple | desert_well | igloo | witch_hut | boulder | ice_spike_small | ice_spike_large | fossil | end_exit_portal | end_portal_shrine | dungeon",
|
params = "desert_temple | desert_well | igloo | witch_hut | boulder | ice_spike_small | ice_spike_large | fossil | end_exit_portal | end_portal_shrine | nether_portal | dungeon",
|
||||||
description = S("Generate a pre-defined structure near your position."),
|
description = S("Generate a pre-defined structure near your position."),
|
||||||
privs = {debug = true},
|
privs = {debug = true},
|
||||||
func = function(name, param)
|
func = function(name, param)
|
||||||
|
@ -570,6 +570,8 @@ minetest.register_chatcommand("spawnstruct", {
|
||||||
mcl_structures.generate_end_portal_shrine(pos, rot, pr)
|
mcl_structures.generate_end_portal_shrine(pos, rot, pr)
|
||||||
elseif param == "dungeon" and mcl_dungeons and mcl_dungeons.spawn_dungeon then
|
elseif param == "dungeon" and mcl_dungeons and mcl_dungeons.spawn_dungeon then
|
||||||
mcl_dungeons.spawn_dungeon(pos, rot, pr)
|
mcl_dungeons.spawn_dungeon(pos, rot, pr)
|
||||||
|
elseif param == "nether_portal" and mcl_portals and mcl_portals.spawn_nether_portal then
|
||||||
|
mcl_portals.spawn_nether_portal(pos, rot, pr, name)
|
||||||
elseif param == "" then
|
elseif param == "" then
|
||||||
message = S("Error: No structure type given. Please use “/spawnstruct <type>”.")
|
message = S("Error: No structure type given. Please use “/spawnstruct <type>”.")
|
||||||
errord = true
|
errord = true
|
||||||
|
|
Loading…
Reference in New Issue