forked from Mirrorlandia_minetest/minetest
Weather support
This commit is contained in:
parent
e65d8ad655
commit
3aedfac968
@ -14,11 +14,11 @@ minetest.register_entity("__builtin:falling_node", {
|
|||||||
visual_size = {x=0.667, y=0.667},
|
visual_size = {x=0.667, y=0.667},
|
||||||
},
|
},
|
||||||
|
|
||||||
nodename = "",
|
node = {},
|
||||||
|
|
||||||
set_node = function(self, nodename)
|
set_node = function(self, node)
|
||||||
self.nodename = nodename
|
self.node = node
|
||||||
local stack = ItemStack(nodename)
|
local stack = ItemStack(node.name)
|
||||||
local itemtable = stack:to_table()
|
local itemtable = stack:to_table()
|
||||||
local itemname = nil
|
local itemname = nil
|
||||||
if itemtable then
|
if itemtable then
|
||||||
@ -32,20 +32,19 @@ minetest.register_entity("__builtin:falling_node", {
|
|||||||
end
|
end
|
||||||
prop = {
|
prop = {
|
||||||
is_visible = true,
|
is_visible = true,
|
||||||
textures = {nodename},
|
textures = {node.name},
|
||||||
}
|
}
|
||||||
self.object:set_properties(prop)
|
self.object:set_properties(prop)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
get_staticdata = function(self)
|
get_staticdata = function(self)
|
||||||
return self.nodename
|
return self.node.name
|
||||||
end,
|
end,
|
||||||
|
|
||||||
on_activate = function(self, staticdata)
|
on_activate = function(self, staticdata)
|
||||||
self.nodename = staticdata
|
|
||||||
self.object:set_armor_groups({immortal=1})
|
self.object:set_armor_groups({immortal=1})
|
||||||
--self.object:setacceleration({x=0, y=-10, z=0})
|
--self.object:setacceleration({x=0, y=-10, z=0})
|
||||||
self:set_node(self.nodename)
|
self:set_node({name=staticdata})
|
||||||
end,
|
end,
|
||||||
|
|
||||||
on_step = function(self, dtime)
|
on_step = function(self, dtime)
|
||||||
@ -57,8 +56,10 @@ minetest.register_entity("__builtin:falling_node", {
|
|||||||
local bcn = minetest.get_node(bcp)
|
local bcn = minetest.get_node(bcp)
|
||||||
-- Note: walkable is in the node definition, not in item groups
|
-- Note: walkable is in the node definition, not in item groups
|
||||||
if minetest.registered_nodes[bcn.name] and
|
if minetest.registered_nodes[bcn.name] and
|
||||||
minetest.registered_nodes[bcn.name].walkable then
|
minetest.registered_nodes[bcn.name].walkable or
|
||||||
if minetest.registered_nodes[bcn.name].buildable_to then
|
(minetest.get_node_group(self.node.name, "float") ~= 0 and minetest.registered_nodes[bcn.name].liquidtype ~= "none")
|
||||||
|
then
|
||||||
|
if minetest.registered_nodes[bcn.name].buildable_to and (minetest.get_node_group(self.node.name, "float") == 0 or minetest.registered_nodes[bcn.name].liquidtype == "none") then
|
||||||
minetest.remove_node(bcp)
|
minetest.remove_node(bcp)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -83,7 +84,7 @@ minetest.register_entity("__builtin:falling_node", {
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- Create node and remove entity
|
-- Create node and remove entity
|
||||||
minetest.add_node(np, {name=self.nodename})
|
minetest.add_node(np, self.node)
|
||||||
self.object:remove()
|
self.object:remove()
|
||||||
nodeupdate(np)
|
nodeupdate(np)
|
||||||
else
|
else
|
||||||
@ -92,9 +93,9 @@ minetest.register_entity("__builtin:falling_node", {
|
|||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
function spawn_falling_node(p, nodename)
|
function spawn_falling_node(p, node)
|
||||||
obj = minetest.add_entity(p, "__builtin:falling_node")
|
obj = minetest.add_entity(p, "__builtin:falling_node")
|
||||||
obj:get_luaentity():set_node(nodename)
|
obj:get_luaentity():set_node(node)
|
||||||
end
|
end
|
||||||
|
|
||||||
function drop_attached_node(p)
|
function drop_attached_node(p)
|
||||||
@ -150,13 +151,14 @@ function nodeupdate_single(p, delay)
|
|||||||
n_bottom = minetest.get_node(p_bottom)
|
n_bottom = minetest.get_node(p_bottom)
|
||||||
-- Note: walkable is in the node definition, not in item groups
|
-- Note: walkable is in the node definition, not in item groups
|
||||||
if minetest.registered_nodes[n_bottom.name] and
|
if minetest.registered_nodes[n_bottom.name] and
|
||||||
|
(minetest.get_node_group(n.name, "float") == 0 or minetest.registered_nodes[n_bottom.name].liquidtype == "none") and
|
||||||
(not minetest.registered_nodes[n_bottom.name].walkable or
|
(not minetest.registered_nodes[n_bottom.name].walkable or
|
||||||
minetest.registered_nodes[n_bottom.name].buildable_to) then
|
minetest.registered_nodes[n_bottom.name].buildable_to) then
|
||||||
if delay then
|
if delay then
|
||||||
minetest.after(0.1, nodeupdate_single, {x=p.x, y=p.y, z=p.z}, false)
|
minetest.after(0.1, nodeupdate_single, {x=p.x, y=p.y, z=p.z}, false)
|
||||||
else
|
else
|
||||||
minetest.remove_node(p)
|
minetest.remove_node(p)
|
||||||
spawn_falling_node(p, n.name)
|
spawn_falling_node(p, n)
|
||||||
nodeupdate(p)
|
nodeupdate(p)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -170,7 +172,7 @@ function nodeupdate_single(p, delay)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function nodeupdate(p)
|
function nodeupdate(p, delay)
|
||||||
-- Round p to prevent falling entities to get stuck
|
-- Round p to prevent falling entities to get stuck
|
||||||
p.x = math.floor(p.x+0.5)
|
p.x = math.floor(p.x+0.5)
|
||||||
p.y = math.floor(p.y+0.5)
|
p.y = math.floor(p.y+0.5)
|
||||||
@ -179,7 +181,7 @@ function nodeupdate(p)
|
|||||||
for x = -1,1 do
|
for x = -1,1 do
|
||||||
for y = -1,1 do
|
for y = -1,1 do
|
||||||
for z = -1,1 do
|
for z = -1,1 do
|
||||||
nodeupdate_single({x=p.x+x, y=p.y+y, z=p.z+z}, not (x==0 and y==0 and z==0))
|
nodeupdate_single({x=p.x+x, y=p.y+y, z=p.z+z}, delay or not (x==0 and y==0 and z==0))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -322,6 +322,8 @@ param2 is reserved for the engine when any of these are used:
|
|||||||
facedir modulo 4 = axisdir
|
facedir modulo 4 = axisdir
|
||||||
0 = y+ 1 = z+ 2 = z- 3 = x+ 4 = x- 5 = y-
|
0 = y+ 1 = z+ 2 = z- 3 = x+ 4 = x- 5 = y-
|
||||||
facedir's two less significant bits are rotation around the axis
|
facedir's two less significant bits are rotation around the axis
|
||||||
|
paramtype2 == "leveled"
|
||||||
|
^ The drawn node level is read from param2, like flowingliquid
|
||||||
|
|
||||||
Nodes can also contain extra data. See "Node Metadata".
|
Nodes can also contain extra data. See "Node Metadata".
|
||||||
|
|
||||||
@ -353,7 +355,7 @@ Node selection boxes are defined using "node boxes"
|
|||||||
|
|
||||||
The "nodebox" node drawtype allows defining visual of nodes consisting of
|
The "nodebox" node drawtype allows defining visual of nodes consisting of
|
||||||
arbitrary number of boxes. It allows defining stuff like stairs. Only the
|
arbitrary number of boxes. It allows defining stuff like stairs. Only the
|
||||||
"fixed" box type is supported for these.
|
"fixed" and "leveled" box type is supported for these.
|
||||||
^ Please note that this is still experimental, and may be incompatibly
|
^ Please note that this is still experimental, and may be incompatibly
|
||||||
changed in the future.
|
changed in the future.
|
||||||
|
|
||||||
@ -381,6 +383,8 @@ A box is defined as:
|
|||||||
A box of a regular node would look like:
|
A box of a regular node would look like:
|
||||||
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||||
|
|
||||||
|
type = "leveled" is same as "fixed", but y2 will be automaticaly setted to level from param2
|
||||||
|
|
||||||
Ore types
|
Ore types
|
||||||
---------------
|
---------------
|
||||||
These tell in what manner the ore is generated.
|
These tell in what manner the ore is generated.
|
||||||
@ -1258,6 +1262,18 @@ minetest.find_path(pos1,pos2,searchdistance,max_jump,max_drop,algorithm)
|
|||||||
^ algorithm: A*_noprefetch(default), A*, Dijkstra
|
^ algorithm: A*_noprefetch(default), A*, Dijkstra
|
||||||
minetest.spawn_tree (pos, {treedef})
|
minetest.spawn_tree (pos, {treedef})
|
||||||
^ spawns L-System tree at given pos with definition in treedef table
|
^ spawns L-System tree at given pos with definition in treedef table
|
||||||
|
minetest.transforming_liquid_add(pos)
|
||||||
|
^ add node to liquid update queue
|
||||||
|
minetest.get_node_max_level(pos)
|
||||||
|
^ get max available level for leveled node
|
||||||
|
minetest.get_node_level(pos)
|
||||||
|
^ get level of leveled node (water, snow)
|
||||||
|
minetest.add_node_level(pos, level)
|
||||||
|
^ increase level of leveled node by level, default level = 1, if totallevel > maxlevel returns rest (total-max). can be negative for decreasing
|
||||||
|
minetest.get_heat(pos)
|
||||||
|
^ heat at pos
|
||||||
|
minetest.get_humidity(pos)
|
||||||
|
^ humidity at pos
|
||||||
|
|
||||||
Inventory:
|
Inventory:
|
||||||
minetest.get_inventory(location) -> InvRef
|
minetest.get_inventory(location) -> InvRef
|
||||||
@ -1965,6 +1981,8 @@ Node definition (register_node)
|
|||||||
liquid_alternative_source = "", -- Source version of flowing liquid
|
liquid_alternative_source = "", -- Source version of flowing liquid
|
||||||
liquid_viscosity = 0, -- Higher viscosity = slower flow (max. 7)
|
liquid_viscosity = 0, -- Higher viscosity = slower flow (max. 7)
|
||||||
liquid_renewable = true, -- Can new liquid source be created by placing
|
liquid_renewable = true, -- Can new liquid source be created by placing
|
||||||
|
freezemelt = "", -- water for snow/ice, ice/snow for water
|
||||||
|
leveled = 0, -- Block contain level in param2. value - default level, used for snow. Dont forget use "leveled" type nodebox
|
||||||
liquid_range = 8, -- number of flowing nodes arround source (max. 8)
|
liquid_range = 8, -- number of flowing nodes arround source (max. 8)
|
||||||
drowning = true, -- Player will drown in these
|
drowning = true, -- Player will drown in these
|
||||||
two or more sources nearly?
|
two or more sources nearly?
|
||||||
|
@ -107,6 +107,8 @@
|
|||||||
#liquid_fast_flood = 1
|
#liquid_fast_flood = 1
|
||||||
# Underground water and lava springs, its infnity sources if liquid_finite enabled
|
# Underground water and lava springs, its infnity sources if liquid_finite enabled
|
||||||
#underground_springs = 1
|
#underground_springs = 1
|
||||||
|
# Enable weather (cold-hot, water freeze-melt). use only with liquid_finite=1
|
||||||
|
#weather = false
|
||||||
# Enable nice leaves; disable for speed
|
# Enable nice leaves; disable for speed
|
||||||
#new_style_leaves = true
|
#new_style_leaves = true
|
||||||
# Enable smooth lighting with simple ambient occlusion;
|
# Enable smooth lighting with simple ambient occlusion;
|
||||||
@ -268,7 +270,9 @@
|
|||||||
# Interval of sending time of day to clients
|
# Interval of sending time of day to clients
|
||||||
#time_send_interval = 5
|
#time_send_interval = 5
|
||||||
# Length of day/night cycle. 72=20min, 360=4min, 1=24hour, 0=day/night/whatever stays unchanged
|
# Length of day/night cycle. 72=20min, 360=4min, 1=24hour, 0=day/night/whatever stays unchanged
|
||||||
#time_speed = 96
|
#time_speed = 72
|
||||||
|
# Length of year in days for seasons change. With default time_speed 365 days = 5 real days for year. 30 days = 10 real hours
|
||||||
|
#year_days = 30
|
||||||
#server_unload_unused_data_timeout = 29
|
#server_unload_unused_data_timeout = 29
|
||||||
# Interval of saving important changes in the world
|
# Interval of saving important changes in the world
|
||||||
#server_map_save_interval = 5.3
|
#server_map_save_interval = 5.3
|
||||||
|
@ -28,6 +28,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "treegen.h" // For treegen::make_tree
|
#include "treegen.h" // For treegen::make_tree
|
||||||
#include "main.h" // for g_settings
|
#include "main.h" // for g_settings
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
|
#include "cpp_api/scriptapi.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||||
|
|
||||||
@ -166,86 +168,220 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LiquidFlowABM : public ActiveBlockModifier
|
class LiquidFlowABM : public ActiveBlockModifier {
|
||||||
{
|
private:
|
||||||
private:
|
std::set<std::string> contents;
|
||||||
std::set<std::string> contents;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LiquidFlowABM(ServerEnvironment *env, INodeDefManager *nodemgr)
|
LiquidFlowABM(ServerEnvironment *env, INodeDefManager *nodemgr) {
|
||||||
{
|
std::set<content_t> liquids;
|
||||||
std::set<content_t> liquids;
|
nodemgr->getIds("group:liquid", liquids);
|
||||||
nodemgr->getIds("group:liquid", liquids);
|
for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++)
|
||||||
for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++)
|
contents.insert(nodemgr->get(*k).liquid_alternative_flowing);
|
||||||
contents.insert(nodemgr->get(*k).liquid_alternative_flowing);
|
}
|
||||||
|
virtual std::set<std::string> getTriggerContents() {
|
||||||
}
|
return contents;
|
||||||
virtual std::set<std::string> getTriggerContents()
|
}
|
||||||
{
|
virtual float getTriggerInterval()
|
||||||
return contents;
|
{ return 10.0; }
|
||||||
}
|
virtual u32 getTriggerChance()
|
||||||
virtual float getTriggerInterval()
|
{ return 10; }
|
||||||
{ return 10.0; }
|
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) {
|
||||||
virtual u32 getTriggerChance()
|
ServerMap *map = &env->getServerMap();
|
||||||
{ return 10; }
|
if (map->transforming_liquid_size() > 500)
|
||||||
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n)
|
return;
|
||||||
{
|
map->transforming_liquid_add(p);
|
||||||
ServerMap *map = &env->getServerMap();
|
}
|
||||||
if (map->transforming_liquid_size() > 500)
|
|
||||||
return;
|
|
||||||
map->transforming_liquid_add(p);
|
|
||||||
//if ((*map).m_transforming_liquid.size() < 500) (*map).m_transforming_liquid.push_back(p);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class LiquidDropABM : public ActiveBlockModifier
|
class LiquidDropABM : public ActiveBlockModifier {
|
||||||
{
|
private:
|
||||||
private:
|
std::set<std::string> contents;
|
||||||
std::set<std::string> contents;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LiquidDropABM(ServerEnvironment *env, INodeDefManager *nodemgr)
|
LiquidDropABM(ServerEnvironment *env, INodeDefManager *nodemgr) {
|
||||||
{
|
std::set<content_t> liquids;
|
||||||
std::set<content_t> liquids;
|
nodemgr->getIds("group:liquid", liquids);
|
||||||
nodemgr->getIds("group:liquid", liquids);
|
for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++)
|
||||||
for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++)
|
contents.insert(nodemgr->get(*k).liquid_alternative_source);
|
||||||
contents.insert(nodemgr->get(*k).liquid_alternative_source);
|
}
|
||||||
}
|
virtual std::set<std::string> getTriggerContents()
|
||||||
virtual std::set<std::string> getTriggerContents()
|
{ return contents; }
|
||||||
{ return contents; }
|
virtual std::set<std::string> getRequiredNeighbors() {
|
||||||
virtual std::set<std::string> getRequiredNeighbors()
|
std::set<std::string> neighbors;
|
||||||
{
|
neighbors.insert("mapgen_air");
|
||||||
std::set<std::string> neighbors;
|
return neighbors;
|
||||||
neighbors.insert("mapgen_air");
|
}
|
||||||
return neighbors;
|
virtual float getTriggerInterval()
|
||||||
}
|
{ return 20.0; }
|
||||||
virtual float getTriggerInterval()
|
virtual u32 getTriggerChance()
|
||||||
{ return 20.0; }
|
{ return 10; }
|
||||||
virtual u32 getTriggerChance()
|
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) {
|
||||||
{ return 10; }
|
ServerMap *map = &env->getServerMap();
|
||||||
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n)
|
if (map->transforming_liquid_size() > 500)
|
||||||
{
|
return;
|
||||||
ServerMap *map = &env->getServerMap();
|
if ( map->getNodeNoEx(p - v3s16(0, 1, 0 )).getContent() != CONTENT_AIR // below
|
||||||
if (map->transforming_liquid_size() > 500)
|
&& map->getNodeNoEx(p - v3s16(1, 0, 0 )).getContent() != CONTENT_AIR // right
|
||||||
return;
|
&& map->getNodeNoEx(p - v3s16(-1, 0, 0 )).getContent() != CONTENT_AIR // left
|
||||||
if ( map->getNodeNoEx(p - v3s16(0, 1, 0 )).getContent() != CONTENT_AIR // below
|
&& map->getNodeNoEx(p - v3s16(0, 0, 1 )).getContent() != CONTENT_AIR // back
|
||||||
&& map->getNodeNoEx(p - v3s16(1, 0, 0 )).getContent() != CONTENT_AIR // right
|
&& map->getNodeNoEx(p - v3s16(0, 0, -1)).getContent() != CONTENT_AIR // front
|
||||||
&& map->getNodeNoEx(p - v3s16(-1, 0, 0 )).getContent() != CONTENT_AIR // left
|
)
|
||||||
&& map->getNodeNoEx(p - v3s16(0, 0, 1 )).getContent() != CONTENT_AIR // back
|
return;
|
||||||
&& map->getNodeNoEx(p - v3s16(0, 0, -1)).getContent() != CONTENT_AIR // front
|
map->transforming_liquid_add(p);
|
||||||
)
|
}
|
||||||
return;
|
|
||||||
map->transforming_liquid_add(p);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef)
|
class LiquidFreeze : public ActiveBlockModifier {
|
||||||
{
|
public:
|
||||||
|
LiquidFreeze(ServerEnvironment *env, INodeDefManager *nodemgr) { }
|
||||||
|
virtual std::set<std::string> getTriggerContents() {
|
||||||
|
std::set<std::string> s;
|
||||||
|
s.insert("group:freezes");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
virtual std::set<std::string> getRequiredNeighbors() {
|
||||||
|
std::set<std::string> s;
|
||||||
|
s.insert("mapgen_air");
|
||||||
|
s.insert("group:melts");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
virtual float getTriggerInterval()
|
||||||
|
{ return 10.0; }
|
||||||
|
virtual u32 getTriggerChance()
|
||||||
|
{ return 20; }
|
||||||
|
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) {
|
||||||
|
ServerMap *map = &env->getServerMap();
|
||||||
|
INodeDefManager *ndef = env->getGameDef()->ndef();
|
||||||
|
|
||||||
|
float heat = map->getHeat(env, p);
|
||||||
|
//heater = rare
|
||||||
|
if (heat <= -1 && (heat <= -50 || ((myrand_range(-50, heat)) <= -30))) {
|
||||||
|
content_t c_self = n.getContent();
|
||||||
|
// making freeze not annoying, do not freeze random blocks in center of ocean
|
||||||
|
// todo: any block not water (dont freeze _source near _flowing)
|
||||||
|
content_t c;
|
||||||
|
bool allow = heat < -40;
|
||||||
|
// todo: make for(...)
|
||||||
|
if (!allow) {
|
||||||
|
c = map->getNodeNoEx(p - v3s16(0, 1, 0 )).getContent(); // below
|
||||||
|
if (c == CONTENT_AIR || c == CONTENT_IGNORE)
|
||||||
|
return; // do not freeze when falling
|
||||||
|
if (c != c_self && c != CONTENT_IGNORE) allow = 1;
|
||||||
|
if (!allow) {
|
||||||
|
c = map->getNodeNoEx(p - v3s16(1, 0, 0 )).getContent(); // right
|
||||||
|
if (c != c_self && c != CONTENT_IGNORE) allow = 1;
|
||||||
|
if (!allow) {
|
||||||
|
c = map->getNodeNoEx(p - v3s16(-1, 0, 0 )).getContent(); // left
|
||||||
|
if (c != c_self && c != CONTENT_IGNORE) allow = 1;
|
||||||
|
if (!allow) {
|
||||||
|
c = map->getNodeNoEx(p - v3s16(0, 0, 1 )).getContent(); // back
|
||||||
|
if (c != c_self && c != CONTENT_IGNORE) allow = 1;
|
||||||
|
if (!allow) {
|
||||||
|
c = map->getNodeNoEx(p - v3s16(0, 0, -1)).getContent(); // front
|
||||||
|
if (c != c_self && c != CONTENT_IGNORE) allow = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allow) {
|
||||||
|
n.setContent(ndef->getId(ndef->get(n).freezemelt));
|
||||||
|
map->addNodeWithEvent(p, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LiquidMeltWeather : public ActiveBlockModifier {
|
||||||
|
public:
|
||||||
|
LiquidMeltWeather(ServerEnvironment *env, INodeDefManager *nodemgr) { }
|
||||||
|
virtual std::set<std::string> getTriggerContents() {
|
||||||
|
std::set<std::string> s;
|
||||||
|
s.insert("group:melts");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
virtual std::set<std::string> getRequiredNeighbors() {
|
||||||
|
std::set<std::string> s;
|
||||||
|
s.insert("mapgen_air");
|
||||||
|
s.insert("group:freezes");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
virtual float getTriggerInterval()
|
||||||
|
{ return 10.0; }
|
||||||
|
virtual u32 getTriggerChance()
|
||||||
|
{ return 20; }
|
||||||
|
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) {
|
||||||
|
ServerMap *map = &env->getServerMap();
|
||||||
|
INodeDefManager *ndef = env->getGameDef()->ndef();
|
||||||
|
|
||||||
|
float heat = map->getHeat(env, p);
|
||||||
|
if (heat >= 1 && (heat >= 40 || ((myrand_range(heat, 40)) >= 20))) {
|
||||||
|
n.setContent(ndef->getId(ndef->get(n).freezemelt));
|
||||||
|
if (!n.getLevel(ndef))
|
||||||
|
n.addLevel(ndef);
|
||||||
|
map->addNodeWithEvent(p, n);
|
||||||
|
env->getScriptIface()->node_falling_update(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LiquidMeltHot : public ActiveBlockModifier {
|
||||||
|
public:
|
||||||
|
LiquidMeltHot(ServerEnvironment *env, INodeDefManager *nodemgr) { }
|
||||||
|
virtual std::set<std::string> getTriggerContents() {
|
||||||
|
std::set<std::string> s;
|
||||||
|
s.insert("group:melts");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
virtual std::set<std::string> getRequiredNeighbors() {
|
||||||
|
std::set<std::string> s;
|
||||||
|
s.insert("group:igniter");
|
||||||
|
s.insert("group:hot");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
virtual float getTriggerInterval()
|
||||||
|
{ return 2.0; }
|
||||||
|
virtual u32 getTriggerChance()
|
||||||
|
{ return 4; }
|
||||||
|
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) {
|
||||||
|
ServerMap *map = &env->getServerMap();
|
||||||
|
INodeDefManager *ndef = env->getGameDef()->ndef();
|
||||||
|
n.setContent(ndef->getId(ndef->get(n).freezemelt));
|
||||||
|
if (!n.getLevel(ndef))
|
||||||
|
n.addLevel(ndef);
|
||||||
|
map->addNodeWithEvent(p, n);
|
||||||
|
env->getScriptIface()->node_falling_update(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LiquidMeltAround : public LiquidMeltHot {
|
||||||
|
public:
|
||||||
|
LiquidMeltAround(ServerEnvironment *env, INodeDefManager *nodemgr)
|
||||||
|
: LiquidMeltHot(env, nodemgr) { }
|
||||||
|
virtual std::set<std::string> getRequiredNeighbors() {
|
||||||
|
std::set<std::string> s;
|
||||||
|
s.insert("group:melt_around");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
virtual float getTriggerInterval()
|
||||||
|
{ return 40.0; }
|
||||||
|
virtual u32 getTriggerChance()
|
||||||
|
{ return 60; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef) {
|
||||||
env->addActiveBlockModifier(new GrowGrassABM());
|
env->addActiveBlockModifier(new GrowGrassABM());
|
||||||
env->addActiveBlockModifier(new RemoveGrassABM());
|
env->addActiveBlockModifier(new RemoveGrassABM());
|
||||||
env->addActiveBlockModifier(new MakeTreesFromSaplingsABM(env, nodedef));
|
env->addActiveBlockModifier(new MakeTreesFromSaplingsABM(env, nodedef));
|
||||||
if (g_settings->getBool("liquid_finite")) {
|
if (g_settings->getBool("liquid_finite")) {
|
||||||
env->addActiveBlockModifier(new LiquidFlowABM(env, nodedef));
|
env->addActiveBlockModifier(new LiquidFlowABM(env, nodedef));
|
||||||
env->addActiveBlockModifier(new LiquidDropABM(env, nodedef));
|
env->addActiveBlockModifier(new LiquidDropABM(env, nodedef));
|
||||||
|
env->addActiveBlockModifier(new LiquidMeltHot(env, nodedef));
|
||||||
|
env->addActiveBlockModifier(new LiquidMeltAround(env, nodedef));
|
||||||
|
if (g_settings->getBool("weather")) {
|
||||||
|
env->addActiveBlockModifier(new LiquidFreeze(env, nodedef));
|
||||||
|
env->addActiveBlockModifier(new LiquidMeltWeather(env, nodedef));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,6 +178,7 @@ void set_default_settings(Settings *settings)
|
|||||||
settings->setDefault("max_clearobjects_extra_loaded_blocks", "4096");
|
settings->setDefault("max_clearobjects_extra_loaded_blocks", "4096");
|
||||||
settings->setDefault("time_send_interval", "5");
|
settings->setDefault("time_send_interval", "5");
|
||||||
settings->setDefault("time_speed", "72");
|
settings->setDefault("time_speed", "72");
|
||||||
|
settings->setDefault("year_days", "30");
|
||||||
settings->setDefault("server_unload_unused_data_timeout", "29");
|
settings->setDefault("server_unload_unused_data_timeout", "29");
|
||||||
settings->setDefault("server_map_save_interval", "5.3");
|
settings->setDefault("server_map_save_interval", "5.3");
|
||||||
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
|
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
|
||||||
@ -214,6 +215,7 @@ void set_default_settings(Settings *settings)
|
|||||||
settings->setDefault("liquid_relax", "2");
|
settings->setDefault("liquid_relax", "2");
|
||||||
settings->setDefault("liquid_fast_flood", "1");
|
settings->setDefault("liquid_fast_flood", "1");
|
||||||
settings->setDefault("underground_springs", "1");
|
settings->setDefault("underground_springs", "1");
|
||||||
|
settings->setDefault("weather", "false");
|
||||||
|
|
||||||
//mapgen stuff
|
//mapgen stuff
|
||||||
settings->setDefault("mg_name", "v6");
|
settings->setDefault("mg_name", "v6");
|
||||||
|
@ -488,6 +488,14 @@ void *EmergeThread::Thread() {
|
|||||||
if (block)
|
if (block)
|
||||||
modified_blocks[p] = block;
|
modified_blocks[p] = block;
|
||||||
|
|
||||||
|
// Update weather data in mapblock
|
||||||
|
for(std::map<v3s16, MapBlock *>::iterator
|
||||||
|
i = modified_blocks.begin();
|
||||||
|
i != modified_blocks.end(); ++i) {
|
||||||
|
map->getHeat(m_server->m_env, MAP_BLOCKSIZE*i->first ,i->second);
|
||||||
|
map->getHumidity(m_server->m_env, MAP_BLOCKSIZE*i->first, i->second);
|
||||||
|
}
|
||||||
|
|
||||||
// Set the modified blocks unsent for all the clients
|
// Set the modified blocks unsent for all the clients
|
||||||
for (std::map<u16, RemoteClient*>::iterator
|
for (std::map<u16, RemoteClient*>::iterator
|
||||||
i = m_server->m_clients.begin();
|
i = m_server->m_clients.begin();
|
||||||
|
@ -303,6 +303,7 @@ public:
|
|||||||
//check if there's a line of sight between two positions
|
//check if there's a line of sight between two positions
|
||||||
bool line_of_sight(v3f pos1, v3f pos2, float stepsize=1.0);
|
bool line_of_sight(v3f pos1, v3f pos2, float stepsize=1.0);
|
||||||
|
|
||||||
|
u32 getGameTime() { return m_game_time; }
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2455,6 +2455,7 @@ void the_game(
|
|||||||
camera.step(dtime);
|
camera.step(dtime);
|
||||||
|
|
||||||
v3f player_position = player->getPosition();
|
v3f player_position = player->getPosition();
|
||||||
|
v3s16 pos_i = floatToInt(player_position, BS);
|
||||||
v3f camera_position = camera.getPosition();
|
v3f camera_position = camera.getPosition();
|
||||||
v3f camera_direction = camera.getDirection();
|
v3f camera_direction = camera.getDirection();
|
||||||
f32 camera_fov = camera.getFovMax();
|
f32 camera_fov = camera.getFovMax();
|
||||||
@ -3034,7 +3035,9 @@ void the_game(
|
|||||||
<<", "<<(player_position.Y/BS)
|
<<", "<<(player_position.Y/BS)
|
||||||
<<", "<<(player_position.Z/BS)
|
<<", "<<(player_position.Z/BS)
|
||||||
<<") (yaw="<<(wrapDegrees_0_360(camera_yaw))
|
<<") (yaw="<<(wrapDegrees_0_360(camera_yaw))
|
||||||
<<") (seed = "<<((unsigned long long)client.getMapSeed())
|
<<") (t="<<client.getEnv().getClientMap().getHeat(pos_i)
|
||||||
|
<<"C, h="<<client.getEnv().getClientMap().getHumidity(pos_i)
|
||||||
|
<<"%) (seed = "<<((unsigned long long)client.getMapSeed())
|
||||||
<<")";
|
<<")";
|
||||||
guitext2->setText(narrow_to_wide(os.str()).c_str());
|
guitext2->setText(narrow_to_wide(os.str()).c_str());
|
||||||
guitext2->setVisible(true);
|
guitext2->setVisible(true);
|
||||||
|
82
src/map.cpp
82
src/map.cpp
@ -36,6 +36,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "emerge.h"
|
#include "emerge.h"
|
||||||
#include "mapgen_v6.h"
|
#include "mapgen_v6.h"
|
||||||
#include "mapgen_indev.h"
|
#include "mapgen_indev.h"
|
||||||
|
#include "biome.h"
|
||||||
|
|
||||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||||
|
|
||||||
@ -1087,6 +1088,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
|
|||||||
/*
|
/*
|
||||||
Add neighboring liquid nodes and the node itself if it is
|
Add neighboring liquid nodes and the node itself if it is
|
||||||
liquid (=water node was added) to transform queue.
|
liquid (=water node was added) to transform queue.
|
||||||
|
note: todo: for liquid_finite enough to add only self node
|
||||||
*/
|
*/
|
||||||
v3s16 dirs[7] = {
|
v3s16 dirs[7] = {
|
||||||
v3s16(0,0,0), // self
|
v3s16(0,0,0), // self
|
||||||
@ -1278,6 +1280,7 @@ void Map::removeNodeAndUpdate(v3s16 p,
|
|||||||
/*
|
/*
|
||||||
Add neighboring liquid nodes and this node to transform queue.
|
Add neighboring liquid nodes and this node to transform queue.
|
||||||
(it's vital for the node itself to get updated last.)
|
(it's vital for the node itself to get updated last.)
|
||||||
|
note: todo: for liquid_finite enough to add only self node
|
||||||
*/
|
*/
|
||||||
v3s16 dirs[7] = {
|
v3s16 dirs[7] = {
|
||||||
v3s16(0,0,1), // back
|
v3s16(0,0,1), // back
|
||||||
@ -2364,6 +2367,26 @@ void Map::removeNodeTimer(v3s16 p)
|
|||||||
block->m_node_timers.remove(p_rel);
|
block->m_node_timers.remove(p_rel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s16 Map::getHeat(v3s16 p)
|
||||||
|
{
|
||||||
|
MapBlock *block = getBlockNoCreateNoEx(getNodeBlockPos(p));
|
||||||
|
if(block != NULL) {
|
||||||
|
return block->heat;
|
||||||
|
}
|
||||||
|
//errorstream << "No heat for " << p.X<<"," << p.Z << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s16 Map::getHumidity(v3s16 p)
|
||||||
|
{
|
||||||
|
MapBlock *block = getBlockNoCreateNoEx(getNodeBlockPos(p));
|
||||||
|
if(block != NULL) {
|
||||||
|
return block->humidity;
|
||||||
|
}
|
||||||
|
//errorstream << "No humidity for " << p.X<<"," << p.Z << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ServerMap
|
ServerMap
|
||||||
*/
|
*/
|
||||||
@ -3863,7 +3886,7 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto
|
|||||||
<<" (SerializationError). "
|
<<" (SerializationError). "
|
||||||
<<"what()="<<e.what()
|
<<"what()="<<e.what()
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
//" Ignoring. A new one will be generated.
|
// Ignoring. A new one will be generated.
|
||||||
assert(0);
|
assert(0);
|
||||||
|
|
||||||
// TODO: Backup file; name is in fullpath.
|
// TODO: Backup file; name is in fullpath.
|
||||||
@ -4039,6 +4062,63 @@ void ServerMap::PrintInfo(std::ostream &out)
|
|||||||
out<<"ServerMap: ";
|
out<<"ServerMap: ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s16 ServerMap::getHeat(ServerEnvironment *env, v3s16 p, MapBlock *block)
|
||||||
|
{
|
||||||
|
if(block == NULL)
|
||||||
|
block = getBlockNoCreateNoEx(getNodeBlockPos(p));
|
||||||
|
if(block != NULL) {
|
||||||
|
if (env->getGameTime() - block->heat_time < 10)
|
||||||
|
return block->heat;
|
||||||
|
}
|
||||||
|
|
||||||
|
//variant 1: full random
|
||||||
|
//f32 heat = NoisePerlin3D(m_emerge->biomedef->np_heat, p.X, env->getGameTime()/100, p.Z, m_emerge->params->seed);
|
||||||
|
|
||||||
|
//variant 2: season change based on default heat map
|
||||||
|
f32 heat = NoisePerlin2D(m_emerge->biomedef->np_heat, p.X, p.Z, m_emerge->params->seed);
|
||||||
|
heat += -30; // -30 - todo REMOVE after fixed NoiseParams nparams_biome_def_heat = {50, 50, -> 20, 50,
|
||||||
|
f32 base = (f32)env->getGameTime() * env->getTimeOfDaySpeed();
|
||||||
|
base /= ( 86400 * g_settings->getS16("year_days") );
|
||||||
|
base += (f32)p.X / 3000;
|
||||||
|
heat += 30 * sin(base * M_PI); // season
|
||||||
|
|
||||||
|
heat += p.Y / -333; // upper=colder, lower=hotter
|
||||||
|
|
||||||
|
// daily change, hotter at sun +4, colder at night -4
|
||||||
|
heat += 8 * (sin(cycle_shift(env->getTimeOfDayF(), -0.25) * M_PI) - 0.5);
|
||||||
|
|
||||||
|
if(block != NULL) {
|
||||||
|
block->heat = heat;
|
||||||
|
block->heat_time = env->getGameTime();
|
||||||
|
}
|
||||||
|
return heat;
|
||||||
|
}
|
||||||
|
|
||||||
|
s16 ServerMap::getHumidity(ServerEnvironment *env, v3s16 p, MapBlock *block)
|
||||||
|
{
|
||||||
|
if(block == NULL)
|
||||||
|
block = getBlockNoCreateNoEx(getNodeBlockPos(p));
|
||||||
|
if(block != NULL) {
|
||||||
|
if (env->getGameTime() - block->humidity_time < 10)
|
||||||
|
return block->humidity;
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 humidity = NoisePerlin3D( m_emerge->biomedef->np_humidity,
|
||||||
|
p.X, env->getGameTime()/10, p.Z,
|
||||||
|
m_emerge->params->seed);
|
||||||
|
humidity += -12 * ( sin(cycle_shift(env->getTimeOfDayF(), -0.1) * M_PI) - 0.5);
|
||||||
|
//todo like heat//humidity += 20 * ( sin(((f32)p.Z / 300) * M_PI) - 0.5);
|
||||||
|
|
||||||
|
if (humidity > 100) humidity = 100;
|
||||||
|
if (humidity < 0) humidity = 0;
|
||||||
|
|
||||||
|
if(block != NULL) {
|
||||||
|
block->humidity = humidity;
|
||||||
|
block->humidity_time = env->getGameTime();
|
||||||
|
}
|
||||||
|
return humidity;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
MapVoxelManipulator
|
MapVoxelManipulator
|
||||||
*/
|
*/
|
||||||
|
@ -37,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "modifiedstate.h"
|
#include "modifiedstate.h"
|
||||||
#include "util/container.h"
|
#include "util/container.h"
|
||||||
#include "nodetimer.h"
|
#include "nodetimer.h"
|
||||||
|
#include "environment.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "sqlite3.h"
|
#include "sqlite3.h"
|
||||||
@ -336,6 +337,9 @@ public:
|
|||||||
void transforming_liquid_add(v3s16 p);
|
void transforming_liquid_add(v3s16 p);
|
||||||
s32 transforming_liquid_size();
|
s32 transforming_liquid_size();
|
||||||
|
|
||||||
|
virtual s16 getHeat(v3s16 p);
|
||||||
|
virtual s16 getHumidity(v3s16 p);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class LuaVoxelManip;
|
friend class LuaVoxelManip;
|
||||||
|
|
||||||
@ -483,6 +487,10 @@ public:
|
|||||||
|
|
||||||
// Parameters fed to the Mapgen
|
// Parameters fed to the Mapgen
|
||||||
MapgenParams *m_mgparams;
|
MapgenParams *m_mgparams;
|
||||||
|
|
||||||
|
virtual s16 getHeat(ServerEnvironment *env, v3s16 p, MapBlock *block = NULL);
|
||||||
|
virtual s16 getHumidity(ServerEnvironment *env, v3s16 p, MapBlock *block = NULL);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Seed used for all kinds of randomness in generation
|
// Seed used for all kinds of randomness in generation
|
||||||
u64 m_seed;
|
u64 m_seed;
|
||||||
|
@ -58,7 +58,11 @@ MapBlock::MapBlock(Map *parent, v3s16 pos, IGameDef *gamedef, bool dummy):
|
|||||||
m_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
m_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
||||||
m_disk_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
m_disk_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
||||||
m_usage_timer(0),
|
m_usage_timer(0),
|
||||||
m_refcount(0)
|
m_refcount(0),
|
||||||
|
heat_time(0),
|
||||||
|
heat(0),
|
||||||
|
humidity_time(0),
|
||||||
|
humidity(0)
|
||||||
{
|
{
|
||||||
data = NULL;
|
data = NULL;
|
||||||
if(dummy == false)
|
if(dummy == false)
|
||||||
@ -632,6 +636,11 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
|
|||||||
// Node timers
|
// Node timers
|
||||||
m_node_timers.serialize(os, version);
|
m_node_timers.serialize(os, version);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if(version >= 26){
|
||||||
|
writeF1000(os, heat);
|
||||||
|
writeF1000(os, humidity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -734,6 +743,11 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
|
|||||||
<<": Node timers (ver>=25)"<<std::endl);
|
<<": Node timers (ver>=25)"<<std::endl);
|
||||||
m_node_timers.deSerialize(is, version);
|
m_node_timers.deSerialize(is, version);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if(version >= 26){
|
||||||
|
heat = readF1000(is);
|
||||||
|
humidity = readF1000(is);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
|
TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
|
||||||
|
@ -518,6 +518,11 @@ public:
|
|||||||
NodeTimerList m_node_timers;
|
NodeTimerList m_node_timers;
|
||||||
StaticObjectList m_static_objects;
|
StaticObjectList m_static_objects;
|
||||||
|
|
||||||
|
s16 heat;
|
||||||
|
u32 heat_time;
|
||||||
|
s16 humidity;
|
||||||
|
u32 humidity_time;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*
|
/*
|
||||||
Private member variables
|
Private member variables
|
||||||
|
@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "content_mapnode.h" // For mapnode_translate_*_internal
|
#include "content_mapnode.h" // For mapnode_translate_*_internal
|
||||||
#include "serialization.h" // For ser_ver_supported
|
#include "serialization.h" // For ser_ver_supported
|
||||||
#include "util/serialize.h"
|
#include "util/serialize.h"
|
||||||
|
#include "log.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
@ -359,9 +360,23 @@ std::vector<aabb3f> MapNode::getSelectionBoxes(INodeDefManager *nodemgr) const
|
|||||||
return transformNodeBox(*this, f.selection_box, nodemgr);
|
return transformNodeBox(*this, f.selection_box, nodemgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 MapNode::getMaxLevel(INodeDefManager *nodemgr) const
|
||||||
|
{
|
||||||
|
const ContentFeatures &f = nodemgr->get(*this);
|
||||||
|
// todo: after update in all games leave only if (f.param_type_2 ==
|
||||||
|
if( f.liquid_type == LIQUID_SOURCE
|
||||||
|
|| f.liquid_type == LIQUID_FLOWING
|
||||||
|
|| f.param_type_2 == CPT2_FLOWINGLIQUID)
|
||||||
|
return LIQUID_LEVEL_MAX;
|
||||||
|
if(f.leveled || f.param_type_2 == CPT2_LEVELED)
|
||||||
|
return LEVELED_MAX;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
u8 MapNode::getLevel(INodeDefManager *nodemgr) const
|
u8 MapNode::getLevel(INodeDefManager *nodemgr) const
|
||||||
{
|
{
|
||||||
const ContentFeatures &f = nodemgr->get(*this);
|
const ContentFeatures &f = nodemgr->get(*this);
|
||||||
|
// todo: after update in all games leave only if (f.param_type_2 ==
|
||||||
if(f.liquid_type == LIQUID_SOURCE)
|
if(f.liquid_type == LIQUID_SOURCE)
|
||||||
return LIQUID_LEVEL_SOURCE;
|
return LIQUID_LEVEL_SOURCE;
|
||||||
if (f.param_type_2 == CPT2_FLOWINGLIQUID)
|
if (f.param_type_2 == CPT2_FLOWINGLIQUID)
|
||||||
@ -377,6 +392,37 @@ u8 MapNode::getLevel(INodeDefManager *nodemgr) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 MapNode::addLevel(INodeDefManager *nodemgr, s8 add)
|
||||||
|
{
|
||||||
|
s8 level = getLevel(nodemgr);
|
||||||
|
u8 rest = 0;
|
||||||
|
if (add == 0) level = 1;
|
||||||
|
level += add;
|
||||||
|
if (level < 1) {
|
||||||
|
setContent(CONTENT_AIR);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const ContentFeatures &f = nodemgr->get(*this);
|
||||||
|
if ( f.param_type_2 == CPT2_FLOWINGLIQUID
|
||||||
|
|| f.liquid_type == LIQUID_FLOWING
|
||||||
|
|| f.liquid_type == LIQUID_SOURCE) {
|
||||||
|
if (level >= LIQUID_LEVEL_MAX) {
|
||||||
|
rest = level - LIQUID_LEVEL_MAX;
|
||||||
|
setContent(nodemgr->getId(f.liquid_alternative_source));
|
||||||
|
} else {
|
||||||
|
setContent(nodemgr->getId(f.liquid_alternative_flowing));
|
||||||
|
setParam2(level & LIQUID_LEVEL_MASK);
|
||||||
|
}
|
||||||
|
} else if (f.leveled || f.param_type_2 == CPT2_LEVELED) {
|
||||||
|
if (level > LEVELED_MAX) {
|
||||||
|
rest = level - LEVELED_MAX;
|
||||||
|
level = LEVELED_MAX;
|
||||||
|
}
|
||||||
|
setParam2(level & LEVELED_MASK);
|
||||||
|
}
|
||||||
|
return rest;
|
||||||
|
}
|
||||||
|
|
||||||
u32 MapNode::serializedLength(u8 version)
|
u32 MapNode::serializedLength(u8 version)
|
||||||
{
|
{
|
||||||
if(!ser_ver_supported(version))
|
if(!ser_ver_supported(version))
|
||||||
|
@ -227,7 +227,9 @@ struct MapNode
|
|||||||
std::vector<aabb3f> getSelectionBoxes(INodeDefManager *nodemgr) const;
|
std::vector<aabb3f> getSelectionBoxes(INodeDefManager *nodemgr) const;
|
||||||
|
|
||||||
/* Liquid helpers */
|
/* Liquid helpers */
|
||||||
|
u8 getMaxLevel(INodeDefManager *nodemgr) const;
|
||||||
u8 getLevel(INodeDefManager *nodemgr) const;
|
u8 getLevel(INodeDefManager *nodemgr) const;
|
||||||
|
u8 addLevel(INodeDefManager *nodemgr, s8 add = 1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Serialization functions
|
Serialization functions
|
||||||
|
@ -213,6 +213,7 @@ void ContentFeatures::reset()
|
|||||||
liquid_alternative_source = "";
|
liquid_alternative_source = "";
|
||||||
liquid_viscosity = 0;
|
liquid_viscosity = 0;
|
||||||
liquid_renewable = true;
|
liquid_renewable = true;
|
||||||
|
freezemelt = "";
|
||||||
liquid_range = LIQUID_LEVEL_MAX+1;
|
liquid_range = LIQUID_LEVEL_MAX+1;
|
||||||
drowning = true;
|
drowning = true;
|
||||||
light_source = 0;
|
light_source = 0;
|
||||||
|
@ -224,6 +224,8 @@ struct ContentFeatures
|
|||||||
u8 liquid_viscosity;
|
u8 liquid_viscosity;
|
||||||
// Is liquid renewable (new liquid source will be created between 2 existing)
|
// Is liquid renewable (new liquid source will be created between 2 existing)
|
||||||
bool liquid_renewable;
|
bool liquid_renewable;
|
||||||
|
// Ice for water, water for ice
|
||||||
|
std::string freezemelt;
|
||||||
// Number of flowing liquids surrounding source
|
// Number of flowing liquids surrounding source
|
||||||
u8 liquid_range;
|
u8 liquid_range;
|
||||||
bool drowning;
|
bool drowning;
|
||||||
|
@ -397,6 +397,7 @@ ContentFeatures read_content_features(lua_State *L, int index)
|
|||||||
f.leveled = getintfield_default(L, index, "leveled", f.leveled);
|
f.leveled = getintfield_default(L, index, "leveled", f.leveled);
|
||||||
|
|
||||||
getboolfield(L, index, "liquid_renewable", f.liquid_renewable);
|
getboolfield(L, index, "liquid_renewable", f.liquid_renewable);
|
||||||
|
getstringfield(L, index, "freezemelt", f.freezemelt);
|
||||||
getboolfield(L, index, "drowning", f.drowning);
|
getboolfield(L, index, "drowning", f.drowning);
|
||||||
// Amount of light the node emits
|
// Amount of light the node emits
|
||||||
f.light_source = getintfield_default(L, index,
|
f.light_source = getintfield_default(L, index,
|
||||||
|
@ -233,3 +233,20 @@ void ScriptApiNode::node_on_receive_fields(v3s16 p,
|
|||||||
scriptError("error: %s", lua_tostring(L, -1));
|
scriptError("error: %s", lua_tostring(L, -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScriptApiNode::node_falling_update(v3s16 p)
|
||||||
|
{
|
||||||
|
SCRIPTAPI_PRECHECKHEADER
|
||||||
|
lua_getglobal(L, "nodeupdate");
|
||||||
|
push_v3s16(L, p);
|
||||||
|
if(lua_pcall(L, 1, 0, 0))
|
||||||
|
scriptError("error: %s", lua_tostring(L, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptApiNode::node_falling_update_single(v3s16 p)
|
||||||
|
{
|
||||||
|
SCRIPTAPI_PRECHECKHEADER
|
||||||
|
lua_getglobal(L, "nodeupdate_single");
|
||||||
|
push_v3s16(L, p);
|
||||||
|
if(lua_pcall(L, 1, 0, 0))
|
||||||
|
scriptError("error: %s", lua_tostring(L, -1));
|
||||||
|
}
|
||||||
|
@ -49,6 +49,8 @@ public:
|
|||||||
const std::string &formname,
|
const std::string &formname,
|
||||||
const std::map<std::string, std::string> &fields,
|
const std::map<std::string, std::string> &fields,
|
||||||
ServerActiveObject *sender);
|
ServerActiveObject *sender);
|
||||||
|
void node_falling_update(v3s16 p);
|
||||||
|
void node_falling_update_single(v3s16 p);
|
||||||
public:
|
public:
|
||||||
static struct EnumString es_DrawType[];
|
static struct EnumString es_DrawType[];
|
||||||
static struct EnumString es_ContentParamType[];
|
static struct EnumString es_ContentParamType[];
|
||||||
|
@ -263,6 +263,48 @@ int ModApiEnvMod::l_punch_node(lua_State *L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// minetest.get_node_max_level(pos)
|
||||||
|
// pos = {x=num, y=num, z=num}
|
||||||
|
int ModApiEnvMod::l_get_node_max_level(lua_State *L)
|
||||||
|
{
|
||||||
|
GET_ENV_PTR;
|
||||||
|
|
||||||
|
v3s16 pos = read_v3s16(L, 1);
|
||||||
|
MapNode n = env->getMap().getNodeNoEx(pos);
|
||||||
|
lua_pushnumber(L, n.getMaxLevel(env->getGameDef()->ndef()));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// minetest.get_node_level(pos)
|
||||||
|
// pos = {x=num, y=num, z=num}
|
||||||
|
int ModApiEnvMod::l_get_node_level(lua_State *L)
|
||||||
|
{
|
||||||
|
GET_ENV_PTR;
|
||||||
|
|
||||||
|
v3s16 pos = read_v3s16(L, 1);
|
||||||
|
MapNode n = env->getMap().getNodeNoEx(pos);
|
||||||
|
lua_pushnumber(L, n.getLevel(env->getGameDef()->ndef()));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// minetest.add_node_level(pos, level)
|
||||||
|
// pos = {x=num, y=num, z=num}
|
||||||
|
// level: 0..8
|
||||||
|
int ModApiEnvMod::l_add_node_level(lua_State *L)
|
||||||
|
{
|
||||||
|
GET_ENV_PTR;
|
||||||
|
|
||||||
|
v3s16 pos = read_v3s16(L, 1);
|
||||||
|
u8 level = 1;
|
||||||
|
if(lua_isnumber(L, 2))
|
||||||
|
level = lua_tonumber(L, 2);
|
||||||
|
MapNode n = env->getMap().getNodeNoEx(pos);
|
||||||
|
lua_pushnumber(L, n.addLevel(env->getGameDef()->ndef(), level));
|
||||||
|
env->setNode(pos, n);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// minetest.get_meta(pos)
|
// minetest.get_meta(pos)
|
||||||
int ModApiEnvMod::l_get_meta(lua_State *L)
|
int ModApiEnvMod::l_get_meta(lua_State *L)
|
||||||
{
|
{
|
||||||
@ -820,6 +862,40 @@ int ModApiEnvMod::l_spawn_tree(lua_State *L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// minetest.transforming_liquid_add(pos)
|
||||||
|
int ModApiEnvMod::l_transforming_liquid_add(lua_State *L)
|
||||||
|
{
|
||||||
|
GET_ENV_PTR;
|
||||||
|
|
||||||
|
v3s16 p0 = read_v3s16(L, 1);
|
||||||
|
env->getMap().transforming_liquid_add(p0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// minetest.get_heat(pos)
|
||||||
|
// pos = {x=num, y=num, z=num}
|
||||||
|
int ModApiEnvMod::l_get_heat(lua_State *L)
|
||||||
|
{
|
||||||
|
GET_ENV_PTR;
|
||||||
|
|
||||||
|
v3s16 pos = read_v3s16(L, 1);
|
||||||
|
lua_pushnumber(L, env->getServerMap().getHeat(env, pos));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// minetest.get_humidity(pos)
|
||||||
|
// pos = {x=num, y=num, z=num}
|
||||||
|
int ModApiEnvMod::l_get_humidity(lua_State *L)
|
||||||
|
{
|
||||||
|
GET_ENV_PTR;
|
||||||
|
|
||||||
|
v3s16 pos = read_v3s16(L, 1);
|
||||||
|
lua_pushnumber(L, env->getServerMap().getHumidity(env, pos));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ModApiEnvMod::Initialize(lua_State *L,int top)
|
bool ModApiEnvMod::Initialize(lua_State *L,int top)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -835,6 +911,9 @@ bool ModApiEnvMod::Initialize(lua_State *L,int top)
|
|||||||
retval &= API_FCT(place_node);
|
retval &= API_FCT(place_node);
|
||||||
retval &= API_FCT(dig_node);
|
retval &= API_FCT(dig_node);
|
||||||
retval &= API_FCT(punch_node);
|
retval &= API_FCT(punch_node);
|
||||||
|
retval &= API_FCT(get_node_max_level);
|
||||||
|
retval &= API_FCT(get_node_level);
|
||||||
|
retval &= API_FCT(add_node_level);
|
||||||
retval &= API_FCT(add_entity);
|
retval &= API_FCT(add_entity);
|
||||||
retval &= API_FCT(get_meta);
|
retval &= API_FCT(get_meta);
|
||||||
retval &= API_FCT(get_node_timer);
|
retval &= API_FCT(get_node_timer);
|
||||||
@ -853,6 +932,9 @@ bool ModApiEnvMod::Initialize(lua_State *L,int top)
|
|||||||
retval &= API_FCT(spawn_tree);
|
retval &= API_FCT(spawn_tree);
|
||||||
retval &= API_FCT(find_path);
|
retval &= API_FCT(find_path);
|
||||||
retval &= API_FCT(line_of_sight);
|
retval &= API_FCT(line_of_sight);
|
||||||
|
retval &= API_FCT(transforming_liquid_add);
|
||||||
|
retval &= API_FCT(get_heat);
|
||||||
|
retval &= API_FCT(get_humidity);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,19 @@ private:
|
|||||||
// pos = {x=num, y=num, z=num}
|
// pos = {x=num, y=num, z=num}
|
||||||
static int l_punch_node(lua_State *L);
|
static int l_punch_node(lua_State *L);
|
||||||
|
|
||||||
|
|
||||||
|
// minetest.get_node_max_level(pos)
|
||||||
|
// pos = {x=num, y=num, z=num}
|
||||||
|
static int l_get_node_max_level(lua_State *L);
|
||||||
|
|
||||||
|
// minetest.get_node_level(pos)
|
||||||
|
// pos = {x=num, y=num, z=num}
|
||||||
|
static int l_get_node_level(lua_State *L);
|
||||||
|
|
||||||
|
// minetest.add_node_level(pos)
|
||||||
|
// pos = {x=num, y=num, z=num}
|
||||||
|
static int l_add_node_level(lua_State *L);
|
||||||
|
|
||||||
// minetest.get_meta(pos)
|
// minetest.get_meta(pos)
|
||||||
static int l_get_meta(lua_State *L);
|
static int l_get_meta(lua_State *L);
|
||||||
|
|
||||||
@ -136,6 +149,12 @@ private:
|
|||||||
// max_jump, max_drop, algorithm) -> table containing path
|
// max_jump, max_drop, algorithm) -> table containing path
|
||||||
static int l_find_path(lua_State *L);
|
static int l_find_path(lua_State *L);
|
||||||
|
|
||||||
|
// minetest.transforming_liquid_add(pos)
|
||||||
|
static int l_transforming_liquid_add(lua_State *L);
|
||||||
|
|
||||||
|
static int l_get_heat(lua_State *L);
|
||||||
|
static int l_get_humidity(lua_State *L);
|
||||||
|
|
||||||
static struct EnumString es_MapgenObject[];
|
static struct EnumString es_MapgenObject[];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -61,11 +61,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
23: new node metadata format
|
23: new node metadata format
|
||||||
24: 16-bit node ids and node timers (never released as stable)
|
24: 16-bit node ids and node timers (never released as stable)
|
||||||
25: Improved node timer format
|
25: Improved node timer format
|
||||||
|
26: MapBlocks contain heat and humidity
|
||||||
*/
|
*/
|
||||||
// This represents an uninitialized or invalid format
|
// This represents an uninitialized or invalid format
|
||||||
#define SER_FMT_VER_INVALID 255
|
#define SER_FMT_VER_INVALID 255
|
||||||
// Highest supported serialization version
|
// Highest supported serialization version
|
||||||
#define SER_FMT_VER_HIGHEST 25
|
#define SER_FMT_VER_HIGHEST 26
|
||||||
// Lowest supported serialization version
|
// Lowest supported serialization version
|
||||||
#define SER_FMT_VER_LOWEST 0
|
#define SER_FMT_VER_LOWEST 0
|
||||||
|
|
||||||
|
@ -349,5 +349,12 @@ inline void paging(u32 length, u32 page, u32 pagecount, u32 &minindex, u32 &maxi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline float cycle_shift(float value, float by = 0, float max = 1)
|
||||||
|
{
|
||||||
|
if (value + by < 0) return max + by + value;
|
||||||
|
if (value + by > max) return value + by - max;
|
||||||
|
return value + by;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user