master
commit
4be38f6a0d
|
@ -261,9 +261,12 @@ minetest.register_chatcommand("teleport", {
|
||||||
}
|
}
|
||||||
for _, d in ipairs(tries) do
|
for _, d in ipairs(tries) do
|
||||||
local p = {x = pos.x+d.x, y = pos.y+d.y, z = pos.z+d.z}
|
local p = {x = pos.x+d.x, y = pos.y+d.y, z = pos.z+d.z}
|
||||||
local n = minetest.get_node(p)
|
local n = minetest.get_node_or_nil(p)
|
||||||
if not minetest.registered_nodes[n.name].walkable then
|
if n and n.name then
|
||||||
return p, true
|
local def = minetest.registered_nodes[n.name]
|
||||||
|
if def and not def.walkable then
|
||||||
|
return p, true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return pos, false
|
return pos, false
|
||||||
|
|
|
@ -367,7 +367,7 @@ function minetest.node_punch(pos, node, puncher, pointed_thing)
|
||||||
-- Copy pos and node because callback can modify them
|
-- Copy pos and node because callback can modify them
|
||||||
local pos_copy = vector.new(pos)
|
local pos_copy = vector.new(pos)
|
||||||
local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
|
local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
|
||||||
local pointed_thing_copy = copy_pointed_thing(pointed_thing)
|
local pointed_thing_copy = pointed_thing and copy_pointed_thing(pointed_thing) or nil
|
||||||
callback(pos_copy, node_copy, puncher, pointed_thing_copy)
|
callback(pos_copy, node_copy, puncher, pointed_thing_copy)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -116,6 +116,7 @@ minetest.register_entity("__builtin:item", {
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
self.itemstring = ''
|
||||||
self.object:remove()
|
self.object:remove()
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
|
@ -176,7 +176,7 @@ function update_menu()
|
||||||
|
|
||||||
-- handle errors
|
-- handle errors
|
||||||
if gamedata.errormessage ~= nil then
|
if gamedata.errormessage ~= nil then
|
||||||
formspec = "size[12,5.2]" ..
|
formspec = "size[12,5.2,true]" ..
|
||||||
"textarea[1,2;10,2;;ERROR: " ..
|
"textarea[1,2;10,2;;ERROR: " ..
|
||||||
engine.formspec_escape(gamedata.errormessage) ..
|
engine.formspec_escape(gamedata.errormessage) ..
|
||||||
";]"..
|
";]"..
|
||||||
|
@ -365,7 +365,7 @@ end
|
||||||
|
|
||||||
function tabbuilder.gettab()
|
function tabbuilder.gettab()
|
||||||
local tsize = tabbuilder.tabsizes[tabbuilder.current_tab] or {width=12, height=5.2}
|
local tsize = tabbuilder.tabsizes[tabbuilder.current_tab] or {width=12, height=5.2}
|
||||||
local retval = "size[" .. tsize.width .. "," .. tsize.height .. "]"
|
local retval = "size[" .. tsize.width .. "," .. tsize.height .. ",true]"
|
||||||
|
|
||||||
if tabbuilder.show_buttons then
|
if tabbuilder.show_buttons then
|
||||||
retval = retval .. tabbuilder.tab_header()
|
retval = retval .. tabbuilder.tab_header()
|
||||||
|
@ -714,15 +714,15 @@ function tabbuilder.handle_settings_buttons(fields)
|
||||||
if fields["cb_particles"] then
|
if fields["cb_particles"] then
|
||||||
engine.setting_set("enable_particles", fields["cb_particles"])
|
engine.setting_set("enable_particles", fields["cb_particles"])
|
||||||
end
|
end
|
||||||
if fields["cb_finite_liquid"] then
|
|
||||||
engine.setting_set("liquid_finite", fields["cb_finite_liquid"])
|
|
||||||
end
|
|
||||||
if fields["cb_bumpmapping"] then
|
if fields["cb_bumpmapping"] then
|
||||||
engine.setting_set("enable_bumpmapping", fields["cb_bumpmapping"])
|
engine.setting_set("enable_bumpmapping", fields["cb_bumpmapping"])
|
||||||
end
|
end
|
||||||
if fields["cb_parallax"] then
|
if fields["cb_parallax"] then
|
||||||
engine.setting_set("enable_parallax_occlusion", fields["cb_parallax"])
|
engine.setting_set("enable_parallax_occlusion", fields["cb_parallax"])
|
||||||
end
|
end
|
||||||
|
if fields["cb_generate_normalmaps"] then
|
||||||
|
engine.setting_set("generate_normalmaps", fields["cb_generate_normalmaps"])
|
||||||
|
end
|
||||||
if fields["cb_waving_water"] then
|
if fields["cb_waving_water"] then
|
||||||
engine.setting_set("enable_waving_water", fields["cb_waving_water"])
|
engine.setting_set("enable_waving_water", fields["cb_waving_water"])
|
||||||
end
|
end
|
||||||
|
@ -994,9 +994,6 @@ function tabbuilder.tab_settings()
|
||||||
.. dump(engine.setting_getbool("preload_item_visuals")) .. "]"..
|
.. dump(engine.setting_getbool("preload_item_visuals")) .. "]"..
|
||||||
"checkbox[1,2.5;cb_particles;".. fgettext("Enable Particles") .. ";"
|
"checkbox[1,2.5;cb_particles;".. fgettext("Enable Particles") .. ";"
|
||||||
.. dump(engine.setting_getbool("enable_particles")) .. "]"..
|
.. dump(engine.setting_getbool("enable_particles")) .. "]"..
|
||||||
"checkbox[1,3.0;cb_finite_liquid;".. fgettext("Finite Liquid") .. ";"
|
|
||||||
.. dump(engine.setting_getbool("liquid_finite")) .. "]"..
|
|
||||||
|
|
||||||
"checkbox[4.5,0;cb_mipmapping;".. fgettext("Mip-Mapping") .. ";"
|
"checkbox[4.5,0;cb_mipmapping;".. fgettext("Mip-Mapping") .. ";"
|
||||||
.. dump(engine.setting_getbool("mip_map")) .. "]"..
|
.. dump(engine.setting_getbool("mip_map")) .. "]"..
|
||||||
"checkbox[4.5,0.5;cb_anisotrophic;".. fgettext("Anisotropic Filtering") .. ";"
|
"checkbox[4.5,0.5;cb_anisotrophic;".. fgettext("Anisotropic Filtering") .. ";"
|
||||||
|
@ -1010,27 +1007,30 @@ function tabbuilder.tab_settings()
|
||||||
.. dump(engine.setting_getbool("enable_shaders")) .. "]"..
|
.. dump(engine.setting_getbool("enable_shaders")) .. "]"..
|
||||||
"button[1,4.5;2.25,0.5;btn_change_keys;".. fgettext("Change keys") .. "]"
|
"button[1,4.5;2.25,0.5;btn_change_keys;".. fgettext("Change keys") .. "]"
|
||||||
|
|
||||||
if engine.setting_getbool("enable_shaders") then
|
if engine.setting_getbool("enable_shaders") then
|
||||||
tab_string = tab_string ..
|
tab_string = tab_string ..
|
||||||
"checkbox[8,0.5;cb_bumpmapping;".. fgettext("Bumpmapping") .. ";"
|
"checkbox[8,0.5;cb_bumpmapping;".. fgettext("Bumpmapping") .. ";"
|
||||||
.. dump(engine.setting_getbool("enable_bumpmapping")) .. "]"..
|
.. dump(engine.setting_getbool("enable_bumpmapping")) .. "]"..
|
||||||
"checkbox[8,1.0;cb_parallax;".. fgettext("Parallax Occlusion") .. ";"
|
"checkbox[8,1.0;cb_parallax;".. fgettext("Parallax Occlusion") .. ";"
|
||||||
.. dump(engine.setting_getbool("enable_parallax_occlusion")) .. "]"..
|
.. dump(engine.setting_getbool("enable_parallax_occlusion")) .. "]"..
|
||||||
"checkbox[8,1.5;cb_waving_water;".. fgettext("Waving Water") .. ";"
|
"checkbox[8,1.5;cb_generate_normalmaps;".. fgettext("Generate Normalmaps") .. ";"
|
||||||
|
.. dump(engine.setting_getbool("generate_normalmaps")) .. "]"..
|
||||||
|
"checkbox[8,2.0;cb_waving_water;".. fgettext("Waving Water") .. ";"
|
||||||
.. dump(engine.setting_getbool("enable_waving_water")) .. "]"..
|
.. dump(engine.setting_getbool("enable_waving_water")) .. "]"..
|
||||||
"checkbox[8,2.0;cb_waving_leaves;".. fgettext("Waving Leaves") .. ";"
|
"checkbox[8,2.5;cb_waving_leaves;".. fgettext("Waving Leaves") .. ";"
|
||||||
.. dump(engine.setting_getbool("enable_waving_leaves")) .. "]"..
|
.. dump(engine.setting_getbool("enable_waving_leaves")) .. "]"..
|
||||||
"checkbox[8,2.5;cb_waving_plants;".. fgettext("Waving Plants") .. ";"
|
"checkbox[8,3.0;cb_waving_plants;".. fgettext("Waving Plants") .. ";"
|
||||||
.. dump(engine.setting_getbool("enable_waving_plants")) .. "]"
|
.. dump(engine.setting_getbool("enable_waving_plants")) .. "]"
|
||||||
else
|
else
|
||||||
tab_string = tab_string ..
|
tab_string = tab_string ..
|
||||||
"textlist[8.33,0.7;4,1;;#888888" .. fgettext("Bumpmapping") .. ";0;true]" ..
|
"textlist[8.33,0.7;4,1;;#888888" .. fgettext("Bumpmapping") .. ";0;true]" ..
|
||||||
"textlist[8.33,1.2;4,1;;#888888" .. fgettext("Parallax Occlusion") .. ";0;true]" ..
|
"textlist[8.33,1.2;4,1;;#888888" .. fgettext("Parallax Occlusion") .. ";0;true]" ..
|
||||||
"textlist[8.33,1.7;4,1;;#888888" .. fgettext("Waving Water") .. ";0;true]" ..
|
"textlist[8.33,1.7;4,1;;#888888" .. fgettext("Generate Normalmaps") .. ";0;true]" ..
|
||||||
"textlist[8.33,2.2;4,1;;#888888" .. fgettext("Waving Leaves") .. ";0;true]" ..
|
"textlist[8.33,2.2;4,1;;#888888" .. fgettext("Waving Water") .. ";0;true]" ..
|
||||||
"textlist[8.33,2.7;4,1;;#888888" .. fgettext("Waving Plants") .. ";0;true]"
|
"textlist[8.33,2.7;4,1;;#888888" .. fgettext("Waving Leaves") .. ";0;true]" ..
|
||||||
|
"textlist[8.33,3.2;4,1;;#888888" .. fgettext("Waving Plants") .. ";0;true]"
|
||||||
end
|
end
|
||||||
return tab_string
|
return tab_string
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
|
@ -21,6 +21,8 @@ minetest.register_globalstep(function(dtime)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
function minetest.after(time, func, ...)
|
function minetest.after(time, func, ...)
|
||||||
|
assert(tonumber(time) and type(func) == "function",
|
||||||
|
"Invalid minetest.after invocation")
|
||||||
table.insert(minetest.timers_to_add, {time=time, func=func, args={...}})
|
table.insert(minetest.timers_to_add, {time=time, func=func, args={...}})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -422,7 +422,7 @@ function modmgr.dialog_configure_world()
|
||||||
local mod = filterlist.get_list(modmgr.modlist)[modmgr.world_config_selected_mod]
|
local mod = filterlist.get_list(modmgr.modlist)[modmgr.world_config_selected_mod]
|
||||||
|
|
||||||
local retval =
|
local retval =
|
||||||
"size[11,6.5]" ..
|
"size[11,6.5,true]" ..
|
||||||
"label[0.5,-0.25;" .. fgettext("World:") .. "]" ..
|
"label[0.5,-0.25;" .. fgettext("World:") .. "]" ..
|
||||||
"label[1.75,-0.25;" .. worldspec.name .. "]"
|
"label[1.75,-0.25;" .. worldspec.name .. "]"
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ end
|
||||||
-- @function [parent=#modstore] getsuccessfuldialog
|
-- @function [parent=#modstore] getsuccessfuldialog
|
||||||
function modstore.getsuccessfuldialog()
|
function modstore.getsuccessfuldialog()
|
||||||
local retval = ""
|
local retval = ""
|
||||||
retval = retval .. "size[6,2]"
|
retval = retval .. "size[6,2,true]"
|
||||||
if modstore.lastmodentry ~= nil then
|
if modstore.lastmodentry ~= nil then
|
||||||
retval = retval .. "label[0,0.25;" .. fgettext("Successfully installed:") .. "]"
|
retval = retval .. "label[0,0.25;" .. fgettext("Successfully installed:") .. "]"
|
||||||
retval = retval .. "label[3,0.25;" .. modstore.lastmodentry.moddetails.title .. "]"
|
retval = retval .. "label[3,0.25;" .. modstore.lastmodentry.moddetails.title .. "]"
|
||||||
|
@ -152,7 +152,7 @@ end
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- @function [parent=#modstore] tabheader
|
-- @function [parent=#modstore] tabheader
|
||||||
function modstore.tabheader(tabname)
|
function modstore.tabheader(tabname)
|
||||||
local retval = "size[12,10.25]"
|
local retval = "size[12,10.25,true]"
|
||||||
retval = retval .. "tabheader[-0.3,-0.99;modstore_tab;" ..
|
retval = retval .. "tabheader[-0.3,-0.99;modstore_tab;" ..
|
||||||
"Unsorted,Search;" ..
|
"Unsorted,Search;" ..
|
||||||
modstore.nametoindex(tabname) .. ";true;false]" ..
|
modstore.nametoindex(tabname) .. ";true;false]" ..
|
||||||
|
|
|
@ -1,71 +1,110 @@
|
||||||
uniform sampler2D baseTexture;
|
uniform sampler2D baseTexture;
|
||||||
uniform sampler2D normalTexture;
|
uniform sampler2D normalTexture;
|
||||||
uniform sampler2D useNormalmap;
|
uniform sampler2D useNormalmap;
|
||||||
|
|
||||||
uniform vec4 skyBgColor;
|
uniform vec4 skyBgColor;
|
||||||
uniform float fogDistance;
|
uniform float fogDistance;
|
||||||
uniform vec3 eyePosition;
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
varying vec3 vPosition;
|
varying vec3 vPosition;
|
||||||
varying vec3 eyeVec;
|
varying vec3 worldPosition;
|
||||||
|
|
||||||
#ifdef ENABLE_PARALLAX_OCCLUSION
|
varying vec3 eyeVec;
|
||||||
varying vec3 tsEyeVec;
|
varying vec3 tsEyeVec;
|
||||||
#endif
|
varying vec3 lightVec;
|
||||||
|
varying vec3 tsLightVec;
|
||||||
const float e = 2.718281828459;
|
|
||||||
|
bool normalTexturePresent = false;
|
||||||
void main (void)
|
|
||||||
{
|
const float e = 2.718281828459;
|
||||||
vec3 color;
|
|
||||||
vec2 uv = gl_TexCoord[0].st;
|
float intensity (vec3 color){
|
||||||
|
return (color.r + color.g + color.b) / 3.0;
|
||||||
#ifdef USE_NORMALMAPS
|
}
|
||||||
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
|
|
||||||
#endif
|
float get_rgb_height (vec2 uv){
|
||||||
|
return intensity(texture2D(baseTexture,uv).rgb);
|
||||||
#ifdef ENABLE_PARALLAX_OCCLUSION
|
}
|
||||||
float height;
|
|
||||||
vec2 tsEye = vec2(tsEyeVec.x,-tsEyeVec.y);
|
vec4 get_normal_map(vec2 uv){
|
||||||
|
vec4 bump = texture2D(normalTexture, uv).rgba;
|
||||||
if (use_normalmap > 0.0) {
|
bump.xyz = normalize(bump.xyz * 2.0 -1.0);
|
||||||
float map_height = texture2D(normalTexture, uv).a;
|
bump.y = -bump.y;
|
||||||
if (map_height < 1.0){
|
return bump;
|
||||||
float height = PARALLAX_OCCLUSION_SCALE * map_height - PARALLAX_OCCLUSION_BIAS;
|
}
|
||||||
uv = uv + height * tsEye;
|
|
||||||
}
|
void main (void)
|
||||||
}
|
{
|
||||||
#endif
|
vec3 color;
|
||||||
|
vec4 bump;
|
||||||
#ifdef ENABLE_BUMPMAPPING
|
vec2 uv = gl_TexCoord[0].st;
|
||||||
if (use_normalmap > 0.0) {
|
bool use_normalmap = false;
|
||||||
vec3 base = texture2D(baseTexture, uv).rgb;
|
|
||||||
vec3 vVec = normalize(eyeVec);
|
#ifdef USE_NORMALMAPS
|
||||||
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
|
if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0){
|
||||||
vec3 R = reflect(-vVec, bump);
|
normalTexturePresent = true;
|
||||||
vec3 lVec = normalize(vVec);
|
}
|
||||||
float diffuse = max(dot(lVec, bump), 0.0);
|
#endif
|
||||||
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
|
|
||||||
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
|
#ifdef ENABLE_PARALLAX_OCCLUSION
|
||||||
} else {
|
if (normalTexturePresent){
|
||||||
color = texture2D(baseTexture, uv).rgb;
|
vec3 tsEye = normalize(tsEyeVec);
|
||||||
}
|
float height = PARALLAX_OCCLUSION_SCALE * texture2D(normalTexture, uv).a - PARALLAX_OCCLUSION_BIAS;
|
||||||
#else
|
uv = uv + texture2D(normalTexture, uv).z * height * vec2(tsEye.x,-tsEye.y);
|
||||||
color = texture2D(baseTexture, uv).rgb;
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float alpha = texture2D(baseTexture, uv).a;
|
#ifdef USE_NORMALMAPS
|
||||||
vec4 col = vec4(color.r, color.g, color.b, alpha);
|
if (normalTexturePresent){
|
||||||
col *= gl_Color;
|
bump = get_normal_map(uv);
|
||||||
col = col * col; // SRGB -> Linear
|
use_normalmap = true;
|
||||||
col *= 1.8;
|
}
|
||||||
col.r = 1.0 - exp(1.0 - col.r) / e;
|
#endif
|
||||||
col.g = 1.0 - exp(1.0 - col.g) / e;
|
|
||||||
col.b = 1.0 - exp(1.0 - col.b) / e;
|
#ifdef GENERATE_NORMALMAPS
|
||||||
col = sqrt(col); // Linear -> SRGB
|
if (use_normalmap == false){
|
||||||
if(fogDistance != 0.0){
|
float tl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y+SAMPLE_STEP));
|
||||||
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
float t = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
|
||||||
col = mix(col, skyBgColor, d);
|
float tr = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y+SAMPLE_STEP));
|
||||||
}
|
float r = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y));
|
||||||
gl_FragColor = vec4(col.r, col.g, col.b, alpha);
|
float br = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y-SAMPLE_STEP));
|
||||||
}
|
float b = get_rgb_height (vec2(uv.x,uv.y-SAMPLE_STEP));
|
||||||
|
float bl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
|
||||||
|
float l = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y));
|
||||||
|
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
|
||||||
|
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
|
||||||
|
bump = vec4 (normalize(vec3 (dX, -dY, NORMALMAPS_STRENGTH)),1.0);
|
||||||
|
use_normalmap = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4 base = texture2D(baseTexture, uv).rgba;
|
||||||
|
|
||||||
|
#ifdef ENABLE_BUMPMAPPING
|
||||||
|
if (use_normalmap){
|
||||||
|
vec3 L = normalize(lightVec);
|
||||||
|
vec3 E = normalize(eyeVec);
|
||||||
|
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0),0.5);
|
||||||
|
float diffuse = dot(E,bump.xyz);
|
||||||
|
color = 0.05*base.rgb + diffuse*base.rgb + 0.2*specular*base.rgb;
|
||||||
|
} else {
|
||||||
|
color = base.rgb;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
color = base.rgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4 col = vec4(color.rgb, base.a);
|
||||||
|
col = col * col; // SRGB -> Linear
|
||||||
|
col *= 1.8;
|
||||||
|
col.r = 1.0 - exp(1.0 - col.r) / e;
|
||||||
|
col.g = 1.0 - exp(1.0 - col.g) / e;
|
||||||
|
col.b = 1.0 - exp(1.0 - col.b) / e;
|
||||||
|
col = sqrt(col); // Linear -> SRGB
|
||||||
|
col *= gl_Color;
|
||||||
|
if(fogDistance != 0.0){
|
||||||
|
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
||||||
|
col = mix(col, skyBgColor, d);
|
||||||
|
}
|
||||||
|
gl_FragColor = vec4(col.rgb, base.a);
|
||||||
|
}
|
||||||
|
|
|
@ -1,27 +1,33 @@
|
||||||
uniform mat4 mWorldViewProj;
|
uniform mat4 mWorldViewProj;
|
||||||
uniform mat4 mInvWorld;
|
uniform mat4 mInvWorld;
|
||||||
uniform mat4 mTransWorld;
|
uniform mat4 mTransWorld;
|
||||||
|
uniform mat4 mWorld;
|
||||||
|
|
||||||
uniform float dayNightRatio;
|
uniform float dayNightRatio;
|
||||||
|
|
||||||
uniform vec3 eyePosition;
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
varying vec3 vPosition;
|
varying vec3 vPosition;
|
||||||
varying vec3 eyeVec;
|
varying vec3 worldPosition;
|
||||||
|
|
||||||
|
varying vec3 eyeVec;
|
||||||
|
varying vec3 lightVec;
|
||||||
|
|
||||||
#ifdef ENABLE_PARALLAX_OCCLUSION
|
|
||||||
varying vec3 tsEyeVec;
|
varying vec3 tsEyeVec;
|
||||||
#endif
|
varying vec3 tsLightVec;
|
||||||
|
|
||||||
|
const float BS = 10.0;
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
gl_Position = mWorldViewProj * gl_Vertex;
|
gl_Position = mWorldViewProj * gl_Vertex;
|
||||||
vPosition = (mWorldViewProj * gl_Vertex).xyz;
|
vPosition = gl_Position.xyz;
|
||||||
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
worldPosition = (mWorld * gl_Vertex).xyz;
|
||||||
|
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);
|
||||||
|
|
||||||
#ifdef ENABLE_PARALLAX_OCCLUSION
|
vec3 normal, tangent, binormal;
|
||||||
vec3 normal,tangent,binormal;
|
|
||||||
normal = normalize(gl_NormalMatrix * gl_Normal);
|
normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||||
|
|
||||||
if (gl_Normal.x > 0.5) {
|
if (gl_Normal.x > 0.5) {
|
||||||
// 1.0, 0.0, 0.0
|
// 1.0, 0.0, 0.0
|
||||||
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, -1.0));
|
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, -1.0));
|
||||||
|
@ -47,25 +53,20 @@ void main(void)
|
||||||
tangent = normalize(gl_NormalMatrix * vec3(-1.0, 0.0, 0.0));
|
tangent = normalize(gl_NormalMatrix * vec3(-1.0, 0.0, 0.0));
|
||||||
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
mat3 tbnMatrix = mat3( tangent.x, binormal.x, normal.x,
|
mat3 tbnMatrix = mat3( tangent.x, binormal.x, normal.x,
|
||||||
tangent.y, binormal.y, normal.y,
|
tangent.y, binormal.y, normal.y,
|
||||||
tangent.z, binormal.z, normal.z);
|
tangent.z, binormal.z, normal.z);
|
||||||
|
|
||||||
tsEyeVec = normalize(eyeVec * tbnMatrix);
|
lightVec = sunPosition - worldPosition;
|
||||||
#endif
|
tsLightVec = lightVec * tbnMatrix;
|
||||||
|
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||||
|
tsEyeVec = eyeVec * tbnMatrix;
|
||||||
|
|
||||||
vec4 color;
|
vec4 color;
|
||||||
//color = vec4(1.0, 1.0, 1.0, 1.0);
|
|
||||||
|
|
||||||
float day = gl_Color.r;
|
float day = gl_Color.r;
|
||||||
float night = gl_Color.g;
|
float night = gl_Color.g;
|
||||||
float light_source = gl_Color.b;
|
float light_source = gl_Color.b;
|
||||||
|
|
||||||
/*color.r = mix(night, day, dayNightRatio);
|
|
||||||
color.g = color.r;
|
|
||||||
color.b = color.r;*/
|
|
||||||
|
|
||||||
float rg = mix(night, day, dayNightRatio);
|
float rg = mix(night, day, dayNightRatio);
|
||||||
rg += light_source * 2.5; // Make light sources brighter
|
rg += light_source * 2.5; // Make light sources brighter
|
||||||
float b = rg;
|
float b = rg;
|
||||||
|
@ -90,13 +91,8 @@ void main(void)
|
||||||
color = color * color; // SRGB -> Linear
|
color = color * color; // SRGB -> Linear
|
||||||
if(gl_Normal.y <= 0.5)
|
if(gl_Normal.y <= 0.5)
|
||||||
color *= 0.6;
|
color *= 0.6;
|
||||||
//color *= 0.7;
|
|
||||||
color = sqrt(color); // Linear -> SRGB
|
color = sqrt(color); // Linear -> SRGB
|
||||||
|
|
||||||
color.a = gl_Color.a;
|
color.a = gl_Color.a;
|
||||||
|
|
||||||
gl_FrontColor = gl_BackColor = color;
|
gl_FrontColor = gl_BackColor = color;
|
||||||
|
|
||||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,54 +1,100 @@
|
||||||
uniform sampler2D baseTexture;
|
uniform sampler2D baseTexture;
|
||||||
uniform sampler2D normalTexture;
|
uniform sampler2D normalTexture;
|
||||||
uniform sampler2D useNormalmap;
|
uniform sampler2D useNormalmap;
|
||||||
|
|
||||||
uniform vec4 skyBgColor;
|
uniform vec4 skyBgColor;
|
||||||
uniform float fogDistance;
|
uniform float fogDistance;
|
||||||
uniform vec3 eyePosition;
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
varying vec3 vPosition;
|
varying vec3 vPosition;
|
||||||
varying vec3 eyeVec;
|
varying vec3 worldPosition;
|
||||||
|
|
||||||
const float e = 2.718281828459;
|
varying vec3 eyeVec;
|
||||||
|
varying vec3 lightVec;
|
||||||
void main (void)
|
|
||||||
{
|
bool normalTexturePresent = false;
|
||||||
vec3 color;
|
|
||||||
vec2 uv = gl_TexCoord[0].st;
|
const float e = 2.718281828459;
|
||||||
|
|
||||||
#ifdef USE_NORMALMAPS
|
float intensity (vec3 color){
|
||||||
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
|
return (color.r + color.g + color.b) / 3.0;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_BUMPMAPPING
|
float get_rgb_height (vec2 uv){
|
||||||
if (use_normalmap > 0.0) {
|
return intensity(texture2D(baseTexture,uv).rgb);
|
||||||
vec3 base = texture2D(baseTexture, uv).rgb;
|
}
|
||||||
vec3 vVec = normalize(eyeVec);
|
|
||||||
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
|
vec4 get_normal_map(vec2 uv){
|
||||||
vec3 R = reflect(-vVec, bump);
|
vec4 bump = texture2D(normalTexture, uv).rgba;
|
||||||
vec3 lVec = normalize(vVec);
|
bump.xyz = normalize(bump.xyz * 2.0 -1.0);
|
||||||
float diffuse = max(dot(lVec, bump), 0.0);
|
bump.y = -bump.y;
|
||||||
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
|
return bump;
|
||||||
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
|
}
|
||||||
} else {
|
|
||||||
color = texture2D(baseTexture, uv).rgb;
|
void main (void)
|
||||||
}
|
{
|
||||||
#else
|
vec3 color;
|
||||||
color = texture2D(baseTexture, uv).rgb;
|
vec4 bump;
|
||||||
#endif
|
vec2 uv = gl_TexCoord[0].st;
|
||||||
|
bool use_normalmap = false;
|
||||||
float alpha = texture2D(baseTexture, uv).a;
|
|
||||||
vec4 col = vec4(color.r, color.g, color.b, alpha);
|
#ifdef USE_NORMALMAPS
|
||||||
col *= gl_Color;
|
if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0){
|
||||||
col = col * col; // SRGB -> Linear
|
normalTexturePresent = true;
|
||||||
col *= 1.8;
|
}
|
||||||
col.r = 1.0 - exp(1.0 - col.r) / e;
|
#endif
|
||||||
col.g = 1.0 - exp(1.0 - col.g) / e;
|
|
||||||
col.b = 1.0 - exp(1.0 - col.b) / e;
|
#ifdef USE_NORMALMAPS
|
||||||
col = sqrt(col); // Linear -> SRGB
|
if (normalTexturePresent){
|
||||||
if(fogDistance != 0.0){
|
bump = get_normal_map(uv);
|
||||||
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
use_normalmap = true;
|
||||||
col = mix(col, skyBgColor, d);
|
}
|
||||||
}
|
#endif
|
||||||
gl_FragColor = vec4(col.r, col.g, col.b, alpha);
|
|
||||||
}
|
#ifdef GENERATE_NORMALMAPS
|
||||||
|
if (use_normalmap == false){
|
||||||
|
float tl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y+SAMPLE_STEP));
|
||||||
|
float t = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
|
||||||
|
float tr = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y+SAMPLE_STEP));
|
||||||
|
float r = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y));
|
||||||
|
float br = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y-SAMPLE_STEP));
|
||||||
|
float b = get_rgb_height (vec2(uv.x,uv.y-SAMPLE_STEP));
|
||||||
|
float bl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
|
||||||
|
float l = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y));
|
||||||
|
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
|
||||||
|
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
|
||||||
|
bump = vec4 (normalize(vec3 (dX, -dY, NORMALMAPS_STRENGTH)),1.0);
|
||||||
|
use_normalmap = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4 base = texture2D(baseTexture, uv).rgba;
|
||||||
|
|
||||||
|
#ifdef ENABLE_BUMPMAPPING
|
||||||
|
if (use_normalmap){
|
||||||
|
vec3 L = normalize(lightVec);
|
||||||
|
vec3 E = normalize(eyeVec);
|
||||||
|
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0),0.5);
|
||||||
|
float diffuse = dot(E,bump.xyz);
|
||||||
|
color = 0.05*base.rgb + diffuse*base.rgb + 0.2*specular*base.rgb;
|
||||||
|
} else {
|
||||||
|
color = base.rgb;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
color = base.rgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4 col = vec4(color.rgb, base.a);
|
||||||
|
col = col * col; // SRGB -> Linear
|
||||||
|
col *= 1.8;
|
||||||
|
col.r = 1.0 - exp(1.0 - col.r) / e;
|
||||||
|
col.g = 1.0 - exp(1.0 - col.g) / e;
|
||||||
|
col.b = 1.0 - exp(1.0 - col.b) / e;
|
||||||
|
col = sqrt(col); // Linear -> SRGB
|
||||||
|
col *= gl_Color;
|
||||||
|
if(fogDistance != 0.0){
|
||||||
|
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
||||||
|
col = mix(col, skyBgColor, d);
|
||||||
|
}
|
||||||
|
gl_FragColor = vec4(col.rgb, base.a);
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
uniform mat4 mWorldViewProj;
|
uniform mat4 mWorldViewProj;
|
||||||
uniform mat4 mInvWorld;
|
uniform mat4 mInvWorld;
|
||||||
uniform mat4 mTransWorld;
|
uniform mat4 mTransWorld;
|
||||||
|
uniform mat4 mWorld;
|
||||||
|
|
||||||
uniform float dayNightRatio;
|
uniform float dayNightRatio;
|
||||||
uniform float animationTimer;
|
uniform float animationTimer;
|
||||||
|
|
||||||
uniform vec3 eyePosition;
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
varying vec3 vPosition;
|
varying vec3 vPosition;
|
||||||
|
varying vec3 worldPosition;
|
||||||
|
|
||||||
varying vec3 eyeVec;
|
varying vec3 eyeVec;
|
||||||
|
varying vec3 lightVec;
|
||||||
|
|
||||||
|
const float BS = 10.0;
|
||||||
|
|
||||||
#ifdef ENABLE_WAVING_LEAVES
|
#ifdef ENABLE_WAVING_LEAVES
|
||||||
float smoothCurve( float x ) {
|
float smoothCurve( float x ) {
|
||||||
|
@ -27,7 +34,7 @@ void main(void)
|
||||||
|
|
||||||
#ifdef ENABLE_WAVING_LEAVES
|
#ifdef ENABLE_WAVING_LEAVES
|
||||||
vec4 pos = gl_Vertex;
|
vec4 pos = gl_Vertex;
|
||||||
vec4 pos2 = mTransWorld*gl_Vertex;
|
vec4 pos2 = mWorld*gl_Vertex;
|
||||||
pos.x += (smoothTriangleWave(animationTimer*10.0 + pos2.x * 0.01 + pos2.z * 0.01) * 2.0 - 1.0) * 0.4;
|
pos.x += (smoothTriangleWave(animationTimer*10.0 + pos2.x * 0.01 + pos2.z * 0.01) * 2.0 - 1.0) * 0.4;
|
||||||
pos.y += (smoothTriangleWave(animationTimer*15.0 + pos2.x * -0.01 + pos2.z * -0.01) * 2.0 - 1.0) * 0.2;
|
pos.y += (smoothTriangleWave(animationTimer*15.0 + pos2.x * -0.01 + pos2.z * -0.01) * 2.0 - 1.0) * 0.2;
|
||||||
pos.z += (smoothTriangleWave(animationTimer*10.0 + pos2.x * -0.01 + pos2.z * -0.01) * 2.0 - 1.0) * 0.4;
|
pos.z += (smoothTriangleWave(animationTimer*10.0 + pos2.x * -0.01 + pos2.z * -0.01) * 2.0 - 1.0) * 0.4;
|
||||||
|
@ -36,10 +43,13 @@ void main(void)
|
||||||
gl_Position = mWorldViewProj * gl_Vertex;
|
gl_Position = mWorldViewProj * gl_Vertex;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vPosition = (mWorldViewProj * gl_Vertex).xyz;
|
vPosition = gl_Position.xyz;
|
||||||
|
worldPosition = (mWorld * gl_Vertex).xyz;
|
||||||
|
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);
|
||||||
|
|
||||||
|
lightVec = sunPosition - worldPosition;
|
||||||
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||||
|
|
||||||
vec4 color;
|
vec4 color;
|
||||||
//color = vec4(1.0, 1.0, 1.0, 1.0);
|
//color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
@ -75,13 +85,8 @@ void main(void)
|
||||||
color = color * color; // SRGB -> Linear
|
color = color * color; // SRGB -> Linear
|
||||||
if(gl_Normal.y <= 0.5)
|
if(gl_Normal.y <= 0.5)
|
||||||
color *= 0.6;
|
color *= 0.6;
|
||||||
//color *= 0.7;
|
|
||||||
color = sqrt(color); // Linear -> SRGB
|
color = sqrt(color); // Linear -> SRGB
|
||||||
|
|
||||||
color.a = gl_Color.a;
|
color.a = gl_Color.a;
|
||||||
|
|
||||||
gl_FrontColor = gl_BackColor = color;
|
gl_FrontColor = gl_BackColor = color;
|
||||||
|
|
||||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,54 +1,95 @@
|
||||||
uniform sampler2D baseTexture;
|
uniform sampler2D baseTexture;
|
||||||
uniform sampler2D normalTexture;
|
uniform sampler2D normalTexture;
|
||||||
uniform sampler2D useNormalmap;
|
uniform sampler2D useNormalmap;
|
||||||
|
|
||||||
uniform vec4 skyBgColor;
|
uniform vec4 skyBgColor;
|
||||||
uniform float fogDistance;
|
uniform float fogDistance;
|
||||||
uniform vec3 eyePosition;
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
varying vec3 vPosition;
|
varying vec3 vPosition;
|
||||||
varying vec3 eyeVec;
|
varying vec3 worldPosition;
|
||||||
|
|
||||||
const float e = 2.718281828459;
|
varying vec3 eyeVec;
|
||||||
|
varying vec3 tsEyeVec;
|
||||||
void main (void)
|
varying vec3 lightVec;
|
||||||
{
|
varying vec3 tsLightVec;
|
||||||
vec3 color;
|
|
||||||
vec2 uv = gl_TexCoord[0].st;
|
const float e = 2.718281828459;
|
||||||
|
|
||||||
#ifdef USE_NORMALMAPS
|
float intensity (vec3 color){
|
||||||
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
|
return (color.r + color.g + color.b) / 3.0;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_BUMPMAPPING
|
float get_rgb_height (vec2 uv){
|
||||||
if (use_normalmap > 0.0) {
|
return intensity(texture2D(baseTexture,uv).rgb);
|
||||||
vec3 base = texture2D(baseTexture, uv).rgb;
|
}
|
||||||
vec3 vVec = normalize(eyeVec);
|
|
||||||
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
|
vec4 get_normal_map(vec2 uv){
|
||||||
vec3 R = reflect(-vVec, bump);
|
vec4 bump = texture2D(normalTexture, uv).rgba;
|
||||||
vec3 lVec = normalize(vVec);
|
bump.xyz = normalize(bump.xyz * 2.0 -1.0);
|
||||||
float diffuse = max(dot(vec3(-1.0, -0.4, 0.5), bump), 0.0);
|
bump.y = -bump.y;
|
||||||
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
|
return bump;
|
||||||
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
|
}
|
||||||
} else {
|
|
||||||
color = texture2D(baseTexture, uv).rgb;
|
void main (void)
|
||||||
}
|
{
|
||||||
#else
|
vec3 color;
|
||||||
color = texture2D(baseTexture, uv).rgb;
|
vec4 bump;
|
||||||
#endif
|
vec2 uv = gl_TexCoord[0].st;
|
||||||
|
bool use_normalmap = false;
|
||||||
float alpha = gl_Color.a;
|
|
||||||
vec4 col = vec4(color.r, color.g, color.b, alpha);
|
#ifdef USE_NORMALMAPS
|
||||||
col *= gl_Color;
|
if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0){
|
||||||
col = col * col; // SRGB -> Linear
|
bump = get_normal_map(uv);
|
||||||
col *= 1.8;
|
use_normalmap = true;
|
||||||
col.r = 1.0 - exp(1.0 - col.r) / e;
|
}
|
||||||
col.g = 1.0 - exp(1.0 - col.g) / e;
|
#endif
|
||||||
col.b = 1.0 - exp(1.0 - col.b) / e;
|
|
||||||
col = sqrt(col); // Linear -> SRGB
|
#ifdef GENERATE_NORMALMAPS
|
||||||
if(fogDistance != 0.0){
|
if (use_normalmap == false){
|
||||||
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
float tl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y+SAMPLE_STEP));
|
||||||
alpha = mix(alpha, 0.0, d);
|
float t = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
|
||||||
}
|
float tr = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y+SAMPLE_STEP));
|
||||||
gl_FragColor = vec4(col.r, col.g, col.b, alpha);
|
float r = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y));
|
||||||
}
|
float br = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y-SAMPLE_STEP));
|
||||||
|
float b = get_rgb_height (vec2(uv.x,uv.y-SAMPLE_STEP));
|
||||||
|
float bl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
|
||||||
|
float l = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y));
|
||||||
|
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
|
||||||
|
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
|
||||||
|
bump = vec4 (normalize(vec3 (dX, -dY, NORMALMAPS_STRENGTH)),1.0);
|
||||||
|
use_normalmap = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4 base = texture2D(baseTexture, uv).rgba;
|
||||||
|
|
||||||
|
#ifdef ENABLE_BUMPMAPPING
|
||||||
|
if (use_normalmap){
|
||||||
|
vec3 L = normalize(lightVec);
|
||||||
|
vec3 E = normalize(eyeVec);
|
||||||
|
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0),0.5);
|
||||||
|
float diffuse = dot(E,bump.xyz);
|
||||||
|
color = 0.05*base.rgb + diffuse*base.rgb + 0.2*specular*base.rgb;
|
||||||
|
} else {
|
||||||
|
color = base.rgb;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
color = base.rgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float alpha = gl_Color.a;
|
||||||
|
vec4 col = vec4(color.rgb, alpha);
|
||||||
|
col = col * col; // SRGB -> Linear
|
||||||
|
col *= 1.8;
|
||||||
|
col.r = 1.0 - exp(1.0 - col.r) / e;
|
||||||
|
col.g = 1.0 - exp(1.0 - col.g) / e;
|
||||||
|
col.b = 1.0 - exp(1.0 - col.b) / e;
|
||||||
|
col = sqrt(col); // Linear -> SRGB
|
||||||
|
col *= gl_Color;
|
||||||
|
if(fogDistance != 0.0){
|
||||||
|
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
||||||
|
alpha = mix(alpha, 0.0, d);
|
||||||
|
}
|
||||||
|
gl_FragColor = vec4(col.rgb, alpha);
|
||||||
|
}
|
||||||
|
|
|
@ -1,40 +1,84 @@
|
||||||
uniform mat4 mWorldViewProj;
|
uniform mat4 mWorldViewProj;
|
||||||
uniform mat4 mInvWorld;
|
uniform mat4 mInvWorld;
|
||||||
uniform mat4 mTransWorld;
|
uniform mat4 mTransWorld;
|
||||||
|
uniform mat4 mWorld;
|
||||||
|
|
||||||
uniform float dayNightRatio;
|
uniform float dayNightRatio;
|
||||||
uniform float animationTimer;
|
uniform float animationTimer;
|
||||||
|
|
||||||
uniform vec3 eyePosition;
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
varying vec3 vPosition;
|
varying vec3 vPosition;
|
||||||
|
varying vec3 worldPosition;
|
||||||
|
|
||||||
varying vec3 eyeVec;
|
varying vec3 eyeVec;
|
||||||
|
varying vec3 lightVec;
|
||||||
|
|
||||||
|
varying vec3 tsEyeVec;
|
||||||
|
varying vec3 tsLightVec;
|
||||||
|
|
||||||
|
const float BS = 10.0;
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
|
|
||||||
#ifdef ENABLE_WAVING_WATER
|
#ifdef ENABLE_WAVING_WATER
|
||||||
vec4 pos2 = gl_Vertex;
|
vec4 pos2 = gl_Vertex;
|
||||||
pos2.y -= 2.0;
|
pos2.y -= 2.0;
|
||||||
pos2.y -= sin (pos2.z/WATER_WAVE_LENGTH + animationTimer * WATER_WAVE_SPEED * WATER_WAVE_LENGTH) * WATER_WAVE_HEIGHT
|
pos2.y -= sin (pos2.z/WATER_WAVE_LENGTH + animationTimer * WATER_WAVE_SPEED * WATER_WAVE_LENGTH) * WATER_WAVE_HEIGHT
|
||||||
+ sin ((pos2.z/WATER_WAVE_LENGTH + animationTimer * WATER_WAVE_SPEED * WATER_WAVE_LENGTH) / 7.0) * WATER_WAVE_HEIGHT;
|
+ sin ((pos2.z/WATER_WAVE_LENGTH + animationTimer * WATER_WAVE_SPEED * WATER_WAVE_LENGTH) / 7.0) * WATER_WAVE_HEIGHT;
|
||||||
gl_Position = mWorldViewProj * pos2;
|
gl_Position = mWorldViewProj * pos2;
|
||||||
|
vPosition = gl_Position.xyz;
|
||||||
#else
|
#else
|
||||||
gl_Position = mWorldViewProj * gl_Vertex;
|
gl_Position = mWorldViewProj * gl_Vertex;
|
||||||
|
vPosition = gl_Position.xyz;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
worldPosition = (mWorld * gl_Vertex).xyz;
|
||||||
|
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);
|
||||||
|
|
||||||
|
vec3 normal, tangent, binormal;
|
||||||
|
normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||||
|
if (gl_Normal.x > 0.5) {
|
||||||
|
// 1.0, 0.0, 0.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, -1.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
|
||||||
|
} else if (gl_Normal.x < -0.5) {
|
||||||
|
// -1.0, 0.0, 0.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
|
||||||
|
} else if (gl_Normal.y > 0.5) {
|
||||||
|
// 0.0, 1.0, 0.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
|
||||||
|
} else if (gl_Normal.y < -0.5) {
|
||||||
|
// 0.0, -1.0, 0.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
|
||||||
|
} else if (gl_Normal.z > 0.5) {
|
||||||
|
// 0.0, 0.0, 1.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
|
||||||
|
} else if (gl_Normal.z < -0.5) {
|
||||||
|
// 0.0, 0.0, -1.0
|
||||||
|
tangent = normalize(gl_NormalMatrix * vec3(-1.0, 0.0, 0.0));
|
||||||
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
|
||||||
|
}
|
||||||
|
mat3 tbnMatrix = mat3( tangent.x, binormal.x, normal.x,
|
||||||
|
tangent.y, binormal.y, normal.y,
|
||||||
|
tangent.z, binormal.z, normal.z);
|
||||||
|
|
||||||
|
lightVec = sunPosition - worldPosition;
|
||||||
|
tsLightVec = lightVec * tbnMatrix;
|
||||||
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||||
vPosition = (mWorldViewProj * gl_Vertex).xyz;
|
tsEyeVec = eyeVec * tbnMatrix;
|
||||||
|
|
||||||
vec4 color;
|
vec4 color;
|
||||||
//color = vec4(1.0, 1.0, 1.0, 1.0);
|
|
||||||
|
|
||||||
float day = gl_Color.r;
|
float day = gl_Color.r;
|
||||||
float night = gl_Color.g;
|
float night = gl_Color.g;
|
||||||
float light_source = gl_Color.b;
|
float light_source = gl_Color.b;
|
||||||
|
|
||||||
/*color.r = mix(night, day, dayNightRatio);
|
|
||||||
color.g = color.r;
|
|
||||||
color.b = color.r;*/
|
|
||||||
|
|
||||||
float rg = mix(night, day, dayNightRatio);
|
float rg = mix(night, day, dayNightRatio);
|
||||||
rg += light_source * 2.5; // Make light sources brighter
|
rg += light_source * 2.5; // Make light sources brighter
|
||||||
float b = rg;
|
float b = rg;
|
||||||
|
@ -54,10 +98,13 @@ void main(void)
|
||||||
color.r = clamp(rg,0.0,1.0);
|
color.r = clamp(rg,0.0,1.0);
|
||||||
color.g = clamp(rg,0.0,1.0);
|
color.g = clamp(rg,0.0,1.0);
|
||||||
color.b = clamp(b,0.0,1.0);
|
color.b = clamp(b,0.0,1.0);
|
||||||
|
|
||||||
|
// Make sides and bottom darker than the top
|
||||||
|
color = color * color; // SRGB -> Linear
|
||||||
|
if(gl_Normal.y <= 0.5)
|
||||||
|
color *= 0.6;
|
||||||
|
color = sqrt(color); // Linear -> SRGB
|
||||||
color.a = gl_Color.a;
|
color.a = gl_Color.a;
|
||||||
|
|
||||||
gl_FrontColor = gl_BackColor = color;
|
gl_FrontColor = gl_BackColor = color;
|
||||||
|
|
||||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,54 +1,94 @@
|
||||||
uniform sampler2D baseTexture;
|
uniform sampler2D baseTexture;
|
||||||
uniform sampler2D normalTexture;
|
uniform sampler2D normalTexture;
|
||||||
uniform sampler2D useNormalmap;
|
uniform sampler2D useNormalmap;
|
||||||
|
|
||||||
uniform vec4 skyBgColor;
|
uniform vec4 skyBgColor;
|
||||||
uniform float fogDistance;
|
uniform float fogDistance;
|
||||||
uniform vec3 eyePosition;
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
varying vec3 vPosition;
|
varying vec3 vPosition;
|
||||||
varying vec3 eyeVec;
|
varying vec3 worldPosition;
|
||||||
|
|
||||||
const float e = 2.718281828459;
|
varying vec3 eyeVec;
|
||||||
|
varying vec3 lightVec;
|
||||||
void main (void)
|
|
||||||
{
|
bool normalTexturePresent = false;
|
||||||
vec3 color;
|
|
||||||
vec2 uv = gl_TexCoord[0].st;
|
const float e = 2.718281828459;
|
||||||
|
|
||||||
#ifdef USE_NORMALMAPS
|
float intensity (vec3 color){
|
||||||
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
|
return (color.r + color.g + color.b) / 3.0;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_BUMPMAPPING
|
float get_rgb_height (vec2 uv){
|
||||||
if (use_normalmap > 0.0) {
|
return intensity(texture2D(baseTexture,uv).rgb);
|
||||||
vec3 base = texture2D(baseTexture, uv).rgb;
|
}
|
||||||
vec3 vVec = normalize(eyeVec);
|
|
||||||
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
|
vec4 get_normal_map(vec2 uv){
|
||||||
vec3 R = reflect(-vVec, bump);
|
vec4 bump = texture2D(normalTexture, uv).rgba;
|
||||||
vec3 lVec = normalize(vVec);
|
bump.xyz = normalize(bump.xyz * 2.0 -1.0);
|
||||||
float diffuse = max(dot(lVec, bump), 0.0);
|
bump.y = -bump.y;
|
||||||
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
|
return bump;
|
||||||
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
|
}
|
||||||
} else {
|
|
||||||
color = texture2D(baseTexture, uv).rgb;
|
void main (void)
|
||||||
}
|
{
|
||||||
#else
|
vec3 color;
|
||||||
color = texture2D(baseTexture, uv).rgb;
|
vec4 bump;
|
||||||
#endif
|
vec2 uv = gl_TexCoord[0].st;
|
||||||
|
bool use_normalmap = false;
|
||||||
float alpha = texture2D(baseTexture, uv).a;
|
|
||||||
vec4 col = vec4(color.r, color.g, color.b, alpha);
|
#ifdef USE_NORMALMAPS
|
||||||
col *= gl_Color;
|
if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0){
|
||||||
col = col * col; // SRGB -> Linear
|
bump = get_normal_map(uv);
|
||||||
col *= 1.8;
|
use_normalmap = true;
|
||||||
col.r = 1.0 - exp(1.0 - col.r) / e;
|
}
|
||||||
col.g = 1.0 - exp(1.0 - col.g) / e;
|
#endif
|
||||||
col.b = 1.0 - exp(1.0 - col.b) / e;
|
|
||||||
col = sqrt(col); // Linear -> SRGB
|
#ifdef GENERATE_NORMALMAPS
|
||||||
if(fogDistance != 0.0){
|
if (use_normalmap == false){
|
||||||
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
float tl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y+SAMPLE_STEP));
|
||||||
col = mix(col, skyBgColor, d);
|
float t = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
|
||||||
}
|
float tr = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y+SAMPLE_STEP));
|
||||||
gl_FragColor = vec4(col.r, col.g, col.b, alpha);
|
float r = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y));
|
||||||
}
|
float br = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y-SAMPLE_STEP));
|
||||||
|
float b = get_rgb_height (vec2(uv.x,uv.y-SAMPLE_STEP));
|
||||||
|
float bl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
|
||||||
|
float l = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y));
|
||||||
|
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
|
||||||
|
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
|
||||||
|
bump = vec4 (normalize(vec3 (dX, -dY, NORMALMAPS_STRENGTH)),1.0);
|
||||||
|
use_normalmap = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4 base = texture2D(baseTexture, uv).rgba;
|
||||||
|
|
||||||
|
#ifdef ENABLE_BUMPMAPPING
|
||||||
|
if (use_normalmap){
|
||||||
|
vec3 L = normalize(lightVec);
|
||||||
|
vec3 E = normalize(eyeVec);
|
||||||
|
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0),0.5);
|
||||||
|
float diffuse = dot(E,bump.xyz);
|
||||||
|
color = 0.05*base.rgb + diffuse*base.rgb + 0.2*specular*base.rgb;
|
||||||
|
} else {
|
||||||
|
color = base.rgb;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
color = base.rgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4 col = vec4(color.rgb, base.a);
|
||||||
|
col = col * col; // SRGB -> Linear
|
||||||
|
col *= 1.8;
|
||||||
|
col.r = 1.0 - exp(1.0 - col.r) / e;
|
||||||
|
col.g = 1.0 - exp(1.0 - col.g) / e;
|
||||||
|
col.b = 1.0 - exp(1.0 - col.b) / e;
|
||||||
|
col = sqrt(col); // Linear -> SRGB
|
||||||
|
col *= gl_Color;
|
||||||
|
if(fogDistance != 0.0){
|
||||||
|
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
||||||
|
col = mix(col, skyBgColor, d);
|
||||||
|
}
|
||||||
|
gl_FragColor = vec4(col.rgb, base.a);
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
uniform mat4 mWorldViewProj;
|
uniform mat4 mWorldViewProj;
|
||||||
uniform mat4 mInvWorld;
|
uniform mat4 mInvWorld;
|
||||||
uniform mat4 mTransWorld;
|
uniform mat4 mTransWorld;
|
||||||
|
uniform mat4 mWorld;
|
||||||
|
|
||||||
uniform float dayNightRatio;
|
uniform float dayNightRatio;
|
||||||
uniform float animationTimer;
|
uniform float animationTimer;
|
||||||
|
|
||||||
uniform vec3 eyePosition;
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
varying vec3 vPosition;
|
varying vec3 vPosition;
|
||||||
|
varying vec3 worldPosition;
|
||||||
|
|
||||||
varying vec3 eyeVec;
|
varying vec3 eyeVec;
|
||||||
|
varying vec3 lightVec;
|
||||||
|
|
||||||
|
const float BS = 10.0;
|
||||||
|
|
||||||
#ifdef ENABLE_WAVING_PLANTS
|
#ifdef ENABLE_WAVING_PLANTS
|
||||||
float smoothCurve( float x ) {
|
float smoothCurve( float x ) {
|
||||||
|
@ -23,12 +30,11 @@ float smoothTriangleWave( float x ) {
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
|
|
||||||
#ifdef ENABLE_WAVING_PLANTS
|
#ifdef ENABLE_WAVING_PLANTS
|
||||||
vec4 pos = gl_Vertex;
|
vec4 pos = gl_Vertex;
|
||||||
vec4 pos2 = mTransWorld * gl_Vertex;
|
vec4 pos2 = mWorld * gl_Vertex;
|
||||||
if (gl_TexCoord[0].y < 0.05) {
|
if (gl_TexCoord[0].y < 0.05) {
|
||||||
pos.x += (smoothTriangleWave(animationTimer * 20.0 + pos2.x * 0.1 + pos2.z * 0.1) * 2.0 - 1.0) * 0.8;
|
pos.x += (smoothTriangleWave(animationTimer * 20.0 + pos2.x * 0.1 + pos2.z * 0.1) * 2.0 - 1.0) * 0.8;
|
||||||
pos.y -= (smoothTriangleWave(animationTimer * 10.0 + pos2.x * -0.5 + pos2.z * -0.5) * 2.0 - 1.0) * 0.4;
|
pos.y -= (smoothTriangleWave(animationTimer * 10.0 + pos2.x * -0.5 + pos2.z * -0.5) * 2.0 - 1.0) * 0.4;
|
||||||
|
@ -38,9 +44,13 @@ void main(void)
|
||||||
gl_Position = mWorldViewProj * gl_Vertex;
|
gl_Position = mWorldViewProj * gl_Vertex;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vPosition = (mWorldViewProj * gl_Vertex).xyz;
|
vPosition = gl_Position.xyz;
|
||||||
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
worldPosition = (mWorld * gl_Vertex).xyz;
|
||||||
|
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);
|
||||||
|
|
||||||
|
lightVec = sunPosition - worldPosition;
|
||||||
|
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||||
|
|
||||||
vec4 color;
|
vec4 color;
|
||||||
//color = vec4(1.0, 1.0, 1.0, 1.0);
|
//color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
@ -76,11 +86,8 @@ void main(void)
|
||||||
color = color * color; // SRGB -> Linear
|
color = color * color; // SRGB -> Linear
|
||||||
if(gl_Normal.y <= 0.5)
|
if(gl_Normal.y <= 0.5)
|
||||||
color *= 0.6;
|
color *= 0.6;
|
||||||
//color *= 0.7;
|
|
||||||
color = sqrt(color); // Linear -> SRGB
|
color = sqrt(color); // Linear -> SRGB
|
||||||
|
|
||||||
color.a = gl_Color.a;
|
color.a = gl_Color.a;
|
||||||
|
|
||||||
gl_FrontColor = gl_BackColor = color;
|
gl_FrontColor = gl_BackColor = color;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,90 +1,110 @@
|
||||||
uniform sampler2D baseTexture;
|
uniform sampler2D baseTexture;
|
||||||
uniform sampler2D normalTexture;
|
uniform sampler2D normalTexture;
|
||||||
uniform sampler2D useNormalmap;
|
uniform sampler2D useNormalmap;
|
||||||
|
|
||||||
uniform vec4 skyBgColor;
|
uniform vec4 skyBgColor;
|
||||||
uniform float fogDistance;
|
uniform float fogDistance;
|
||||||
uniform vec3 eyePosition;
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
varying vec3 vPosition;
|
varying vec3 vPosition;
|
||||||
varying vec3 eyeVec;
|
varying vec3 worldPosition;
|
||||||
|
|
||||||
#ifdef ENABLE_PARALLAX_OCCLUSION
|
varying vec3 eyeVec;
|
||||||
varying vec3 tsEyeVec;
|
varying vec3 tsEyeVec;
|
||||||
#endif
|
varying vec3 lightVec;
|
||||||
|
varying vec3 tsLightVec;
|
||||||
const float e = 2.718281828459;
|
|
||||||
|
bool normalTexturePresent = false;
|
||||||
void main (void)
|
|
||||||
{
|
const float e = 2.718281828459;
|
||||||
vec3 color;
|
|
||||||
vec2 uv = gl_TexCoord[0].st;
|
float intensity (vec3 color){
|
||||||
|
return (color.r + color.g + color.b) / 3.0;
|
||||||
#ifdef USE_NORMALMAPS
|
}
|
||||||
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
|
|
||||||
#endif
|
float get_rgb_height (vec2 uv){
|
||||||
|
return intensity(texture2D(baseTexture,uv).rgb);
|
||||||
#ifdef ENABLE_PARALLAX_OCCLUSION
|
}
|
||||||
float height;
|
|
||||||
vec2 tsEye = vec2(tsEyeVec.x,-tsEyeVec.y);
|
vec4 get_normal_map(vec2 uv){
|
||||||
|
vec4 bump = texture2D(normalTexture, uv).rgba;
|
||||||
if (use_normalmap > 0.0) {
|
bump.xyz = normalize(bump.xyz * 2.0 -1.0);
|
||||||
float map_height = texture2D(normalTexture, uv).a;
|
bump.y = -bump.y;
|
||||||
if (map_height < 1.0){
|
return bump;
|
||||||
float height = PARALLAX_OCCLUSION_SCALE * map_height - PARALLAX_OCCLUSION_BIAS;
|
}
|
||||||
uv = uv + height * tsEye;
|
|
||||||
}
|
void main (void)
|
||||||
}
|
{
|
||||||
#endif
|
vec3 color;
|
||||||
|
vec4 bump;
|
||||||
/* Steep parallax code, for future use
|
vec2 uv = gl_TexCoord[0].st;
|
||||||
if ((parallaxMappingMode == 2.0) && (use_normalmap > 0.0)) {
|
bool use_normalmap = false;
|
||||||
const float numSteps = 40.0;
|
|
||||||
float height = 1.0;
|
#ifdef USE_NORMALMAPS
|
||||||
float step = 1.0 / numSteps;
|
if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0){
|
||||||
vec4 NB = texture2D(normalTexture, uv);
|
normalTexturePresent = true;
|
||||||
vec2 delta = tsEye * parallaxMappingScale / numSteps;
|
}
|
||||||
for (float i = 0.0; i < numSteps; i++) {
|
#endif
|
||||||
if (NB.a < height) {
|
|
||||||
height -= step;
|
#ifdef ENABLE_PARALLAX_OCCLUSION
|
||||||
uv += delta;
|
if (normalTexturePresent){
|
||||||
NB = texture2D(normalTexture, uv);
|
vec3 tsEye = normalize(tsEyeVec);
|
||||||
} else {
|
float height = PARALLAX_OCCLUSION_SCALE * texture2D(normalTexture, uv).a - PARALLAX_OCCLUSION_BIAS;
|
||||||
break;
|
uv = uv + texture2D(normalTexture, uv).z * height * vec2(tsEye.x,-tsEye.y);
|
||||||
}
|
}
|
||||||
}
|
#endif
|
||||||
}
|
|
||||||
*/
|
#ifdef USE_NORMALMAPS
|
||||||
|
if (normalTexturePresent){
|
||||||
#ifdef ENABLE_BUMPMAPPING
|
bump = get_normal_map(uv);
|
||||||
if (use_normalmap > 0.0) {
|
use_normalmap = true;
|
||||||
vec3 base = texture2D(baseTexture, uv).rgb;
|
}
|
||||||
vec3 vVec = normalize(eyeVec);
|
#endif
|
||||||
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
|
|
||||||
vec3 R = reflect(-vVec, bump);
|
#ifdef GENERATE_NORMALMAPS
|
||||||
vec3 lVec = normalize(vVec);
|
if (use_normalmap == false){
|
||||||
float diffuse = max(dot(lVec, bump), 0.0);
|
float tl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y+SAMPLE_STEP));
|
||||||
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
|
float t = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
|
||||||
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
|
float tr = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y+SAMPLE_STEP));
|
||||||
} else {
|
float r = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y));
|
||||||
color = texture2D(baseTexture, uv).rgb;
|
float br = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y-SAMPLE_STEP));
|
||||||
}
|
float b = get_rgb_height (vec2(uv.x,uv.y-SAMPLE_STEP));
|
||||||
#else
|
float bl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
|
||||||
color = texture2D(baseTexture, uv).rgb;
|
float l = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y));
|
||||||
#endif
|
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
|
||||||
|
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
|
||||||
float alpha = texture2D(baseTexture, uv).a;
|
bump = vec4 (normalize(vec3 (dX, -dY, NORMALMAPS_STRENGTH)),1.0);
|
||||||
vec4 col = vec4(color.r, color.g, color.b, alpha);
|
use_normalmap = true;
|
||||||
col *= gl_Color;
|
}
|
||||||
col = col * col; // SRGB -> Linear
|
#endif
|
||||||
col *= 1.8;
|
|
||||||
col.r = 1.0 - exp(1.0 - col.r) / e;
|
vec4 base = texture2D(baseTexture, uv).rgba;
|
||||||
col.g = 1.0 - exp(1.0 - col.g) / e;
|
|
||||||
col.b = 1.0 - exp(1.0 - col.b) / e;
|
#ifdef ENABLE_BUMPMAPPING
|
||||||
col = sqrt(col); // Linear -> SRGB
|
if (use_normalmap){
|
||||||
if(fogDistance != 0.0){
|
vec3 L = normalize(lightVec);
|
||||||
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
vec3 E = normalize(eyeVec);
|
||||||
col = mix(col, skyBgColor, d);
|
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0),0.5);
|
||||||
}
|
float diffuse = dot(E,bump.xyz);
|
||||||
gl_FragColor = vec4(col.r, col.g, col.b, alpha);
|
color = 0.05*base.rgb + diffuse*base.rgb + 0.2*specular*base.rgb;
|
||||||
}
|
} else {
|
||||||
|
color = base.rgb;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
color = base.rgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4 col = vec4(color.rgb, base.a);
|
||||||
|
col = col * col; // SRGB -> Linear
|
||||||
|
col *= 1.8;
|
||||||
|
col.r = 1.0 - exp(1.0 - col.r) / e;
|
||||||
|
col.g = 1.0 - exp(1.0 - col.g) / e;
|
||||||
|
col.b = 1.0 - exp(1.0 - col.b) / e;
|
||||||
|
col = sqrt(col); // Linear -> SRGB
|
||||||
|
col *= gl_Color;
|
||||||
|
if(fogDistance != 0.0){
|
||||||
|
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
|
||||||
|
col = mix(col, skyBgColor, d);
|
||||||
|
}
|
||||||
|
gl_FragColor = vec4(col.rgb, base.a);
|
||||||
|
}
|
||||||
|
|
|
@ -1,27 +1,33 @@
|
||||||
uniform mat4 mWorldViewProj;
|
uniform mat4 mWorldViewProj;
|
||||||
uniform mat4 mInvWorld;
|
uniform mat4 mInvWorld;
|
||||||
uniform mat4 mTransWorld;
|
uniform mat4 mTransWorld;
|
||||||
|
uniform mat4 mWorld;
|
||||||
|
|
||||||
uniform float dayNightRatio;
|
uniform float dayNightRatio;
|
||||||
|
|
||||||
uniform vec3 eyePosition;
|
uniform vec3 eyePosition;
|
||||||
|
|
||||||
varying vec3 vPosition;
|
varying vec3 vPosition;
|
||||||
varying vec3 eyeVec;
|
varying vec3 worldPosition;
|
||||||
|
|
||||||
|
varying vec3 eyeVec;
|
||||||
|
varying vec3 lightVec;
|
||||||
|
|
||||||
#ifdef ENABLE_PARALLAX_OCCLUSION
|
|
||||||
varying vec3 tsEyeVec;
|
varying vec3 tsEyeVec;
|
||||||
#endif
|
varying vec3 tsLightVec;
|
||||||
|
|
||||||
|
const float BS = 10.0;
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
gl_Position = mWorldViewProj * gl_Vertex;
|
gl_Position = mWorldViewProj * gl_Vertex;
|
||||||
vPosition = (mWorldViewProj * gl_Vertex).xyz;
|
vPosition = gl_Position.xyz;
|
||||||
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
worldPosition = (mWorld * gl_Vertex).xyz;
|
||||||
|
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);
|
||||||
|
|
||||||
#ifdef ENABLE_PARALLAX_OCCLUSION
|
vec3 normal, tangent, binormal;
|
||||||
vec3 normal,tangent,binormal;
|
|
||||||
normal = normalize(gl_NormalMatrix * gl_Normal);
|
normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||||
|
|
||||||
if (gl_Normal.x > 0.5) {
|
if (gl_Normal.x > 0.5) {
|
||||||
// 1.0, 0.0, 0.0
|
// 1.0, 0.0, 0.0
|
||||||
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, -1.0));
|
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, -1.0));
|
||||||
|
@ -47,25 +53,20 @@ void main(void)
|
||||||
tangent = normalize(gl_NormalMatrix * vec3(-1.0, 0.0, 0.0));
|
tangent = normalize(gl_NormalMatrix * vec3(-1.0, 0.0, 0.0));
|
||||||
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
|
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
mat3 tbnMatrix = mat3( tangent.x, binormal.x, normal.x,
|
mat3 tbnMatrix = mat3( tangent.x, binormal.x, normal.x,
|
||||||
tangent.y, binormal.y, normal.y,
|
tangent.y, binormal.y, normal.y,
|
||||||
tangent.z, binormal.z, normal.z);
|
tangent.z, binormal.z, normal.z);
|
||||||
|
|
||||||
tsEyeVec = normalize(eyeVec * tbnMatrix);
|
lightVec = sunPosition - worldPosition;
|
||||||
#endif
|
tsLightVec = lightVec * tbnMatrix;
|
||||||
|
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||||
|
tsEyeVec = eyeVec * tbnMatrix;
|
||||||
|
|
||||||
vec4 color;
|
vec4 color;
|
||||||
//color = vec4(1.0, 1.0, 1.0, 1.0);
|
|
||||||
|
|
||||||
float day = gl_Color.r;
|
float day = gl_Color.r;
|
||||||
float night = gl_Color.g;
|
float night = gl_Color.g;
|
||||||
float light_source = gl_Color.b;
|
float light_source = gl_Color.b;
|
||||||
|
|
||||||
/*color.r = mix(night, day, dayNightRatio);
|
|
||||||
color.g = color.r;
|
|
||||||
color.b = color.r;*/
|
|
||||||
|
|
||||||
float rg = mix(night, day, dayNightRatio);
|
float rg = mix(night, day, dayNightRatio);
|
||||||
rg += light_source * 2.5; // Make light sources brighter
|
rg += light_source * 2.5; // Make light sources brighter
|
||||||
float b = rg;
|
float b = rg;
|
||||||
|
@ -90,13 +91,8 @@ void main(void)
|
||||||
color = color * color; // SRGB -> Linear
|
color = color * color; // SRGB -> Linear
|
||||||
if(gl_Normal.y <= 0.5)
|
if(gl_Normal.y <= 0.5)
|
||||||
color *= 0.6;
|
color *= 0.6;
|
||||||
//color *= 0.7;
|
|
||||||
color = sqrt(color); // Linear -> SRGB
|
color = sqrt(color); // Linear -> SRGB
|
||||||
|
|
||||||
color.a = gl_Color.a;
|
color.a = gl_Color.a;
|
||||||
|
|
||||||
gl_FrontColor = gl_BackColor = color;
|
gl_FrontColor = gl_BackColor = color;
|
||||||
|
|
||||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -849,7 +849,7 @@ Example stuff:
|
||||||
|
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
meta:set_string("formspec",
|
meta:set_string("formspec",
|
||||||
"invsize[8,9;]"..
|
"size[8,9]"..
|
||||||
"list[context;main;0,0;8,4;]"..
|
"list[context;main;0,0;8,4;]"..
|
||||||
"list[current_player;main;0,5;8,4;]")
|
"list[current_player;main;0,5;8,4;]")
|
||||||
meta:set_string("infotext", "Chest");
|
meta:set_string("infotext", "Chest");
|
||||||
|
@ -861,7 +861,7 @@ meta:from_table({
|
||||||
main = {[1] = "default:dirt", [2] = "", [3] = "", [4] = "", [5] = "", [6] = "", [7] = "", [8] = "", [9] = "", [10] = "", [11] = "", [12] = "", [13] = "", [14] = "default:cobble", [15] = "", [16] = "", [17] = "", [18] = "", [19] = "", [20] = "default:cobble", [21] = "", [22] = "", [23] = "", [24] = "", [25] = "", [26] = "", [27] = "", [28] = "", [29] = "", [30] = "", [31] = "", [32] = ""}
|
main = {[1] = "default:dirt", [2] = "", [3] = "", [4] = "", [5] = "", [6] = "", [7] = "", [8] = "", [9] = "", [10] = "", [11] = "", [12] = "", [13] = "", [14] = "default:cobble", [15] = "", [16] = "", [17] = "", [18] = "", [19] = "", [20] = "default:cobble", [21] = "", [22] = "", [23] = "", [24] = "", [25] = "", [26] = "", [27] = "", [28] = "", [29] = "", [30] = "", [31] = "", [32] = ""}
|
||||||
},
|
},
|
||||||
fields = {
|
fields = {
|
||||||
formspec = "invsize[8,9;]list[context;main;0,0;8,4;]list[current_player;main;0,5;8,4;]",
|
formspec = "size[8,9]list[context;main;0,0;8,4;]list[current_player;main;0,5;8,4;]",
|
||||||
infotext = "Chest"
|
infotext = "Chest"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -876,17 +876,17 @@ examples.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
- Chest:
|
- Chest:
|
||||||
invsize[8,9;]
|
size[8,9]
|
||||||
list[context;main;0,0;8,4;]
|
list[context;main;0,0;8,4;]
|
||||||
list[current_player;main;0,5;8,4;]
|
list[current_player;main;0,5;8,4;]
|
||||||
- Furnace:
|
- Furnace:
|
||||||
invsize[8,9;]
|
size[8,9]
|
||||||
list[context;fuel;2,3;1,1;]
|
list[context;fuel;2,3;1,1;]
|
||||||
list[context;src;2,1;1,1;]
|
list[context;src;2,1;1,1;]
|
||||||
list[context;dst;5,1;2,2;]
|
list[context;dst;5,1;2,2;]
|
||||||
list[current_player;main;0,5;8,4;]
|
list[current_player;main;0,5;8,4;]
|
||||||
- Minecraft-like player inventory
|
- Minecraft-like player inventory
|
||||||
invsize[8,7.5;]
|
size[8,7.5]
|
||||||
image[1,0.6;1,2;player.png]
|
image[1,0.6;1,2;player.png]
|
||||||
list[current_player;main;0,3.5;8,4;]
|
list[current_player;main;0,3.5;8,4;]
|
||||||
list[current_player;craft;3,0;3,3;]
|
list[current_player;craft;3,0;3,3;]
|
||||||
|
@ -894,8 +894,9 @@ Examples:
|
||||||
|
|
||||||
Elements:
|
Elements:
|
||||||
|
|
||||||
size[<W>,<H>]
|
size[<W>,<H>,<fixed_size>]
|
||||||
^ Define the size of the menu in inventory slots
|
^ Define the size of the menu in inventory slots
|
||||||
|
^ fixed_size true/false (optional)
|
||||||
^ deprecated: invsize[<W>,<H>;]
|
^ deprecated: invsize[<W>,<H>;]
|
||||||
|
|
||||||
list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;]
|
list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;]
|
||||||
|
@ -1199,6 +1200,29 @@ minetest.features
|
||||||
minetest.has_feature(arg) -> bool, missing_features
|
minetest.has_feature(arg) -> bool, missing_features
|
||||||
^ arg: string or table in format {foo=true, bar=true}
|
^ arg: string or table in format {foo=true, bar=true}
|
||||||
^ missing_features: {foo=true, bar=true}
|
^ missing_features: {foo=true, bar=true}
|
||||||
|
minetest.get_player_information(playername)
|
||||||
|
^ table containing information about player peer:
|
||||||
|
{
|
||||||
|
address = "127.0.0.1", -- ip address of client
|
||||||
|
ip_version = 4, -- IPv4 / IPv6
|
||||||
|
min_rtt = 0.01, -- minimum round trip time
|
||||||
|
max_rtt = 0.2, -- maximum round trip time
|
||||||
|
avg_rtt = 0.02, -- average round trip time
|
||||||
|
min_jitter = 0.01, -- minimum packet time jitter
|
||||||
|
max_jitter = 0.5, -- maximum packet time jitter
|
||||||
|
avg_jitter = 0.03, -- average packet time jitter
|
||||||
|
connection_uptime = 200, -- seconds since client connected
|
||||||
|
|
||||||
|
-- following information is available on debug build only!!!
|
||||||
|
-- DO NOT USE IN MODS
|
||||||
|
--ser_vers = 26, -- serialization version used by client
|
||||||
|
--prot_vers = 23, -- protocol version used by client
|
||||||
|
--major = 0, -- major version number
|
||||||
|
--minor = 4, -- minor version number
|
||||||
|
--patch = 10, -- patch version number
|
||||||
|
--vers_string = "0.4.9-git", -- full version string
|
||||||
|
--state = "Active" -- current client state
|
||||||
|
}
|
||||||
|
|
||||||
Logging:
|
Logging:
|
||||||
minetest.debug(line)
|
minetest.debug(line)
|
||||||
|
@ -1419,10 +1443,6 @@ minetest.set_node_level(pos, level)
|
||||||
^ set level of leveled node, default level = 1, if totallevel > maxlevel returns rest (total-max).
|
^ set level of leveled node, default level = 1, if totallevel > maxlevel returns rest (total-max).
|
||||||
minetest.add_node_level(pos, level)
|
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
|
^ 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
|
||||||
|
@ -1850,6 +1870,15 @@ Player-only: (no-op for other objects)
|
||||||
- override_day_night_ratio(ratio or nil)
|
- override_day_night_ratio(ratio or nil)
|
||||||
^ 0...1: Overrides day-night ratio, controlling sunlight to a specific amount
|
^ 0...1: Overrides day-night ratio, controlling sunlight to a specific amount
|
||||||
^ nil: Disables override, defaulting to sunlight based on day-night cycle
|
^ nil: Disables override, defaulting to sunlight based on day-night cycle
|
||||||
|
- set_local_animation({x=0, y=79}, {x=168, y=187}, {x=189, y=198}, {x=200, y=219}, frame_speed=30): set animation for player model in third person view
|
||||||
|
^ stand/idle animation key frames
|
||||||
|
^ walk animation key frames
|
||||||
|
^ dig animation key frames
|
||||||
|
^ walk+dig animation key frames
|
||||||
|
^ animation frame speed
|
||||||
|
- set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0}): defines offset value for camera per player
|
||||||
|
^ in first person view
|
||||||
|
^ in third person view (max. values {x=-10/10,y=-10,15,z=-5/5})
|
||||||
|
|
||||||
InvRef: Reference to an inventory
|
InvRef: Reference to an inventory
|
||||||
methods:
|
methods:
|
||||||
|
|
|
@ -93,24 +93,10 @@
|
||||||
#enable_fog = true
|
#enable_fog = true
|
||||||
# Enable a bit lower water surface; disable for speed (not quite optimized)
|
# Enable a bit lower water surface; disable for speed (not quite optimized)
|
||||||
#new_style_water = false
|
#new_style_water = false
|
||||||
# Constant volume liquids
|
|
||||||
#liquid_finite = false
|
|
||||||
# Max liquids processed per step
|
# Max liquids processed per step
|
||||||
#liquid_loop_max = 10000
|
#liquid_loop_max = 10000
|
||||||
# Update liquids every .. recommend for finite: 0.2
|
# Update liquids every .. recommend for finite: 0.2
|
||||||
#liquid_update = 1.0
|
#liquid_update = 1.0
|
||||||
# Relax flowing blocks to source if level near max and N nearby
|
|
||||||
# source blocks, more realistic, but not true constant.
|
|
||||||
# values: 0,1,2,3,4 : 0 - disable, 1 - most aggresive
|
|
||||||
# (for finite liquids)
|
|
||||||
#liquid_relax = 2
|
|
||||||
# Optimization: faster cave flood (and not true constant)
|
|
||||||
# (for finite liquids)
|
|
||||||
#liquid_fast_flood = 1
|
|
||||||
# Underground water and lava springs, its infnity sources if liquid_finite enabled
|
|
||||||
#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;
|
||||||
|
@ -173,6 +159,14 @@
|
||||||
# Set to true to enable textures bumpmapping. Requires shaders enabled.
|
# Set to true to enable textures bumpmapping. Requires shaders enabled.
|
||||||
#enable_bumpmapping = false
|
#enable_bumpmapping = false
|
||||||
# Set to true enables parallax occlusion mapping. Requires shaders enabled.
|
# Set to true enables parallax occlusion mapping. Requires shaders enabled.
|
||||||
|
#generate_normalmaps = false
|
||||||
|
# Set to true enables on the fly normalmap generation (Emboss effect).
|
||||||
|
# Requires bumpmapping enabled.
|
||||||
|
#normalmaps_strength = 0.6
|
||||||
|
# Strength of generated normalmaps
|
||||||
|
#normalmaps_smooth = 1
|
||||||
|
# Defines sampling step of texture (0 - 2)
|
||||||
|
# Higher the value normal maps will be smoother
|
||||||
#enable_parallax_occlusion = false
|
#enable_parallax_occlusion = false
|
||||||
# Scale of parallax occlusion effect
|
# Scale of parallax occlusion effect
|
||||||
#parallax_occlusion_scale = 0.08
|
#parallax_occlusion_scale = 0.08
|
||||||
|
@ -353,6 +347,7 @@
|
||||||
# try reducing it, but don't reduce it to a number below double of targeted
|
# try reducing it, but don't reduce it to a number below double of targeted
|
||||||
# client number
|
# client number
|
||||||
#max_packets_per_iteration = 1024
|
#max_packets_per_iteration = 1024
|
||||||
|
|
||||||
#
|
#
|
||||||
# Physics stuff
|
# Physics stuff
|
||||||
#
|
#
|
||||||
|
@ -430,6 +425,7 @@
|
||||||
#enable_ipv6 = true
|
#enable_ipv6 = true
|
||||||
# Enable/disable running an IPv6 server. An IPv6 server may be restricted
|
# Enable/disable running an IPv6 server. An IPv6 server may be restricted
|
||||||
# to IPv6 clients, depending on system configuration.
|
# to IPv6 clients, depending on system configuration.
|
||||||
|
# Ignored if bind_address is set.
|
||||||
#ipv6_server = false
|
#ipv6_server = false
|
||||||
|
|
||||||
#main_menu_script =
|
#main_menu_script =
|
||||||
|
|
|
@ -291,6 +291,25 @@ if(ENABLE_LEVELDB)
|
||||||
endif(LEVELDB_LIBRARY AND LEVELDB_INCLUDE_DIR)
|
endif(LEVELDB_LIBRARY AND LEVELDB_INCLUDE_DIR)
|
||||||
endif(ENABLE_LEVELDB)
|
endif(ENABLE_LEVELDB)
|
||||||
|
|
||||||
|
set(USE_REDIS 0)
|
||||||
|
|
||||||
|
OPTION(ENABLE_REDIS "Enable redis backend" 1)
|
||||||
|
|
||||||
|
if(ENABLE_REDIS)
|
||||||
|
find_library(REDIS_LIBRARY hiredis)
|
||||||
|
find_path(REDIS_INCLUDE_DIR hiredis.h PATH_SUFFIXES hiredis)
|
||||||
|
message(STATUS "redis library: ${REDIS_LIBRARY}")
|
||||||
|
message(STATUS "redis headers: ${REDIS_INCLUDE_DIR}")
|
||||||
|
if(REDIS_LIBRARY AND REDIS_INCLUDE_DIR)
|
||||||
|
set(USE_REDIS 1)
|
||||||
|
message(STATUS "redis backend enabled")
|
||||||
|
include_directories(${REDIS_INCLUDE_DIR})
|
||||||
|
else(REDIS_LIBRARY AND REDIS_INCLUDE_DIR)
|
||||||
|
set(USE_REDIS 0)
|
||||||
|
message(STATUS "redis not found!")
|
||||||
|
endif(REDIS_LIBRARY AND REDIS_INCLUDE_DIR)
|
||||||
|
endif(ENABLE_REDIS)
|
||||||
|
|
||||||
configure_file(
|
configure_file(
|
||||||
"${PROJECT_SOURCE_DIR}/cmake_config.h.in"
|
"${PROJECT_SOURCE_DIR}/cmake_config.h.in"
|
||||||
"${PROJECT_BINARY_DIR}/cmake_config.h"
|
"${PROJECT_BINARY_DIR}/cmake_config.h"
|
||||||
|
@ -368,6 +387,7 @@ set(common_SRCS
|
||||||
database-dummy.cpp
|
database-dummy.cpp
|
||||||
database-leveldb.cpp
|
database-leveldb.cpp
|
||||||
database-sqlite3.cpp
|
database-sqlite3.cpp
|
||||||
|
database-redis.cpp
|
||||||
player.cpp
|
player.cpp
|
||||||
test.cpp
|
test.cpp
|
||||||
sha1.cpp
|
sha1.cpp
|
||||||
|
@ -393,7 +413,7 @@ if(WIN32)
|
||||||
set(CMAKE_RC_COMPILER "windres.exe")
|
set(CMAKE_RC_COMPILER "windres.exe")
|
||||||
endif()
|
endif()
|
||||||
ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o
|
ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o
|
||||||
COMMAND ${CMAKE_RC_COMPILER} -I${CMAKE_CURRENT_SOURCE_DIR}
|
COMMAND ${CMAKE_RC_COMPILER} -I${CMAKE_CURRENT_SOURCE_DIR} -I${CMAKE_CURRENT_BINARY_DIR}
|
||||||
-i${WINRESOURCE_FILE}
|
-i${WINRESOURCE_FILE}
|
||||||
-o ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o
|
-o ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
@ -424,11 +444,9 @@ set(minetest_SRCS
|
||||||
chat.cpp
|
chat.cpp
|
||||||
hud.cpp
|
hud.cpp
|
||||||
guiKeyChangeMenu.cpp
|
guiKeyChangeMenu.cpp
|
||||||
guiMessageMenu.cpp
|
|
||||||
guiTextInputMenu.cpp
|
guiTextInputMenu.cpp
|
||||||
guiFormSpecMenu.cpp
|
guiFormSpecMenu.cpp
|
||||||
guiTable.cpp
|
guiTable.cpp
|
||||||
guiPauseMenu.cpp
|
|
||||||
guiPasswordChange.cpp
|
guiPasswordChange.cpp
|
||||||
guiVolumeChange.cpp
|
guiVolumeChange.cpp
|
||||||
guiDeathScreen.cpp
|
guiDeathScreen.cpp
|
||||||
|
@ -535,6 +553,9 @@ if(BUILD_CLIENT)
|
||||||
if (USE_LEVELDB)
|
if (USE_LEVELDB)
|
||||||
target_link_libraries(${PROJECT_NAME} ${LEVELDB_LIBRARY})
|
target_link_libraries(${PROJECT_NAME} ${LEVELDB_LIBRARY})
|
||||||
endif(USE_LEVELDB)
|
endif(USE_LEVELDB)
|
||||||
|
if (USE_REDIS)
|
||||||
|
target_link_libraries(${PROJECT_NAME} ${REDIS_LIBRARY})
|
||||||
|
endif(USE_REDIS)
|
||||||
endif(BUILD_CLIENT)
|
endif(BUILD_CLIENT)
|
||||||
|
|
||||||
if(BUILD_SERVER)
|
if(BUILD_SERVER)
|
||||||
|
@ -552,6 +573,9 @@ if(BUILD_SERVER)
|
||||||
if (USE_LEVELDB)
|
if (USE_LEVELDB)
|
||||||
target_link_libraries(${PROJECT_NAME}server ${LEVELDB_LIBRARY})
|
target_link_libraries(${PROJECT_NAME}server ${LEVELDB_LIBRARY})
|
||||||
endif(USE_LEVELDB)
|
endif(USE_LEVELDB)
|
||||||
|
if (USE_REDIS)
|
||||||
|
target_link_libraries(${PROJECT_NAME}server ${REDIS_LIBRARY})
|
||||||
|
endif(USE_REDIS)
|
||||||
if(USE_CURL)
|
if(USE_CURL)
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
${PROJECT_NAME}server
|
${PROJECT_NAME}server
|
||||||
|
|
|
@ -203,54 +203,3 @@ u8 BiomeDefManager::getBiomeIdByName(const char *name) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////// Weather
|
|
||||||
|
|
||||||
|
|
||||||
s16 BiomeDefManager::calcBlockHeat(v3s16 p, u64 seed, float timeofday, float totaltime) {
|
|
||||||
//variant 1: full random
|
|
||||||
//f32 heat = NoisePerlin3D(np_heat, p.X, env->getGameTime()/100, p.Z, seed);
|
|
||||||
|
|
||||||
//variant 2: season change based on default heat map
|
|
||||||
const f32 offset = 20; // = np_heat->offset
|
|
||||||
const f32 scale = 20; // = np_heat->scale
|
|
||||||
const f32 range = 20;
|
|
||||||
f32 heat = NoisePerlin2D(np_heat, p.X, p.Z, seed); // 0..50..100
|
|
||||||
|
|
||||||
heat -= np_heat->offset; // -50..0..+50
|
|
||||||
|
|
||||||
// normalizing - todo REMOVE after fixed NoiseParams nparams_biome_def_heat = {50, 50, -> 20, 50,
|
|
||||||
if (np_heat->scale)
|
|
||||||
heat /= np_heat->scale / scale; // -20..0..+20
|
|
||||||
|
|
||||||
f32 seasonv = totaltime;
|
|
||||||
seasonv /= 86400 * g_settings->getS16("year_days"); // season change speed
|
|
||||||
seasonv += (f32)p.X / 3000; // you can walk to area with other season
|
|
||||||
seasonv = sin(seasonv * M_PI);
|
|
||||||
heat += (range * (heat < 0 ? 2 : 0.5)) * seasonv; // -60..0..30
|
|
||||||
|
|
||||||
heat += offset; // -40..0..50
|
|
||||||
heat += p.Y / -333; // upper=colder, lower=hotter, 3c per 1000
|
|
||||||
|
|
||||||
// daily change, hotter at sun +4, colder at night -4
|
|
||||||
heat += 8 * (sin(cycle_shift(timeofday, -0.25) * M_PI) - 0.5); //-44..20..54
|
|
||||||
|
|
||||||
return heat;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
s16 BiomeDefManager::calcBlockHumidity(v3s16 p, u64 seed, float timeofday, float totaltime) {
|
|
||||||
|
|
||||||
f32 humidity = NoisePerlin2D(np_humidity, p.X, p.Z, seed);
|
|
||||||
|
|
||||||
f32 seasonv = totaltime;
|
|
||||||
seasonv /= 86400 * 2; // bad weather change speed (2 days)
|
|
||||||
seasonv += (f32)p.Z / 300;
|
|
||||||
humidity += 30 * sin(seasonv * M_PI);
|
|
||||||
|
|
||||||
humidity += -12 * (sin(cycle_shift(timeofday, -0.1) * M_PI) - 0.5);
|
|
||||||
humidity = rangelim(humidity, 0, 100);
|
|
||||||
|
|
||||||
return humidity;
|
|
||||||
}
|
|
||||||
|
|
|
@ -40,9 +40,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#define CAMERA_OFFSET_STEP 200
|
#define CAMERA_OFFSET_STEP 200
|
||||||
|
|
||||||
|
#include "nodedef.h"
|
||||||
|
|
||||||
Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control,
|
Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control,
|
||||||
IGameDef *gamedef):
|
IGameDef *gamedef):
|
||||||
m_smgr(smgr),
|
|
||||||
m_playernode(NULL),
|
m_playernode(NULL),
|
||||||
m_headnode(NULL),
|
m_headnode(NULL),
|
||||||
m_cameranode(NULL),
|
m_cameranode(NULL),
|
||||||
|
@ -248,7 +249,8 @@ void Camera::step(f32 dtime)
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
|
void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
|
||||||
v2u32 screensize, f32 tool_reload_ratio)
|
v2u32 screensize, f32 tool_reload_ratio,
|
||||||
|
int current_camera_mode, ClientEnvironment &c_env)
|
||||||
{
|
{
|
||||||
// Get player position
|
// Get player position
|
||||||
// Smooth the movement when walking up stairs
|
// Smooth the movement when walking up stairs
|
||||||
|
@ -276,7 +278,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
|
||||||
|
|
||||||
// Fall bobbing animation
|
// Fall bobbing animation
|
||||||
float fall_bobbing = 0;
|
float fall_bobbing = 0;
|
||||||
if(player->camera_impact >= 1)
|
if(player->camera_impact >= 1 && current_camera_mode < CAMERA_MODE_THIRD)
|
||||||
{
|
{
|
||||||
if(m_view_bobbing_fall == -1) // Effect took place and has finished
|
if(m_view_bobbing_fall == -1) // Effect took place and has finished
|
||||||
player->camera_impact = m_view_bobbing_fall = 0;
|
player->camera_impact = m_view_bobbing_fall = 0;
|
||||||
|
@ -293,8 +295,15 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
|
||||||
fall_bobbing *= g_settings->getFloat("fall_bobbing_amount");
|
fall_bobbing *= g_settings->getFloat("fall_bobbing_amount");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate players eye offset for different camera modes
|
||||||
|
v3f PlayerEyeOffset = player->getEyeOffset();
|
||||||
|
if (current_camera_mode == CAMERA_MODE_FIRST)
|
||||||
|
PlayerEyeOffset += player->eye_offset_first;
|
||||||
|
else
|
||||||
|
PlayerEyeOffset += player->eye_offset_third;
|
||||||
|
|
||||||
// Set head node transformation
|
// Set head node transformation
|
||||||
m_headnode->setPosition(player->getEyeOffset()+v3f(0,cameratilt*-player->hurt_tilt_strength+fall_bobbing,0));
|
m_headnode->setPosition(PlayerEyeOffset+v3f(0,cameratilt*-player->hurt_tilt_strength+fall_bobbing,0));
|
||||||
m_headnode->setRotation(v3f(player->getPitch(), 0, cameratilt*player->hurt_tilt_strength));
|
m_headnode->setRotation(v3f(player->getPitch(), 0, cameratilt*player->hurt_tilt_strength));
|
||||||
m_headnode->updateAbsolutePosition();
|
m_headnode->updateAbsolutePosition();
|
||||||
|
|
||||||
|
@ -303,7 +312,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
|
||||||
v3f rel_cam_target = v3f(0,0,1);
|
v3f rel_cam_target = v3f(0,0,1);
|
||||||
v3f rel_cam_up = v3f(0,1,0);
|
v3f rel_cam_up = v3f(0,1,0);
|
||||||
|
|
||||||
if (m_view_bobbing_anim != 0)
|
if (m_view_bobbing_anim != 0 && current_camera_mode < CAMERA_MODE_THIRD)
|
||||||
{
|
{
|
||||||
f32 bobfrac = my_modf(m_view_bobbing_anim * 2);
|
f32 bobfrac = my_modf(m_view_bobbing_anim * 2);
|
||||||
f32 bobdir = (m_view_bobbing_anim < 0.5) ? 1.0 : -1.0;
|
f32 bobdir = (m_view_bobbing_anim < 0.5) ? 1.0 : -1.0;
|
||||||
|
@ -352,19 +361,60 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
|
||||||
v3f abs_cam_up;
|
v3f abs_cam_up;
|
||||||
m_headnode->getAbsoluteTransformation().rotateVect(abs_cam_up, rel_cam_up);
|
m_headnode->getAbsoluteTransformation().rotateVect(abs_cam_up, rel_cam_up);
|
||||||
|
|
||||||
|
// Seperate camera position for calculation
|
||||||
|
v3f my_cp = m_camera_position;
|
||||||
|
|
||||||
|
// Reposition the camera for third person view
|
||||||
|
if (current_camera_mode > CAMERA_MODE_FIRST) {
|
||||||
|
|
||||||
|
if (current_camera_mode == CAMERA_MODE_THIRD_FRONT)
|
||||||
|
m_camera_direction *= -1;
|
||||||
|
|
||||||
|
my_cp.Y += 2;
|
||||||
|
|
||||||
|
// Calculate new position
|
||||||
|
bool abort = false;
|
||||||
|
for (int i = BS; i <= BS*2; i++) {
|
||||||
|
my_cp.X = m_camera_position.X + m_camera_direction.X*-i;
|
||||||
|
my_cp.Z = m_camera_position.Z + m_camera_direction.Z*-i;
|
||||||
|
if (i > 12)
|
||||||
|
my_cp.Y = m_camera_position.Y + (m_camera_direction.Y*-i);
|
||||||
|
|
||||||
|
// Prevent camera positioned inside nodes
|
||||||
|
INodeDefManager *nodemgr = m_gamedef->ndef();
|
||||||
|
MapNode n = c_env.getClientMap().getNodeNoEx(floatToInt(my_cp, BS));
|
||||||
|
const ContentFeatures& features = nodemgr->get(n);
|
||||||
|
if(features.walkable) {
|
||||||
|
my_cp.X += m_camera_direction.X*-1*-BS/2;
|
||||||
|
my_cp.Z += m_camera_direction.Z*-1*-BS/2;
|
||||||
|
my_cp.Y += m_camera_direction.Y*-1*-BS/2;
|
||||||
|
abort = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If node blocks camera position don't move y to heigh
|
||||||
|
if (abort && my_cp.Y > player_position.Y+BS*2)
|
||||||
|
my_cp.Y = player_position.Y+BS*2;
|
||||||
|
}
|
||||||
|
|
||||||
// Update offset if too far away from the center of the map
|
// Update offset if too far away from the center of the map
|
||||||
m_camera_offset.X += CAMERA_OFFSET_STEP*
|
m_camera_offset.X += CAMERA_OFFSET_STEP*
|
||||||
(((s16)(m_camera_position.X/BS) - m_camera_offset.X)/CAMERA_OFFSET_STEP);
|
(((s16)(my_cp.X/BS) - m_camera_offset.X)/CAMERA_OFFSET_STEP);
|
||||||
m_camera_offset.Y += CAMERA_OFFSET_STEP*
|
m_camera_offset.Y += CAMERA_OFFSET_STEP*
|
||||||
(((s16)(m_camera_position.Y/BS) - m_camera_offset.Y)/CAMERA_OFFSET_STEP);
|
(((s16)(my_cp.Y/BS) - m_camera_offset.Y)/CAMERA_OFFSET_STEP);
|
||||||
m_camera_offset.Z += CAMERA_OFFSET_STEP*
|
m_camera_offset.Z += CAMERA_OFFSET_STEP*
|
||||||
(((s16)(m_camera_position.Z/BS) - m_camera_offset.Z)/CAMERA_OFFSET_STEP);
|
(((s16)(my_cp.Z/BS) - m_camera_offset.Z)/CAMERA_OFFSET_STEP);
|
||||||
|
|
||||||
// Set camera node transformation
|
// Set camera node transformation
|
||||||
m_cameranode->setPosition(m_camera_position-intToFloat(m_camera_offset, BS));
|
m_cameranode->setPosition(my_cp-intToFloat(m_camera_offset, BS));
|
||||||
m_cameranode->setUpVector(abs_cam_up);
|
m_cameranode->setUpVector(abs_cam_up);
|
||||||
// *100.0 helps in large map coordinates
|
// *100.0 helps in large map coordinates
|
||||||
m_cameranode->setTarget(m_camera_position-intToFloat(m_camera_offset, BS) + 100 * m_camera_direction);
|
m_cameranode->setTarget(my_cp-intToFloat(m_camera_offset, BS) + 100 * m_camera_direction);
|
||||||
|
|
||||||
|
// update the camera position in front-view mode to render blocks behind player
|
||||||
|
if (current_camera_mode == CAMERA_MODE_THIRD_FRONT)
|
||||||
|
m_camera_position = my_cp;
|
||||||
|
|
||||||
// Get FOV setting
|
// Get FOV setting
|
||||||
f32 fov_degrees = g_settings->getFloat("fov");
|
f32 fov_degrees = g_settings->getFloat("fov");
|
||||||
|
|
10
src/camera.h
10
src/camera.h
|
@ -27,10 +27,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "util/numeric.h"
|
#include "util/numeric.h"
|
||||||
#include <ICameraSceneNode.h>
|
#include <ICameraSceneNode.h>
|
||||||
|
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
class LocalPlayer;
|
class LocalPlayer;
|
||||||
struct MapDrawControl;
|
struct MapDrawControl;
|
||||||
class IGameDef;
|
class IGameDef;
|
||||||
|
|
||||||
|
enum CameraModes {CAMERA_MODE_FIRST, CAMERA_MODE_THIRD, CAMERA_MODE_THIRD_FRONT};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Client camera class, manages the player and camera scene nodes, the viewing distance
|
Client camera class, manages the player and camera scene nodes, the viewing distance
|
||||||
and performs view bobbing etc. It also displays the wielded tool in front of the
|
and performs view bobbing etc. It also displays the wielded tool in front of the
|
||||||
|
@ -113,7 +117,8 @@ public:
|
||||||
// Update the camera from the local player's position.
|
// Update the camera from the local player's position.
|
||||||
// busytime is used to adjust the viewing range.
|
// busytime is used to adjust the viewing range.
|
||||||
void update(LocalPlayer* player, f32 frametime, f32 busytime,
|
void update(LocalPlayer* player, f32 frametime, f32 busytime,
|
||||||
v2u32 screensize, f32 tool_reload_ratio);
|
v2u32 screensize, f32 tool_reload_ratio,
|
||||||
|
int current_camera_mode, ClientEnvironment &c_env);
|
||||||
|
|
||||||
// Render distance feedback loop
|
// Render distance feedback loop
|
||||||
void updateViewingRange(f32 frametime_in, f32 busytime_in);
|
void updateViewingRange(f32 frametime_in, f32 busytime_in);
|
||||||
|
@ -131,8 +136,7 @@ public:
|
||||||
void drawWieldedTool();
|
void drawWieldedTool();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Scene manager and nodes
|
// Nodes
|
||||||
scene::ISceneManager* m_smgr;
|
|
||||||
scene::ISceneNode* m_playernode;
|
scene::ISceneNode* m_playernode;
|
||||||
scene::ISceneNode* m_headnode;
|
scene::ISceneNode* m_headnode;
|
||||||
scene::ICameraSceneNode* m_cameranode;
|
scene::ICameraSceneNode* m_cameranode;
|
||||||
|
|
|
@ -3395,7 +3395,7 @@ inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const short ri
|
||||||
template <typename TAlloc>
|
template <typename TAlloc>
|
||||||
inline ustring16<TAlloc> operator+(const short left, const ustring16<TAlloc>& right)
|
inline ustring16<TAlloc> operator+(const short left, const ustring16<TAlloc>& right)
|
||||||
{
|
{
|
||||||
ustring16<TAlloc> ret(core::stringc(left));
|
ustring16<TAlloc> ret((core::stringc(left)));
|
||||||
ret += right;
|
ret += right;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3415,7 +3415,7 @@ inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const unsigned
|
||||||
template <typename TAlloc>
|
template <typename TAlloc>
|
||||||
inline ustring16<TAlloc> operator+(const unsigned short left, const ustring16<TAlloc>& right)
|
inline ustring16<TAlloc> operator+(const unsigned short left, const ustring16<TAlloc>& right)
|
||||||
{
|
{
|
||||||
ustring16<TAlloc> ret(core::stringc(left));
|
ustring16<TAlloc> ret((core::stringc(left)));
|
||||||
ret += right;
|
ret += right;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3435,7 +3435,7 @@ inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const int righ
|
||||||
template <typename TAlloc>
|
template <typename TAlloc>
|
||||||
inline ustring16<TAlloc> operator+(const int left, const ustring16<TAlloc>& right)
|
inline ustring16<TAlloc> operator+(const int left, const ustring16<TAlloc>& right)
|
||||||
{
|
{
|
||||||
ustring16<TAlloc> ret(core::stringc(left));
|
ustring16<TAlloc> ret((core::stringc(left)));
|
||||||
ret += right;
|
ret += right;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3455,7 +3455,7 @@ inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const unsigned
|
||||||
template <typename TAlloc>
|
template <typename TAlloc>
|
||||||
inline ustring16<TAlloc> operator+(const unsigned int left, const ustring16<TAlloc>& right)
|
inline ustring16<TAlloc> operator+(const unsigned int left, const ustring16<TAlloc>& right)
|
||||||
{
|
{
|
||||||
ustring16<TAlloc> ret(core::stringc(left));
|
ustring16<TAlloc> ret((core::stringc(left)));
|
||||||
ret += right;
|
ret += right;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3475,7 +3475,7 @@ inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const long rig
|
||||||
template <typename TAlloc>
|
template <typename TAlloc>
|
||||||
inline ustring16<TAlloc> operator+(const long left, const ustring16<TAlloc>& right)
|
inline ustring16<TAlloc> operator+(const long left, const ustring16<TAlloc>& right)
|
||||||
{
|
{
|
||||||
ustring16<TAlloc> ret(core::stringc(left));
|
ustring16<TAlloc> ret((core::stringc(left)));
|
||||||
ret += right;
|
ret += right;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3495,7 +3495,7 @@ inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const unsigned
|
||||||
template <typename TAlloc>
|
template <typename TAlloc>
|
||||||
inline ustring16<TAlloc> operator+(const unsigned long left, const ustring16<TAlloc>& right)
|
inline ustring16<TAlloc> operator+(const unsigned long left, const ustring16<TAlloc>& right)
|
||||||
{
|
{
|
||||||
ustring16<TAlloc> ret(core::stringc(left));
|
ustring16<TAlloc> ret((core::stringc(left)));
|
||||||
ret += right;
|
ret += right;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3515,7 +3515,7 @@ inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const float ri
|
||||||
template <typename TAlloc>
|
template <typename TAlloc>
|
||||||
inline ustring16<TAlloc> operator+(const float left, const ustring16<TAlloc>& right)
|
inline ustring16<TAlloc> operator+(const float left, const ustring16<TAlloc>& right)
|
||||||
{
|
{
|
||||||
ustring16<TAlloc> ret(core::stringc(left));
|
ustring16<TAlloc> ret((core::stringc(left)));
|
||||||
ret += right;
|
ret += right;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3535,7 +3535,7 @@ inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const double r
|
||||||
template <typename TAlloc>
|
template <typename TAlloc>
|
||||||
inline ustring16<TAlloc> operator+(const double left, const ustring16<TAlloc>& right)
|
inline ustring16<TAlloc> operator+(const double left, const ustring16<TAlloc>& right)
|
||||||
{
|
{
|
||||||
ustring16<TAlloc> ret(core::stringc(left));
|
ustring16<TAlloc> ret((core::stringc(left)));
|
||||||
ret += right;
|
ret += right;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "serialization.h"
|
#include "serialization.h"
|
||||||
#include "util/serialize.h"
|
#include "util/serialize.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "cmake_config_githash.h"
|
||||||
#include "util/directiontables.h"
|
#include "util/directiontables.h"
|
||||||
#include "util/pointedthing.h"
|
#include "util/pointedthing.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
@ -168,6 +169,8 @@ void * MeshUpdateThread::Thread()
|
||||||
|
|
||||||
BEGIN_DEBUG_EXCEPTION_HANDLER
|
BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||||
|
|
||||||
|
porting::setThreadName("MeshUpdateThread");
|
||||||
|
|
||||||
while(!StopRequested())
|
while(!StopRequested())
|
||||||
{
|
{
|
||||||
QueuedMeshUpdate *q = m_queue_in.pop();
|
QueuedMeshUpdate *q = m_queue_in.pop();
|
||||||
|
@ -252,7 +255,8 @@ Client::Client(
|
||||||
m_last_time_of_day_f(-1),
|
m_last_time_of_day_f(-1),
|
||||||
m_time_of_day_update_timer(0),
|
m_time_of_day_update_timer(0),
|
||||||
m_recommended_send_interval(0.1),
|
m_recommended_send_interval(0.1),
|
||||||
m_removed_sounds_check_timer(0)
|
m_removed_sounds_check_timer(0),
|
||||||
|
m_state(LC_Created)
|
||||||
{
|
{
|
||||||
m_packetcounter_timer = 0.0;
|
m_packetcounter_timer = 0.0;
|
||||||
//m_delete_unused_sectors_timer = 0.0;
|
//m_delete_unused_sectors_timer = 0.0;
|
||||||
|
@ -325,17 +329,6 @@ void Client::connect(Address address)
|
||||||
m_con.Connect(address);
|
m_con.Connect(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Client::connectedAndInitialized()
|
|
||||||
{
|
|
||||||
if(m_con.Connected() == false)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(m_server_ser_ver == SER_FMT_VER_INVALID)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::step(float dtime)
|
void Client::step(float dtime)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
@ -372,9 +365,6 @@ void Client::step(float dtime)
|
||||||
m_packetcounter.clear();
|
m_packetcounter.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get connection status
|
|
||||||
bool connected = connectedAndInitialized();
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
{
|
{
|
||||||
|
@ -467,7 +457,7 @@ void Client::step(float dtime)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(connected == false)
|
if(m_state == LC_Created)
|
||||||
{
|
{
|
||||||
float &counter = m_connection_reinit_timer;
|
float &counter = m_connection_reinit_timer;
|
||||||
counter -= dtime;
|
counter -= dtime;
|
||||||
|
@ -632,7 +622,7 @@ void Client::step(float dtime)
|
||||||
{
|
{
|
||||||
counter = 0.0;
|
counter = 0.0;
|
||||||
// connectedAndInitialized() is true, peer exists.
|
// connectedAndInitialized() is true, peer exists.
|
||||||
float avg_rtt = m_con.GetPeerAvgRTT(PEER_ID_SERVER);
|
float avg_rtt = getRTT();
|
||||||
infostream<<"Client: avg_rtt="<<avg_rtt<<std::endl;
|
infostream<<"Client: avg_rtt="<<avg_rtt<<std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -643,7 +633,7 @@ void Client::step(float dtime)
|
||||||
{
|
{
|
||||||
float &counter = m_playerpos_send_timer;
|
float &counter = m_playerpos_send_timer;
|
||||||
counter += dtime;
|
counter += dtime;
|
||||||
if(counter >= m_recommended_send_interval)
|
if((m_state == LC_Ready) && (counter >= m_recommended_send_interval))
|
||||||
{
|
{
|
||||||
counter = 0.0;
|
counter = 0.0;
|
||||||
sendPlayerPos();
|
sendPlayerPos();
|
||||||
|
@ -1051,6 +1041,8 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||||
// Send as reliable
|
// Send as reliable
|
||||||
m_con.Send(PEER_ID_SERVER, 1, reply, true);
|
m_con.Send(PEER_ID_SERVER, 1, reply, true);
|
||||||
|
|
||||||
|
m_state = LC_Init;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1222,7 +1214,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||||
m_time_of_day_set = true;
|
m_time_of_day_set = true;
|
||||||
|
|
||||||
u32 dr = m_env.getDayNightRatio();
|
u32 dr = m_env.getDayNightRatio();
|
||||||
verbosestream<<"Client: time_of_day="<<time_of_day
|
infostream<<"Client: time_of_day="<<time_of_day
|
||||||
<<" time_speed="<<time_speed
|
<<" time_speed="<<time_speed
|
||||||
<<" dr="<<dr<<std::endl;
|
<<" dr="<<dr<<std::endl;
|
||||||
}
|
}
|
||||||
|
@ -1922,6 +1914,31 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||||
event.override_day_night_ratio.ratio_f = day_night_ratio_f;
|
event.override_day_night_ratio.ratio_f = day_night_ratio_f;
|
||||||
m_client_event_queue.push_back(event);
|
m_client_event_queue.push_back(event);
|
||||||
}
|
}
|
||||||
|
else if(command == TOCLIENT_LOCAL_PLAYER_ANIMATIONS)
|
||||||
|
{
|
||||||
|
std::string datastring((char *)&data[2], datasize - 2);
|
||||||
|
std::istringstream is(datastring, std::ios_base::binary);
|
||||||
|
|
||||||
|
LocalPlayer *player = m_env.getLocalPlayer();
|
||||||
|
assert(player != NULL);
|
||||||
|
|
||||||
|
player->local_animations[0] = readV2S32(is);
|
||||||
|
player->local_animations[1] = readV2S32(is);
|
||||||
|
player->local_animations[2] = readV2S32(is);
|
||||||
|
player->local_animations[3] = readV2S32(is);
|
||||||
|
player->local_animation_speed = readF1000(is);
|
||||||
|
}
|
||||||
|
else if(command == TOCLIENT_EYE_OFFSET)
|
||||||
|
{
|
||||||
|
std::string datastring((char *)&data[2], datasize - 2);
|
||||||
|
std::istringstream is(datastring, std::ios_base::binary);
|
||||||
|
|
||||||
|
LocalPlayer *player = m_env.getLocalPlayer();
|
||||||
|
assert(player != NULL);
|
||||||
|
|
||||||
|
player->eye_offset_first = readV3F1000(is);
|
||||||
|
player->eye_offset_third = readV3F1000(is);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
infostream<<"Client: Ignoring unknown command "
|
infostream<<"Client: Ignoring unknown command "
|
||||||
|
@ -1937,7 +1954,7 @@ void Client::Send(u16 channelnum, SharedBuffer<u8> data, bool reliable)
|
||||||
|
|
||||||
void Client::interact(u8 action, const PointedThing& pointed)
|
void Client::interact(u8 action, const PointedThing& pointed)
|
||||||
{
|
{
|
||||||
if(connectedAndInitialized() == false){
|
if(m_state != LC_Ready){
|
||||||
infostream<<"Client::interact() "
|
infostream<<"Client::interact() "
|
||||||
"cancelled (not connected)"
|
"cancelled (not connected)"
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
|
@ -2072,8 +2089,8 @@ void Client::sendChatMessage(const std::wstring &message)
|
||||||
Send(0, data, true);
|
Send(0, data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::sendChangePassword(const std::wstring oldpassword,
|
void Client::sendChangePassword(const std::wstring &oldpassword,
|
||||||
const std::wstring newpassword)
|
const std::wstring &newpassword)
|
||||||
{
|
{
|
||||||
Player *player = m_env.getLocalPlayer();
|
Player *player = m_env.getLocalPlayer();
|
||||||
if(player == NULL)
|
if(player == NULL)
|
||||||
|
@ -2152,6 +2169,27 @@ void Client::sendRespawn()
|
||||||
Send(0, data, true);
|
Send(0, data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::sendReady()
|
||||||
|
{
|
||||||
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
std::ostringstream os(std::ios_base::binary);
|
||||||
|
|
||||||
|
writeU16(os, TOSERVER_CLIENT_READY);
|
||||||
|
writeU8(os,VERSION_MAJOR);
|
||||||
|
writeU8(os,VERSION_MINOR);
|
||||||
|
writeU8(os,VERSION_PATCH_ORIG);
|
||||||
|
writeU8(os,0);
|
||||||
|
|
||||||
|
writeU16(os,strlen(CMAKE_VERSION_GITHASH));
|
||||||
|
os.write(CMAKE_VERSION_GITHASH,strlen(CMAKE_VERSION_GITHASH));
|
||||||
|
|
||||||
|
// Make data buffer
|
||||||
|
std::string s = os.str();
|
||||||
|
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||||
|
// Send as reliable
|
||||||
|
Send(0, data, true);
|
||||||
|
}
|
||||||
|
|
||||||
void Client::sendPlayerPos()
|
void Client::sendPlayerPos()
|
||||||
{
|
{
|
||||||
LocalPlayer *myplayer = m_env.getLocalPlayer();
|
LocalPlayer *myplayer = m_env.getLocalPlayer();
|
||||||
|
@ -2650,16 +2688,14 @@ void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font)
|
||||||
infostream<<"- Starting mesh update thread"<<std::endl;
|
infostream<<"- Starting mesh update thread"<<std::endl;
|
||||||
m_mesh_update_thread.Start();
|
m_mesh_update_thread.Start();
|
||||||
|
|
||||||
|
m_state = LC_Ready;
|
||||||
|
sendReady();
|
||||||
infostream<<"Client::afterContentReceived() done"<<std::endl;
|
infostream<<"Client::afterContentReceived() done"<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Client::getRTT(void)
|
float Client::getRTT(void)
|
||||||
{
|
{
|
||||||
try{
|
return m_con.getPeerStat(PEER_ID_SERVER,con::AVG_RTT);
|
||||||
return m_con.GetPeerAvgRTT(PEER_ID_SERVER);
|
|
||||||
} catch(con::PeerNotFoundException &e){
|
|
||||||
return 1337;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IGameDef interface
|
// IGameDef interface
|
||||||
|
|
25
src/client.h
25
src/client.h
|
@ -57,6 +57,12 @@ struct QueuedMeshUpdate
|
||||||
~QueuedMeshUpdate();
|
~QueuedMeshUpdate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum LocalClientState {
|
||||||
|
LC_Created,
|
||||||
|
LC_Init,
|
||||||
|
LC_Ready
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A thread-safe queue of mesh update tasks
|
A thread-safe queue of mesh update tasks
|
||||||
*/
|
*/
|
||||||
|
@ -319,14 +325,7 @@ public:
|
||||||
calling this, as it is sent in the initialization.
|
calling this, as it is sent in the initialization.
|
||||||
*/
|
*/
|
||||||
void connect(Address address);
|
void connect(Address address);
|
||||||
/*
|
|
||||||
returns true when
|
|
||||||
m_con.Connected() == true
|
|
||||||
AND m_server_ser_ver != SER_FMT_VER_INVALID
|
|
||||||
throws con::PeerNotFoundException if connection has been deleted,
|
|
||||||
eg. timed out.
|
|
||||||
*/
|
|
||||||
bool connectedAndInitialized();
|
|
||||||
/*
|
/*
|
||||||
Stuff that references the environment is valid only as
|
Stuff that references the environment is valid only as
|
||||||
long as this is not called. (eg. Players)
|
long as this is not called. (eg. Players)
|
||||||
|
@ -349,11 +348,12 @@ public:
|
||||||
const std::map<std::string, std::string> &fields);
|
const std::map<std::string, std::string> &fields);
|
||||||
void sendInventoryAction(InventoryAction *a);
|
void sendInventoryAction(InventoryAction *a);
|
||||||
void sendChatMessage(const std::wstring &message);
|
void sendChatMessage(const std::wstring &message);
|
||||||
void sendChangePassword(const std::wstring oldpassword,
|
void sendChangePassword(const std::wstring &oldpassword,
|
||||||
const std::wstring newpassword);
|
const std::wstring &newpassword);
|
||||||
void sendDamage(u8 damage);
|
void sendDamage(u8 damage);
|
||||||
void sendBreath(u16 breath);
|
void sendBreath(u16 breath);
|
||||||
void sendRespawn();
|
void sendRespawn();
|
||||||
|
void sendReady();
|
||||||
|
|
||||||
ClientEnvironment& getEnv()
|
ClientEnvironment& getEnv()
|
||||||
{ return m_env; }
|
{ return m_env; }
|
||||||
|
@ -454,6 +454,8 @@ public:
|
||||||
// Send a notification that no conventional media transfer is needed
|
// Send a notification that no conventional media transfer is needed
|
||||||
void received_media();
|
void received_media();
|
||||||
|
|
||||||
|
LocalClientState getState() { return m_state; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Virtual methods from con::PeerHandler
|
// Virtual methods from con::PeerHandler
|
||||||
|
@ -537,6 +539,9 @@ private:
|
||||||
|
|
||||||
// Storage for mesh data for creating multiple instances of the same mesh
|
// Storage for mesh data for creating multiple instances of the same mesh
|
||||||
std::map<std::string, std::string> m_mesh_data;
|
std::map<std::string, std::string> m_mesh_data;
|
||||||
|
|
||||||
|
// own state
|
||||||
|
LocalClientState m_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !CLIENT_HEADER
|
#endif // !CLIENT_HEADER
|
||||||
|
|
|
@ -17,6 +17,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "clientiface.h"
|
#include "clientiface.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
@ -140,7 +142,8 @@ void RemoteClient::GetNextBlocks(
|
||||||
*/
|
*/
|
||||||
s32 new_nearest_unsent_d = -1;
|
s32 new_nearest_unsent_d = -1;
|
||||||
|
|
||||||
s16 d_max = g_settings->getS16("max_block_send_distance");
|
const s16 full_d_max = g_settings->getS16("max_block_send_distance");
|
||||||
|
s16 d_max = full_d_max;
|
||||||
s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
|
s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
|
||||||
|
|
||||||
// Don't loop very much at a time
|
// Don't loop very much at a time
|
||||||
|
@ -214,7 +217,7 @@ void RemoteClient::GetNextBlocks(
|
||||||
generate = false;*/
|
generate = false;*/
|
||||||
|
|
||||||
// Limit the send area vertically to 1/2
|
// Limit the send area vertically to 1/2
|
||||||
if(abs(p.Y - center.Y) > d_max / 2)
|
if(abs(p.Y - center.Y) > full_d_max / 2)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,10 +399,11 @@ void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
|
||||||
|
|
||||||
void RemoteClient::notifyEvent(ClientStateEvent event)
|
void RemoteClient::notifyEvent(ClientStateEvent event)
|
||||||
{
|
{
|
||||||
|
std::ostringstream myerror;
|
||||||
switch (m_state)
|
switch (m_state)
|
||||||
{
|
{
|
||||||
case Invalid:
|
case Invalid:
|
||||||
assert("State update for client in invalid state" != 0);
|
//intentionally do nothing
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Created:
|
case Created:
|
||||||
|
@ -419,7 +423,8 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
|
||||||
|
|
||||||
/* GotInit2 SetDefinitionsSent SetMediaSent */
|
/* GotInit2 SetDefinitionsSent SetMediaSent */
|
||||||
default:
|
default:
|
||||||
assert("Invalid client state transition!" == 0);
|
myerror << "Created: Invalid client state transition! " << event;
|
||||||
|
throw ClientStateError(myerror.str());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -445,7 +450,8 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
|
||||||
|
|
||||||
/* Init SetDefinitionsSent SetMediaSent */
|
/* Init SetDefinitionsSent SetMediaSent */
|
||||||
default:
|
default:
|
||||||
assert("Invalid client state transition!" == 0);
|
myerror << "InitSent: Invalid client state transition! " << event;
|
||||||
|
throw ClientStateError(myerror.str());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -466,14 +472,15 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
|
||||||
|
|
||||||
/* Init GotInit2 SetMediaSent */
|
/* Init GotInit2 SetMediaSent */
|
||||||
default:
|
default:
|
||||||
assert("Invalid client state transition!" == 0);
|
myerror << "InitDone: Invalid client state transition! " << event;
|
||||||
|
throw ClientStateError(myerror.str());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DefinitionsSent:
|
case DefinitionsSent:
|
||||||
switch(event)
|
switch(event)
|
||||||
{
|
{
|
||||||
case SetMediaSent:
|
case SetClientReady:
|
||||||
m_state = Active;
|
m_state = Active;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -487,7 +494,8 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
|
||||||
|
|
||||||
/* Init GotInit2 SetDefinitionsSent */
|
/* Init GotInit2 SetDefinitionsSent */
|
||||||
default:
|
default:
|
||||||
assert("Invalid client state transition!" == 0);
|
myerror << "DefinitionsSent: Invalid client state transition! " << event;
|
||||||
|
throw ClientStateError(myerror.str());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -504,7 +512,8 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
|
||||||
|
|
||||||
/* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
|
/* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
|
||||||
default:
|
default:
|
||||||
assert("Invalid client state transition!" == 0);
|
myerror << "Active: Invalid client state transition! " << event;
|
||||||
|
throw ClientStateError(myerror.str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -515,6 +524,11 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 RemoteClient::uptime()
|
||||||
|
{
|
||||||
|
return getTime(PRECISION_SECONDS) - m_connection_time;
|
||||||
|
}
|
||||||
|
|
||||||
ClientInterface::ClientInterface(con::Connection* con)
|
ClientInterface::ClientInterface(con::Connection* con)
|
||||||
:
|
:
|
||||||
m_con(con),
|
m_con(con),
|
||||||
|
@ -748,7 +762,7 @@ void ClientInterface::event(u16 peer_id, ClientStateEvent event)
|
||||||
n->second->notifyEvent(event);
|
n->second->notifyEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((event == SetMediaSent) || (event == Disconnect) || (event == SetDenied))
|
if ((event == SetClientReady) || (event == Disconnect) || (event == SetDenied))
|
||||||
{
|
{
|
||||||
UpdatePlayerList();
|
UpdatePlayerList();
|
||||||
}
|
}
|
||||||
|
@ -762,9 +776,24 @@ u16 ClientInterface::getProtocolVersion(u16 peer_id)
|
||||||
std::map<u16, RemoteClient*>::iterator n;
|
std::map<u16, RemoteClient*>::iterator n;
|
||||||
n = m_clients.find(peer_id);
|
n = m_clients.find(peer_id);
|
||||||
|
|
||||||
// No client to deliver event
|
// No client to get version
|
||||||
if (n == m_clients.end())
|
if (n == m_clients.end())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return n->second->net_proto_version;
|
return n->second->net_proto_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full)
|
||||||
|
{
|
||||||
|
JMutexAutoLock conlock(m_clients_mutex);
|
||||||
|
|
||||||
|
// Error check
|
||||||
|
std::map<u16, RemoteClient*>::iterator n;
|
||||||
|
n = m_clients.find(peer_id);
|
||||||
|
|
||||||
|
// No client to set versions
|
||||||
|
if (n == m_clients.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
n->second->setVersionInfo(major,minor,patch,full);
|
||||||
|
}
|
||||||
|
|
|
@ -34,10 +34,115 @@ class MapBlock;
|
||||||
class ServerEnvironment;
|
class ServerEnvironment;
|
||||||
class EmergeManager;
|
class EmergeManager;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* State Transitions
|
||||||
|
|
||||||
|
Start
|
||||||
|
(peer connect)
|
||||||
|
|
|
||||||
|
v
|
||||||
|
/-----------------\
|
||||||
|
| |
|
||||||
|
| Created |
|
||||||
|
| |
|
||||||
|
\-----------------/
|
||||||
|
|
|
||||||
|
|
|
||||||
|
+-----------------------------+ invalid playername, password
|
||||||
|
|IN: | or denied by mod
|
||||||
|
| TOSERVER_INIT |------------------------------
|
||||||
|
+-----------------------------+ |
|
||||||
|
| |
|
||||||
|
| Auth ok |
|
||||||
|
| |
|
||||||
|
+-----------------------------+ |
|
||||||
|
|OUT: | |
|
||||||
|
| TOCLIENT_INIT | |
|
||||||
|
+-----------------------------+ |
|
||||||
|
| |
|
||||||
|
v |
|
||||||
|
/-----------------\ |
|
||||||
|
| | |
|
||||||
|
| InitSent | |
|
||||||
|
| | |
|
||||||
|
\-----------------/ +------------------
|
||||||
|
| | |
|
||||||
|
+-----------------------------+ +-----------------------------+ |
|
||||||
|
|IN: | |OUT: | |
|
||||||
|
| TOSERVER_INIT2 | | TOCLIENT_ACCESS_DENIED | |
|
||||||
|
+-----------------------------+ +-----------------------------+ |
|
||||||
|
| | |
|
||||||
|
v v |
|
||||||
|
/-----------------\ /-----------------\ |
|
||||||
|
| | | | |
|
||||||
|
| InitDone | | Denied | |
|
||||||
|
| | | | |
|
||||||
|
\-----------------/ \-----------------/ |
|
||||||
|
| |
|
||||||
|
+-----------------------------+ |
|
||||||
|
|OUT: | |
|
||||||
|
| TOCLIENT_MOVEMENT | |
|
||||||
|
| TOCLIENT_ITEMDEF | |
|
||||||
|
| TOCLIENT_NODEDEF | |
|
||||||
|
| TOCLIENT_ANNOUNCE_MEDIA | |
|
||||||
|
| TOCLIENT_DETACHED_INVENTORY | |
|
||||||
|
| TOCLIENT_TIME_OF_DAY | |
|
||||||
|
+-----------------------------+ |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| ----------------------------------- |
|
||||||
|
v | | |
|
||||||
|
/-----------------\ v |
|
||||||
|
| | +-----------------------------+ |
|
||||||
|
| DefinitionsSent | |IN: | |
|
||||||
|
| | | TOSERVER_REQUEST_MEDIA | |
|
||||||
|
\-----------------/ | TOSERVER_RECEIVED_MEDIA | |
|
||||||
|
| +-----------------------------+ |
|
||||||
|
| ^ | |
|
||||||
|
| ----------------------------------- |
|
||||||
|
| |
|
||||||
|
+-----------------------------+ |
|
||||||
|
|IN: | |
|
||||||
|
| TOSERVER_CLIENT_READY | |
|
||||||
|
+-----------------------------+ |
|
||||||
|
| async |
|
||||||
|
v mod action |
|
||||||
|
+-----------------------------+ (ban,kick) |
|
||||||
|
|OUT: | |
|
||||||
|
| TOCLIENT_MOVE_PLAYER | |
|
||||||
|
| TOCLIENT_PRIVILEGES | |
|
||||||
|
| TOCLIENT_INVENTORY_FORMSPEC | |
|
||||||
|
| UpdateCrafting | |
|
||||||
|
| TOCLIENT_INVENTORY | |
|
||||||
|
| TOCLIENT_HP (opt) | |
|
||||||
|
| TOCLIENT_BREATH | |
|
||||||
|
| TOCLIENT_DEATHSCREEN | |
|
||||||
|
+-----------------------------+ |
|
||||||
|
| |
|
||||||
|
v |
|
||||||
|
/-----------------\ |
|
||||||
|
| |------------------------------------------------------
|
||||||
|
| Active |
|
||||||
|
| |----------------------------------
|
||||||
|
\-----------------/ timeout |
|
||||||
|
| +-----------------------------+
|
||||||
|
| |OUT: |
|
||||||
|
| | TOCLIENT_DISCONNECT |
|
||||||
|
| +-----------------------------+
|
||||||
|
| |
|
||||||
|
| v
|
||||||
|
+-----------------------------+ /-----------------\
|
||||||
|
|IN: | | |
|
||||||
|
| TOSERVER_DISCONNECT |------------------->| Disconnecting |
|
||||||
|
+-----------------------------+ | |
|
||||||
|
\-----------------/
|
||||||
|
*/
|
||||||
namespace con {
|
namespace con {
|
||||||
class Connection;
|
class Connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||||
|
|
||||||
enum ClientState
|
enum ClientState
|
||||||
{
|
{
|
||||||
Invalid,
|
Invalid,
|
||||||
|
@ -50,13 +155,24 @@ enum ClientState
|
||||||
Active
|
Active
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char* statenames[] = {
|
||||||
|
"Invalid",
|
||||||
|
"Disconnecting",
|
||||||
|
"Denied",
|
||||||
|
"Created",
|
||||||
|
"InitSent",
|
||||||
|
"InitDone",
|
||||||
|
"DefinitionsSent",
|
||||||
|
"Active"
|
||||||
|
};
|
||||||
|
|
||||||
enum ClientStateEvent
|
enum ClientStateEvent
|
||||||
{
|
{
|
||||||
Init,
|
Init,
|
||||||
GotInit2,
|
GotInit2,
|
||||||
SetDenied,
|
SetDenied,
|
||||||
SetDefinitionsSent,
|
SetDefinitionsSent,
|
||||||
SetMediaSent,
|
SetClientReady,
|
||||||
Disconnect
|
Disconnect
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -105,9 +221,13 @@ public:
|
||||||
m_nearest_unsent_d(0),
|
m_nearest_unsent_d(0),
|
||||||
m_nearest_unsent_reset_timer(0.0),
|
m_nearest_unsent_reset_timer(0.0),
|
||||||
m_excess_gotblocks(0),
|
m_excess_gotblocks(0),
|
||||||
m_nothing_to_send_counter(0),
|
|
||||||
m_nothing_to_send_pause_timer(0.0),
|
m_nothing_to_send_pause_timer(0.0),
|
||||||
m_name("")
|
m_name(""),
|
||||||
|
m_version_major(0),
|
||||||
|
m_version_minor(0),
|
||||||
|
m_version_patch(0),
|
||||||
|
m_full_version("unknown"),
|
||||||
|
m_connection_time(getTime(PRECISION_SECONDS))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
~RemoteClient()
|
~RemoteClient()
|
||||||
|
@ -178,6 +298,23 @@ public:
|
||||||
void confirmSerializationVersion()
|
void confirmSerializationVersion()
|
||||||
{ serialization_version = m_pending_serialization_version; }
|
{ serialization_version = m_pending_serialization_version; }
|
||||||
|
|
||||||
|
/* get uptime */
|
||||||
|
u32 uptime();
|
||||||
|
|
||||||
|
|
||||||
|
/* set version information */
|
||||||
|
void setVersionInfo(u8 major, u8 minor, u8 patch, std::string full) {
|
||||||
|
m_version_major = major;
|
||||||
|
m_version_minor = minor;
|
||||||
|
m_version_patch = patch;
|
||||||
|
m_full_version = full;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read version information */
|
||||||
|
u8 getMajor() { return m_version_major; }
|
||||||
|
u8 getMinor() { return m_version_minor; }
|
||||||
|
u8 getPatch() { return m_version_patch; }
|
||||||
|
std::string getVersion() { return m_full_version; }
|
||||||
private:
|
private:
|
||||||
// Version is stored in here after INIT before INIT2
|
// Version is stored in here after INIT before INIT2
|
||||||
u8 m_pending_serialization_version;
|
u8 m_pending_serialization_version;
|
||||||
|
@ -219,9 +356,26 @@ private:
|
||||||
u32 m_excess_gotblocks;
|
u32 m_excess_gotblocks;
|
||||||
|
|
||||||
// CPU usage optimization
|
// CPU usage optimization
|
||||||
u32 m_nothing_to_send_counter;
|
|
||||||
float m_nothing_to_send_pause_timer;
|
float m_nothing_to_send_pause_timer;
|
||||||
|
|
||||||
|
/*
|
||||||
|
name of player using this client
|
||||||
|
*/
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
|
||||||
|
/*
|
||||||
|
client information
|
||||||
|
*/
|
||||||
|
u8 m_version_major;
|
||||||
|
u8 m_version_minor;
|
||||||
|
u8 m_version_patch;
|
||||||
|
|
||||||
|
std::string m_full_version;
|
||||||
|
|
||||||
|
/*
|
||||||
|
time this client was created
|
||||||
|
*/
|
||||||
|
const u32 m_connection_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClientInterface {
|
class ClientInterface {
|
||||||
|
@ -268,6 +422,9 @@ public:
|
||||||
/* get protocol version of client */
|
/* get protocol version of client */
|
||||||
u16 getProtocolVersion(u16 peer_id);
|
u16 getProtocolVersion(u16 peer_id);
|
||||||
|
|
||||||
|
/* set client version */
|
||||||
|
void setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full);
|
||||||
|
|
||||||
/* event to update client state */
|
/* event to update client state */
|
||||||
void event(u16 peer_id, ClientStateEvent event);
|
void event(u16 peer_id, ClientStateEvent event);
|
||||||
|
|
||||||
|
@ -275,6 +432,11 @@ public:
|
||||||
void setEnv(ServerEnvironment* env)
|
void setEnv(ServerEnvironment* env)
|
||||||
{ assert(m_env == 0); m_env = env; }
|
{ assert(m_env == 0); m_env = env; }
|
||||||
|
|
||||||
|
static std::string state2Name(ClientState state) {
|
||||||
|
assert((int) state < ARRAYSIZE(statenames));
|
||||||
|
return statenames[state];
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//TODO find way to avoid this functions
|
//TODO find way to avoid this functions
|
||||||
void Lock()
|
void Lock()
|
||||||
|
|
|
@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "mapblock.h"
|
#include "mapblock.h"
|
||||||
#include "profiler.h"
|
#include "profiler.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "camera.h" // CameraModes
|
||||||
#include "util/mathconstants.h"
|
#include "util/mathconstants.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
@ -866,13 +867,16 @@ void ClientMap::renderPostFx()
|
||||||
v3f camera_position = m_camera_position;
|
v3f camera_position = m_camera_position;
|
||||||
m_camera_mutex.Unlock();
|
m_camera_mutex.Unlock();
|
||||||
|
|
||||||
|
LocalPlayer *player = m_client->getEnv().getLocalPlayer();
|
||||||
|
|
||||||
MapNode n = getNodeNoEx(floatToInt(camera_position, BS));
|
MapNode n = getNodeNoEx(floatToInt(camera_position, BS));
|
||||||
|
|
||||||
// - If the player is in a solid node, make everything black.
|
// - If the player is in a solid node, make everything black.
|
||||||
// - If the player is in liquid, draw a semi-transparent overlay.
|
// - If the player is in liquid, draw a semi-transparent overlay.
|
||||||
|
// - Do not if player is in third person mode
|
||||||
const ContentFeatures& features = nodemgr->get(n);
|
const ContentFeatures& features = nodemgr->get(n);
|
||||||
video::SColor post_effect_color = features.post_effect_color;
|
video::SColor post_effect_color = features.post_effect_color;
|
||||||
if(features.solidness == 2 && !(g_settings->getBool("noclip") && m_gamedef->checkLocalPrivilege("noclip")))
|
if(features.solidness == 2 && !(g_settings->getBool("noclip") && m_gamedef->checkLocalPrivilege("noclip")) && player->camera_mode == CAMERA_MODE_FIRST)
|
||||||
{
|
{
|
||||||
post_effect_color = video::SColor(255, 0, 0, 0);
|
post_effect_color = video::SColor(255, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ public:
|
||||||
virtual void updateLight(u8 light_at_pos){}
|
virtual void updateLight(u8 light_at_pos){}
|
||||||
virtual v3s16 getLightPosition(){return v3s16(0,0,0);}
|
virtual v3s16 getLightPosition(){return v3s16(0,0,0);}
|
||||||
virtual core::aabbox3d<f32>* getSelectionBox(){return NULL;}
|
virtual core::aabbox3d<f32>* getSelectionBox(){return NULL;}
|
||||||
virtual core::aabbox3d<f32>* getCollisionBox(){return NULL;}
|
virtual bool getCollisionBox(aabb3f *toset){return false;}
|
||||||
virtual bool collideWithObjects(){return false;}
|
virtual bool collideWithObjects(){return false;}
|
||||||
virtual v3f getPosition(){return v3f(0,0,0);}
|
virtual v3f getPosition(){return v3f(0,0,0);}
|
||||||
virtual scene::IMeshSceneNode *getMeshSceneNode(){return NULL;}
|
virtual scene::IMeshSceneNode *getMeshSceneNode(){return NULL;}
|
||||||
|
|
|
@ -100,9 +100,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
version, heat and humidity transfer in MapBock
|
version, heat and humidity transfer in MapBock
|
||||||
automatic_face_movement_dir and automatic_face_movement_dir_offset
|
automatic_face_movement_dir and automatic_face_movement_dir_offset
|
||||||
added to object properties
|
added to object properties
|
||||||
|
PROTOCOL_VERSION 22:
|
||||||
|
add swap_node
|
||||||
|
PROTOCOL_VERSION 23:
|
||||||
|
TOSERVER_CLIENT_READY
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define LATEST_PROTOCOL_VERSION 22
|
#define LATEST_PROTOCOL_VERSION 23
|
||||||
|
|
||||||
// Server's supported network protocol range
|
// Server's supported network protocol range
|
||||||
#define SERVER_PROTOCOL_VERSION_MIN 13
|
#define SERVER_PROTOCOL_VERSION_MIN 13
|
||||||
|
@ -129,7 +133,7 @@ enum ToClientCommand
|
||||||
|
|
||||||
[0] u16 TOSERVER_INIT
|
[0] u16 TOSERVER_INIT
|
||||||
[2] u8 deployed version
|
[2] u8 deployed version
|
||||||
[3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd
|
[3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd
|
||||||
[12] u64 map seed (new as of 2011-02-27)
|
[12] u64 map seed (new as of 2011-02-27)
|
||||||
[20] f1000 recommended send interval (in seconds) (new as of 14)
|
[20] f1000 recommended send interval (in seconds) (new as of 14)
|
||||||
|
|
||||||
|
@ -526,6 +530,23 @@ enum ToClientCommand
|
||||||
u8 do_override (boolean)
|
u8 do_override (boolean)
|
||||||
u16 day-night ratio 0...65535
|
u16 day-night ratio 0...65535
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
TOCLIENT_LOCAL_PLAYER_ANIMATIONS = 0x51,
|
||||||
|
/*
|
||||||
|
u16 command
|
||||||
|
v2s32 stand/idle
|
||||||
|
v2s32 walk
|
||||||
|
v2s32 dig
|
||||||
|
v2s32 walk+dig
|
||||||
|
f1000 frame_speed
|
||||||
|
*/
|
||||||
|
|
||||||
|
TOCLIENT_EYE_OFFSET = 0x52,
|
||||||
|
/*
|
||||||
|
u16 command
|
||||||
|
v3f1000 first
|
||||||
|
v3f1000 third
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ToServerCommand
|
enum ToServerCommand
|
||||||
|
@ -755,6 +776,16 @@ enum ToServerCommand
|
||||||
u16 command
|
u16 command
|
||||||
u16 breath
|
u16 breath
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
TOSERVER_CLIENT_READY = 0x43,
|
||||||
|
/*
|
||||||
|
u8 major
|
||||||
|
u8 minor
|
||||||
|
u8 patch
|
||||||
|
u8 reserved
|
||||||
|
u16 len
|
||||||
|
u8[len] full_version_string
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -76,7 +76,6 @@ private:
|
||||||
video::SMaterial m_material;
|
video::SMaterial m_material;
|
||||||
core::aabbox3d<f32> m_box;
|
core::aabbox3d<f32> m_box;
|
||||||
float m_cloud_y;
|
float m_cloud_y;
|
||||||
float m_brightness;
|
|
||||||
video::SColorf m_color;
|
video::SColorf m_color;
|
||||||
u32 m_seed;
|
u32 m_seed;
|
||||||
v2f m_camera_pos;
|
v2f m_camera_pos;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#define CMAKE_STATIC_SHAREDIR "@SHAREDIR@"
|
#define CMAKE_STATIC_SHAREDIR "@SHAREDIR@"
|
||||||
#define CMAKE_USE_LEVELDB @USE_LEVELDB@
|
#define CMAKE_USE_LEVELDB @USE_LEVELDB@
|
||||||
#define CMAKE_USE_LUAJIT @USE_LUAJIT@
|
#define CMAKE_USE_LUAJIT @USE_LUAJIT@
|
||||||
|
#define CMAKE_USE_REDIS @USE_REDIS@
|
||||||
#define CMAKE_VERSION_MAJOR @VERSION_MAJOR@
|
#define CMAKE_VERSION_MAJOR @VERSION_MAJOR@
|
||||||
#define CMAKE_VERSION_MINOR @VERSION_MINOR@
|
#define CMAKE_VERSION_MINOR @VERSION_MINOR@
|
||||||
#define CMAKE_VERSION_PATCH @VERSION_PATCH@
|
#define CMAKE_VERSION_PATCH @VERSION_PATCH@
|
||||||
|
|
26
src/config.h
26
src/config.h
|
@ -9,12 +9,28 @@
|
||||||
#define PROJECT_NAME "Minetest"
|
#define PROJECT_NAME "Minetest"
|
||||||
#define RUN_IN_PLACE 0
|
#define RUN_IN_PLACE 0
|
||||||
#define USE_GETTEXT 0
|
#define USE_GETTEXT 0
|
||||||
#define USE_SOUND 0
|
#ifndef USE_SOUND
|
||||||
#define USE_CURL 0
|
#define USE_SOUND 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USE_CURL
|
||||||
|
#define USE_CURL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#define USE_FREETYPE 0
|
#define USE_FREETYPE 0
|
||||||
#define STATIC_SHAREDIR ""
|
#define STATIC_SHAREDIR ""
|
||||||
#define USE_LEVELDB 0
|
|
||||||
#define USE_LUAJIT 0
|
#ifndef USE_LEVELDB
|
||||||
|
#define USE_LEVELDB 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USE_LUAJIT
|
||||||
|
#define USE_LUAJIT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USE_REDIS
|
||||||
|
#define USE_REDIS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_CMAKE_CONFIG_H
|
#ifdef USE_CMAKE_CONFIG_H
|
||||||
#include "cmake_config.h"
|
#include "cmake_config.h"
|
||||||
|
@ -36,6 +52,8 @@
|
||||||
#define USE_LEVELDB CMAKE_USE_LEVELDB
|
#define USE_LEVELDB CMAKE_USE_LEVELDB
|
||||||
#undef USE_LUAJIT
|
#undef USE_LUAJIT
|
||||||
#define USE_LUAJIT CMAKE_USE_LUAJIT
|
#define USE_LUAJIT CMAKE_USE_LUAJIT
|
||||||
|
#undef USE_REDIS
|
||||||
|
#define USE_REDIS CMAKE_USE_REDIS
|
||||||
#undef VERSION_MAJOR
|
#undef VERSION_MAJOR
|
||||||
#define VERSION_MAJOR CMAKE_VERSION_MAJOR
|
#define VERSION_MAJOR CMAKE_VERSION_MAJOR
|
||||||
#undef VERSION_MINOR
|
#undef VERSION_MINOR
|
||||||
|
|
|
@ -212,7 +212,7 @@ SharedBuffer<u8> makeReliablePacket(
|
||||||
ReliablePacketBuffer
|
ReliablePacketBuffer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ReliablePacketBuffer::ReliablePacketBuffer(): m_list_size(0),writeptr(0) {}
|
ReliablePacketBuffer::ReliablePacketBuffer(): m_list_size(0) {}
|
||||||
|
|
||||||
void ReliablePacketBuffer::print()
|
void ReliablePacketBuffer::print()
|
||||||
{
|
{
|
||||||
|
@ -1170,7 +1170,7 @@ void UDPPeer::RunCommandQueues(
|
||||||
channels[i].queued_commands.push_front(c);
|
channels[i].queued_commands.push_front(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ItemNotFoundException e) {
|
catch (ItemNotFoundException &e) {
|
||||||
// intentionally empty
|
// intentionally empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1227,6 +1227,8 @@ void * ConnectionSendThread::Thread()
|
||||||
PROFILE(std::stringstream ThreadIdentifier);
|
PROFILE(std::stringstream ThreadIdentifier);
|
||||||
PROFILE(ThreadIdentifier << "ConnectionSend: [" << m_connection->getDesc() << "]");
|
PROFILE(ThreadIdentifier << "ConnectionSend: [" << m_connection->getDesc() << "]");
|
||||||
|
|
||||||
|
porting::setThreadName("ConnectionSend");
|
||||||
|
|
||||||
/* if stop is requested don't stop immediately but try to send all */
|
/* if stop is requested don't stop immediately but try to send all */
|
||||||
/* packets first */
|
/* packets first */
|
||||||
while(!StopRequested() || packetsQueued()) {
|
while(!StopRequested() || packetsQueued()) {
|
||||||
|
@ -1939,8 +1941,7 @@ void ConnectionSendThread::sendAsPacket(u16 peer_id, u8 channelnum,
|
||||||
|
|
||||||
ConnectionReceiveThread::ConnectionReceiveThread(Connection* parent,
|
ConnectionReceiveThread::ConnectionReceiveThread(Connection* parent,
|
||||||
unsigned int max_packet_size) :
|
unsigned int max_packet_size) :
|
||||||
m_connection(parent),
|
m_connection(parent)
|
||||||
m_max_packet_size(max_packet_size)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1955,6 +1956,8 @@ void * ConnectionReceiveThread::Thread()
|
||||||
PROFILE(std::stringstream ThreadIdentifier);
|
PROFILE(std::stringstream ThreadIdentifier);
|
||||||
PROFILE(ThreadIdentifier << "ConnectionReceive: [" << m_connection->getDesc() << "]");
|
PROFILE(ThreadIdentifier << "ConnectionReceive: [" << m_connection->getDesc() << "]");
|
||||||
|
|
||||||
|
porting::setThreadName("ConnectionReceive");
|
||||||
|
|
||||||
#ifdef DEBUG_CONNECTION_KBPS
|
#ifdef DEBUG_CONNECTION_KBPS
|
||||||
u32 curtime = porting::getTimeMs();
|
u32 curtime = porting::getTimeMs();
|
||||||
u32 lasttime = curtime;
|
u32 lasttime = curtime;
|
||||||
|
@ -2067,7 +2070,7 @@ void ConnectionReceiveThread::receive()
|
||||||
m_connection->putEvent(e);
|
m_connection->putEvent(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(ProcessedSilentlyException e) {
|
catch(ProcessedSilentlyException &e) {
|
||||||
/* try reading again */
|
/* try reading again */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2875,11 +2878,11 @@ Address Connection::GetPeerAddress(u16 peer_id)
|
||||||
return peer_address;
|
return peer_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Connection::GetPeerAvgRTT(u16 peer_id)
|
float Connection::getPeerStat(u16 peer_id, rtt_stat_type type)
|
||||||
{
|
{
|
||||||
PeerHelper peer = getPeerNoEx(peer_id);
|
PeerHelper peer = getPeerNoEx(peer_id);
|
||||||
if (!peer) return -1;
|
if (!peer) return -1;
|
||||||
return peer->getStat(AVG_RTT);
|
return peer->getStat(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 Connection::createPeer(Address& sender, MTProtocols protocol, int fd)
|
u16 Connection::createPeer(Address& sender, MTProtocols protocol, int fd)
|
||||||
|
|
|
@ -339,13 +339,11 @@ private:
|
||||||
RPBSearchResult findPacket(u16 seqnum);
|
RPBSearchResult findPacket(u16 seqnum);
|
||||||
|
|
||||||
std::list<BufferedPacket> m_list;
|
std::list<BufferedPacket> m_list;
|
||||||
u16 m_list_size;
|
u32 m_list_size;
|
||||||
|
|
||||||
u16 m_oldest_non_answered_ack;
|
u16 m_oldest_non_answered_ack;
|
||||||
|
|
||||||
JMutex m_list_mutex;
|
JMutex m_list_mutex;
|
||||||
|
|
||||||
unsigned int writeptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -975,7 +973,6 @@ private:
|
||||||
|
|
||||||
|
|
||||||
Connection* m_connection;
|
Connection* m_connection;
|
||||||
unsigned int m_max_packet_size;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Connection
|
class Connection
|
||||||
|
@ -1004,7 +1001,7 @@ public:
|
||||||
void Send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
|
void Send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
|
||||||
u16 GetPeerID(){ return m_peer_id; }
|
u16 GetPeerID(){ return m_peer_id; }
|
||||||
Address GetPeerAddress(u16 peer_id);
|
Address GetPeerAddress(u16 peer_id);
|
||||||
float GetPeerAvgRTT(u16 peer_id);
|
float getPeerStat(u16 peer_id, rtt_stat_type type);
|
||||||
const u32 GetProtocolID() const { return m_protocol_id; };
|
const u32 GetProtocolID() const { return m_protocol_id; };
|
||||||
const std::string getDesc();
|
const std::string getDesc();
|
||||||
void DisconnectPeer(u16 peer_id);
|
void DisconnectPeer(u16 peer_id);
|
||||||
|
|
|
@ -89,11 +89,5 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
// Maximum hit points of a player
|
// Maximum hit points of a player
|
||||||
#define PLAYER_MAX_HP 20
|
#define PLAYER_MAX_HP 20
|
||||||
|
|
||||||
/*
|
|
||||||
Environmental condition constants
|
|
||||||
*/
|
|
||||||
#define HEAT_UNDEFINED (-0x7fff-1)
|
|
||||||
#define HUMIDITY_UNDEFINED (-0x7fff-1)
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -32,216 +32,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||||
|
|
||||||
class LiquidFlowABM : public ActiveBlockModifier {
|
|
||||||
private:
|
|
||||||
std::set<std::string> contents;
|
|
||||||
|
|
||||||
public:
|
|
||||||
LiquidFlowABM(ServerEnvironment *env, INodeDefManager *nodemgr) {
|
|
||||||
std::set<content_t> liquids;
|
|
||||||
nodemgr->getIds("group:liquid", liquids);
|
|
||||||
for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++)
|
|
||||||
contents.insert(nodemgr->get(*k).liquid_alternative_flowing);
|
|
||||||
}
|
|
||||||
virtual std::set<std::string> getTriggerContents() {
|
|
||||||
return contents;
|
|
||||||
}
|
|
||||||
virtual float getTriggerInterval()
|
|
||||||
{ return 10.0; }
|
|
||||||
virtual u32 getTriggerChance()
|
|
||||||
{ return 10; }
|
|
||||||
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) {
|
|
||||||
ServerMap *map = &env->getServerMap();
|
|
||||||
if (map->transforming_liquid_size() > 500)
|
|
||||||
return;
|
|
||||||
map->transforming_liquid_add(p);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class LiquidDropABM : public ActiveBlockModifier {
|
|
||||||
private:
|
|
||||||
std::set<std::string> contents;
|
|
||||||
|
|
||||||
public:
|
|
||||||
LiquidDropABM(ServerEnvironment *env, INodeDefManager *nodemgr) {
|
|
||||||
std::set<content_t> liquids;
|
|
||||||
nodemgr->getIds("group:liquid", liquids);
|
|
||||||
for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++)
|
|
||||||
contents.insert(nodemgr->get(*k).liquid_alternative_source);
|
|
||||||
}
|
|
||||||
virtual std::set<std::string> getTriggerContents()
|
|
||||||
{ return contents; }
|
|
||||||
virtual std::set<std::string> getRequiredNeighbors() {
|
|
||||||
std::set<std::string> neighbors;
|
|
||||||
neighbors.insert("air");
|
|
||||||
return neighbors;
|
|
||||||
}
|
|
||||||
virtual float getTriggerInterval()
|
|
||||||
{ return 20.0; }
|
|
||||||
virtual u32 getTriggerChance()
|
|
||||||
{ return 10; }
|
|
||||||
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) {
|
|
||||||
ServerMap *map = &env->getServerMap();
|
|
||||||
if (map->transforming_liquid_size() > 500)
|
|
||||||
return;
|
|
||||||
if ( map->getNodeNoEx(p - v3s16(0, 1, 0 )).getContent() != CONTENT_AIR // below
|
|
||||||
&& map->getNodeNoEx(p - v3s16(1, 0, 0 )).getContent() != CONTENT_AIR // right
|
|
||||||
&& map->getNodeNoEx(p - v3s16(-1, 0, 0 )).getContent() != CONTENT_AIR // left
|
|
||||||
&& map->getNodeNoEx(p - v3s16(0, 0, 1 )).getContent() != CONTENT_AIR // back
|
|
||||||
&& map->getNodeNoEx(p - v3s16(0, 0, -1)).getContent() != CONTENT_AIR // front
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
map->transforming_liquid_add(p);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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("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->updateBlockHeat(env, p);
|
|
||||||
//heater = rare
|
|
||||||
content_t c = map->getNodeNoEx(p - v3s16(0, -1, 0 )).getContent(); // top
|
|
||||||
//more chance to freeze if air at top
|
|
||||||
if (heat <= -1 && (heat <= -50 || (myrand_range(-50, heat) <= (c == CONTENT_AIR ? -10 : -40)))) {
|
|
||||||
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)
|
|
||||||
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.freezeMelt(ndef);
|
|
||||||
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("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->updateBlockHeat(env, p);
|
|
||||||
content_t c = map->getNodeNoEx(p - v3s16(0, -1, 0 )).getContent(); // top
|
|
||||||
if (heat >= 1 && (heat >= 40 || ((myrand_range(heat, 40)) >= (c == CONTENT_AIR ? 10 : 20)))) {
|
|
||||||
n.freezeMelt(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.freezeMelt(ndef);
|
|
||||||
map->addNodeWithEvent(p, n);
|
|
||||||
env->getScriptIface()->node_falling_update(p);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* too buggy, later via liquid flow code
|
|
||||||
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) {
|
void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef) {
|
||||||
if (g_settings->getBool("liquid_finite")) {
|
|
||||||
env->addActiveBlockModifier(new LiquidFlowABM(env, nodedef));
|
|
||||||
env->addActiveBlockModifier(new LiquidDropABM(env, nodedef));
|
|
||||||
env->addActiveBlockModifier(new LiquidMeltHot(env, nodedef));
|
|
||||||
//env->addActiveBlockModifier(new LiquidMeltAround(env, nodedef));
|
|
||||||
if (env->m_use_weather) {
|
|
||||||
env->addActiveBlockModifier(new LiquidFreeze(env, nodedef));
|
|
||||||
env->addActiveBlockModifier(new LiquidMeltWeather(env, nodedef));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "util/mathconstants.h"
|
#include "util/mathconstants.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "main.h" // g_settings
|
#include "main.h" // g_settings
|
||||||
|
#include "camera.h" // CameraModes
|
||||||
#include <IMeshManipulator.h>
|
#include <IMeshManipulator.h>
|
||||||
#include <IAnimatedMeshSceneNode.h>
|
#include <IAnimatedMeshSceneNode.h>
|
||||||
#include <IBoneSceneNode.h>
|
#include <IBoneSceneNode.h>
|
||||||
|
@ -165,7 +166,7 @@ public:
|
||||||
|
|
||||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||||
IrrlichtDevice *irr);
|
IrrlichtDevice *irr);
|
||||||
void removeFromScene();
|
void removeFromScene(bool permanent);
|
||||||
void updateLight(u8 light_at_pos);
|
void updateLight(u8 light_at_pos);
|
||||||
v3s16 getLightPosition();
|
v3s16 getLightPosition();
|
||||||
void updateNodePos();
|
void updateNodePos();
|
||||||
|
@ -235,7 +236,7 @@ void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||||
updateNodePos();
|
updateNodePos();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCAO::removeFromScene()
|
void TestCAO::removeFromScene(bool permanent)
|
||||||
{
|
{
|
||||||
if(m_node == NULL)
|
if(m_node == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -309,7 +310,7 @@ public:
|
||||||
|
|
||||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||||
IrrlichtDevice *irr);
|
IrrlichtDevice *irr);
|
||||||
void removeFromScene();
|
void removeFromScene(bool permanent);
|
||||||
void updateLight(u8 light_at_pos);
|
void updateLight(u8 light_at_pos);
|
||||||
v3s16 getLightPosition();
|
v3s16 getLightPosition();
|
||||||
void updateNodePos();
|
void updateNodePos();
|
||||||
|
@ -411,7 +412,7 @@ void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||||
updateTexture();
|
updateTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemCAO::removeFromScene()
|
void ItemCAO::removeFromScene(bool permanent)
|
||||||
{
|
{
|
||||||
if(m_node == NULL)
|
if(m_node == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -580,7 +581,7 @@ private:
|
||||||
v2s16 m_tx_basepos;
|
v2s16 m_tx_basepos;
|
||||||
bool m_initial_tx_basepos_set;
|
bool m_initial_tx_basepos_set;
|
||||||
bool m_tx_select_horiz_by_yawpitch;
|
bool m_tx_select_horiz_by_yawpitch;
|
||||||
v2f m_animation_range;
|
v2s32 m_animation_range;
|
||||||
int m_animation_speed;
|
int m_animation_speed;
|
||||||
int m_animation_blend;
|
int m_animation_blend;
|
||||||
std::map<std::string, core::vector2d<v3f> > m_bone_position; // stores position and rotation for each bone name
|
std::map<std::string, core::vector2d<v3f> > m_bone_position; // stores position and rotation for each bone name
|
||||||
|
@ -623,7 +624,7 @@ public:
|
||||||
m_tx_basepos(0,0),
|
m_tx_basepos(0,0),
|
||||||
m_initial_tx_basepos_set(false),
|
m_initial_tx_basepos_set(false),
|
||||||
m_tx_select_horiz_by_yawpitch(false),
|
m_tx_select_horiz_by_yawpitch(false),
|
||||||
m_animation_range(v2f(0,0)),
|
m_animation_range(v2s32(0,0)),
|
||||||
m_animation_speed(15),
|
m_animation_speed(15),
|
||||||
m_animation_blend(0),
|
m_animation_blend(0),
|
||||||
m_bone_position(std::map<std::string, core::vector2d<v3f> >()),
|
m_bone_position(std::map<std::string, core::vector2d<v3f> >()),
|
||||||
|
@ -647,7 +648,6 @@ public:
|
||||||
|
|
||||||
bool getCollisionBox(aabb3f *toset) {
|
bool getCollisionBox(aabb3f *toset) {
|
||||||
if (m_prop.physical) {
|
if (m_prop.physical) {
|
||||||
aabb3f retval;
|
|
||||||
//update collision box
|
//update collision box
|
||||||
toset->MinEdge = m_prop.collisionbox.MinEdge * BS;
|
toset->MinEdge = m_prop.collisionbox.MinEdge * BS;
|
||||||
toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS;
|
toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS;
|
||||||
|
@ -858,7 +858,7 @@ public:
|
||||||
|
|
||||||
m_visuals_expired = false;
|
m_visuals_expired = false;
|
||||||
|
|
||||||
if(!m_prop.is_visible || m_is_local_player)
|
if(!m_prop.is_visible)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//video::IVideoDriver* driver = smgr->getVideoDriver();
|
//video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||||
|
@ -1078,6 +1078,76 @@ public:
|
||||||
|
|
||||||
void step(float dtime, ClientEnvironment *env)
|
void step(float dtime, ClientEnvironment *env)
|
||||||
{
|
{
|
||||||
|
// Handel model of local player instantly to prevent lags
|
||||||
|
if(m_is_local_player) {
|
||||||
|
LocalPlayer *player = m_env->getLocalPlayer();
|
||||||
|
|
||||||
|
if (player->camera_mode > CAMERA_MODE_FIRST) {
|
||||||
|
int old_anim = player->last_animation;
|
||||||
|
float old_anim_speed = player->last_animation_speed;
|
||||||
|
m_is_visible = true;
|
||||||
|
m_position = player->getPosition() + v3f(0,BS,0);
|
||||||
|
m_velocity = v3f(0,0,0);
|
||||||
|
m_acceleration = v3f(0,0,0);
|
||||||
|
pos_translator.vect_show = m_position;
|
||||||
|
m_yaw = player->getYaw();
|
||||||
|
PlayerControl controls = player->getPlayerControl();
|
||||||
|
|
||||||
|
bool walking = false;
|
||||||
|
if(controls.up || controls.down || controls.left || controls.right)
|
||||||
|
walking = true;
|
||||||
|
|
||||||
|
f32 new_speed = player->local_animation_speed;
|
||||||
|
v2s32 new_anim = v2s32(0,0);
|
||||||
|
bool allow_update = false;
|
||||||
|
|
||||||
|
if(!player->touching_ground &&
|
||||||
|
g_settings->getBool("free_move") &&
|
||||||
|
m_gamedef->checkLocalPrivilege("fly") &&
|
||||||
|
g_settings->getBool("fast_move") &&
|
||||||
|
m_gamedef->checkLocalPrivilege("fast"))
|
||||||
|
new_speed *= 1.5;
|
||||||
|
if(controls.sneak && walking)
|
||||||
|
new_speed /= 2;
|
||||||
|
|
||||||
|
if(walking && (controls.LMB || controls.RMB)) {
|
||||||
|
new_anim = player->local_animations[3];
|
||||||
|
player->last_animation = WD_ANIM;
|
||||||
|
} else if(walking) {
|
||||||
|
new_anim = player->local_animations[1];
|
||||||
|
player->last_animation = WALK_ANIM;
|
||||||
|
} else if(controls.LMB || controls.RMB) {
|
||||||
|
new_anim = player->local_animations[2];
|
||||||
|
player->last_animation = DIG_ANIM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((new_anim.X + new_anim.Y) > 0) {
|
||||||
|
allow_update = true;
|
||||||
|
m_animation_range = new_anim;
|
||||||
|
m_animation_speed = new_speed;
|
||||||
|
player->last_animation_speed = m_animation_speed;
|
||||||
|
} else {
|
||||||
|
player->last_animation = NO_ANIM;
|
||||||
|
}
|
||||||
|
// reset animation when no input detected
|
||||||
|
if (!walking && !controls.LMB && !controls.RMB) {
|
||||||
|
player->last_animation = NO_ANIM;
|
||||||
|
if (old_anim != NO_ANIM) {
|
||||||
|
m_animation_range = player->local_animations[0];
|
||||||
|
updateAnimation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update local player animations
|
||||||
|
if ((player->last_animation != old_anim || m_animation_speed != old_anim_speed) &&
|
||||||
|
player->last_animation != NO_ANIM && allow_update)
|
||||||
|
updateAnimation();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
m_is_visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(m_visuals_expired && m_smgr && m_irr){
|
if(m_visuals_expired && m_smgr && m_irr){
|
||||||
m_visuals_expired = false;
|
m_visuals_expired = false;
|
||||||
|
|
||||||
|
@ -1440,8 +1510,7 @@ public:
|
||||||
{
|
{
|
||||||
if(m_animated_meshnode == NULL)
|
if(m_animated_meshnode == NULL)
|
||||||
return;
|
return;
|
||||||
|
m_animated_meshnode->setFrameLoop(m_animation_range.X, m_animation_range.Y);
|
||||||
m_animated_meshnode->setFrameLoop((int)m_animation_range.X, (int)m_animation_range.Y);
|
|
||||||
m_animated_meshnode->setAnimationSpeed(m_animation_speed);
|
m_animated_meshnode->setAnimationSpeed(m_animation_speed);
|
||||||
m_animated_meshnode->setTransitionTime(m_animation_blend);
|
m_animated_meshnode->setTransitionTime(m_animation_blend);
|
||||||
}
|
}
|
||||||
|
@ -1701,6 +1770,7 @@ public:
|
||||||
bool sneak = !readU8(is);
|
bool sneak = !readU8(is);
|
||||||
bool sneak_glitch = !readU8(is);
|
bool sneak_glitch = !readU8(is);
|
||||||
|
|
||||||
|
|
||||||
if(m_is_local_player)
|
if(m_is_local_player)
|
||||||
{
|
{
|
||||||
LocalPlayer *player = m_env->getLocalPlayer();
|
LocalPlayer *player = m_env->getLocalPlayer();
|
||||||
|
@ -1713,11 +1783,31 @@ public:
|
||||||
}
|
}
|
||||||
else if(cmd == GENERIC_CMD_SET_ANIMATION)
|
else if(cmd == GENERIC_CMD_SET_ANIMATION)
|
||||||
{
|
{
|
||||||
m_animation_range = readV2F1000(is);
|
// TODO: change frames send as v2s32 value
|
||||||
m_animation_speed = readF1000(is);
|
v2f range = readV2F1000(is);
|
||||||
m_animation_blend = readF1000(is);
|
if (!m_is_local_player) {
|
||||||
|
m_animation_range = v2s32((s32)range.X, (s32)range.Y);
|
||||||
updateAnimation();
|
m_animation_speed = readF1000(is);
|
||||||
|
m_animation_blend = readF1000(is);
|
||||||
|
updateAnimation();
|
||||||
|
} else {
|
||||||
|
LocalPlayer *player = m_env->getLocalPlayer();
|
||||||
|
if(player->last_animation == NO_ANIM) {
|
||||||
|
m_animation_range = v2s32((s32)range.X, (s32)range.Y);
|
||||||
|
m_animation_speed = readF1000(is);
|
||||||
|
m_animation_blend = readF1000(is);
|
||||||
|
}
|
||||||
|
// update animation only if local animations present
|
||||||
|
// and received animation is not unknown
|
||||||
|
int frames = 0;
|
||||||
|
for (int i = 0;i<4;i++) {
|
||||||
|
frames += (int)player->local_animations[i].Y;
|
||||||
|
}
|
||||||
|
if(frames < 1) {
|
||||||
|
player->last_animation = NO_ANIM;
|
||||||
|
updateAnimation();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(cmd == GENERIC_CMD_SET_BONE_POSITION)
|
else if(cmd == GENERIC_CMD_SET_BONE_POSITION)
|
||||||
{
|
{
|
||||||
|
|
|
@ -219,7 +219,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
if(ntop.getContent() == c_flowing || ntop.getContent() == c_source)
|
if(ntop.getContent() == c_flowing || ntop.getContent() == c_source)
|
||||||
top_is_same_liquid = true;
|
top_is_same_liquid = true;
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 0, data);
|
u16 l = getInteriorLight(n, 0, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(f.alpha, l, decode_light(f.light_source));
|
video::SColor c = MapBlock_LightColor(f.alpha, l, decode_light(f.light_source));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -389,10 +389,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
}
|
}
|
||||||
// Use the light of the node on top if possible
|
// Use the light of the node on top if possible
|
||||||
else if(nodedef->get(ntop).param_type == CPT_LIGHT)
|
else if(nodedef->get(ntop).param_type == CPT_LIGHT)
|
||||||
l = getInteriorLight(ntop, 0, data);
|
l = getInteriorLight(ntop, 0, nodedef);
|
||||||
// Otherwise use the light of this node (the liquid)
|
// Otherwise use the light of this node (the liquid)
|
||||||
else
|
else
|
||||||
l = getInteriorLight(n, 0, data);
|
l = getInteriorLight(n, 0, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(f.alpha, l, decode_light(f.light_source));
|
video::SColor c = MapBlock_LightColor(f.alpha, l, decode_light(f.light_source));
|
||||||
|
|
||||||
u8 range = rangelim(nodedef->get(c_flowing).liquid_range, 1, 8);
|
u8 range = rangelim(nodedef->get(c_flowing).liquid_range, 1, 8);
|
||||||
|
@ -696,7 +696,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
{
|
{
|
||||||
TileSpec tile = getNodeTile(n, p, v3s16(0,0,0), data);
|
TileSpec tile = getNodeTile(n, p, v3s16(0,0,0), data);
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 1, data);
|
u16 l = getInteriorLight(n, 1, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
||||||
|
|
||||||
for(u32 j=0; j<6; j++)
|
for(u32 j=0; j<6; j++)
|
||||||
|
@ -758,7 +758,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
TileSpec tiles[2];
|
TileSpec tiles[2];
|
||||||
tiles[0] = getNodeTile(n, p, dirs[0], data);
|
tiles[0] = getNodeTile(n, p, dirs[0], data);
|
||||||
tiles[1] = getNodeTile(n, p, dirs[1], data);
|
tiles[1] = getNodeTile(n, p, dirs[1], data);
|
||||||
u16 l = getInteriorLight(n, 1, data);
|
u16 l = getInteriorLight(n, 1, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
||||||
v3f pos = intToFloat(p, BS);
|
v3f pos = intToFloat(p, BS);
|
||||||
static const float a=BS/2;
|
static const float a=BS/2;
|
||||||
|
@ -876,7 +876,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
TileSpec tile_leaves = getNodeTile(n, p,
|
TileSpec tile_leaves = getNodeTile(n, p,
|
||||||
v3s16(0,0,0), data);
|
v3s16(0,0,0), data);
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 1, data);
|
u16 l = getInteriorLight(n, 1, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
||||||
|
|
||||||
v3f pos = intToFloat(p, BS);
|
v3f pos = intToFloat(p, BS);
|
||||||
|
@ -909,7 +909,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
tile.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
|
tile.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
|
||||||
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 1, data);
|
u16 l = getInteriorLight(n, 1, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
||||||
|
|
||||||
float s = BS/2*f.visual_scale;
|
float s = BS/2*f.visual_scale;
|
||||||
|
@ -950,7 +950,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
tile.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
|
tile.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
|
||||||
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 0, data);
|
u16 l = getInteriorLight(n, 0, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
||||||
|
|
||||||
float d = (float)BS/16;
|
float d = (float)BS/16;
|
||||||
|
@ -993,7 +993,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
TileSpec tile = getNodeTileN(n, p, 0, data);
|
TileSpec tile = getNodeTileN(n, p, 0, data);
|
||||||
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 1, data);
|
u16 l = getInteriorLight(n, 1, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
||||||
|
|
||||||
float s = BS/2*f.visual_scale;
|
float s = BS/2*f.visual_scale;
|
||||||
|
@ -1045,7 +1045,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
texturestring_rot,
|
texturestring_rot,
|
||||||
&tile_rot.texture_id);
|
&tile_rot.texture_id);
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 1, data);
|
u16 l = getInteriorLight(n, 1, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
||||||
|
|
||||||
const f32 post_rad=(f32)BS/8;
|
const f32 post_rad=(f32)BS/8;
|
||||||
|
@ -1294,7 +1294,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
tile.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
|
tile.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
|
||||||
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 0, data);
|
u16 l = getInteriorLight(n, 0, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
||||||
|
|
||||||
float d = (float)BS/64;
|
float d = (float)BS/64;
|
||||||
|
@ -1333,7 +1333,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
};
|
};
|
||||||
TileSpec tiles[6];
|
TileSpec tiles[6];
|
||||||
|
|
||||||
u16 l = getInteriorLight(n, 0, data);
|
u16 l = getInteriorLight(n, 0, nodedef);
|
||||||
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
|
||||||
|
|
||||||
v3f pos = intToFloat(p, BS);
|
v3f pos = intToFloat(p, BS);
|
||||||
|
|
|
@ -191,7 +191,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemSAO(ServerEnvironment *env, v3f pos,
|
ItemSAO(ServerEnvironment *env, v3f pos,
|
||||||
const std::string itemstring):
|
const std::string &itemstring):
|
||||||
ServerActiveObject(env, pos),
|
ServerActiveObject(env, pos),
|
||||||
m_itemstring(itemstring),
|
m_itemstring(itemstring),
|
||||||
m_itemstring_changed(false),
|
m_itemstring_changed(false),
|
||||||
|
@ -350,7 +350,7 @@ private:
|
||||||
ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), "");
|
ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), "");
|
||||||
|
|
||||||
ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
|
ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
|
||||||
const std::string itemstring)
|
const std::string &itemstring)
|
||||||
{
|
{
|
||||||
return new ItemSAO(env, pos, itemstring);
|
return new ItemSAO(env, pos, itemstring);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "object_properties.h"
|
#include "object_properties.h"
|
||||||
|
|
||||||
ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
|
ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
|
||||||
const std::string itemstring);
|
const std::string &itemstring);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
LuaEntitySAO needs some internals exposed.
|
LuaEntitySAO needs some internals exposed.
|
||||||
|
@ -37,7 +37,7 @@ class LuaEntitySAO : public ServerActiveObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LuaEntitySAO(ServerEnvironment *env, v3f pos,
|
LuaEntitySAO(ServerEnvironment *env, v3f pos,
|
||||||
const std::string &name, const std::string &state);
|
const std::string &name, const std::string &state);
|
||||||
~LuaEntitySAO();
|
~LuaEntitySAO();
|
||||||
u8 getType() const
|
u8 getType() const
|
||||||
{ return ACTIVEOBJECT_TYPE_LUAENTITY; }
|
{ return ACTIVEOBJECT_TYPE_LUAENTITY; }
|
||||||
|
|
|
@ -31,8 +31,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "httpfetch.h"
|
#include "httpfetch.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
|
|
||||||
Json::Value fetchJsonValue(const std::string url,
|
Json::Value fetchJsonValue(const std::string &url,
|
||||||
struct curl_slist *chunk) {
|
struct curl_slist *chunk) {
|
||||||
#if USE_CURL
|
#if USE_CURL
|
||||||
|
|
||||||
HTTPFetchRequest fetchrequest;
|
HTTPFetchRequest fetchrequest;
|
||||||
|
|
|
@ -28,7 +28,7 @@ struct ModStoreModDetails;
|
||||||
std::vector<ModStoreMod> readModStoreList(Json::Value& modlist);
|
std::vector<ModStoreMod> readModStoreList(Json::Value& modlist);
|
||||||
ModStoreModDetails readModStoreModDetails(Json::Value& details);
|
ModStoreModDetails readModStoreModDetails(Json::Value& details);
|
||||||
|
|
||||||
Json::Value fetchJsonValue(const std::string url,
|
Json::Value fetchJsonValue(const std::string &url,
|
||||||
struct curl_slist *chunk);
|
struct curl_slist *chunk);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -151,7 +151,7 @@ MapBlock* Database_Dummy::loadBlock(v3s16 blockpos)
|
||||||
|
|
||||||
void Database_Dummy::listAllLoadableBlocks(std::list<v3s16> &dst)
|
void Database_Dummy::listAllLoadableBlocks(std::list<v3s16> &dst)
|
||||||
{
|
{
|
||||||
for(std::map<unsigned long long, std::string>::iterator x = m_database.begin(); x != m_database.end(); ++x)
|
for(std::map<u64, std::string>::iterator x = m_database.begin(); x != m_database.end(); ++x)
|
||||||
{
|
{
|
||||||
v3s16 p = getIntegerAsBlock(x->first);
|
v3s16 p = getIntegerAsBlock(x->first);
|
||||||
//dstream<<"block_i="<<block_i<<" p="<<PP(p)<<std::endl;
|
//dstream<<"block_i="<<block_i<<" p="<<PP(p)<<std::endl;
|
||||||
|
|
|
@ -20,9 +20,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#ifndef DATABASE_DUMMY_HEADER
|
#ifndef DATABASE_DUMMY_HEADER
|
||||||
#define DATABASE_DUMMY_HEADER
|
#define DATABASE_DUMMY_HEADER
|
||||||
|
|
||||||
#include "database.h"
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "database.h"
|
||||||
|
#include "irrlichttypes.h"
|
||||||
|
|
||||||
class ServerMap;
|
class ServerMap;
|
||||||
|
|
||||||
|
@ -39,6 +40,6 @@ public:
|
||||||
~Database_Dummy();
|
~Database_Dummy();
|
||||||
private:
|
private:
|
||||||
ServerMap *srvmap;
|
ServerMap *srvmap;
|
||||||
std::map<unsigned long long, std::string> m_database;
|
std::map<u64, std::string> m_database;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,224 @@
|
||||||
|
/*
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2014 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#if USE_REDIS
|
||||||
|
/*
|
||||||
|
Redis databases
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "database-redis.h"
|
||||||
|
#include <hiredis.h>
|
||||||
|
|
||||||
|
#include "map.h"
|
||||||
|
#include "mapsector.h"
|
||||||
|
#include "mapblock.h"
|
||||||
|
#include "serialization.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
Database_Redis::Database_Redis(ServerMap *map, std::string savedir)
|
||||||
|
{
|
||||||
|
Settings conf;
|
||||||
|
conf.readConfigFile((std::string(savedir) + DIR_DELIM + "world.mt").c_str());
|
||||||
|
std::string tmp;
|
||||||
|
try {
|
||||||
|
tmp = conf.get("redis_address");
|
||||||
|
hash = conf.get("redis_hash");
|
||||||
|
} catch(SettingNotFoundException e) {
|
||||||
|
throw SettingNotFoundException("Set redis_address and redis_hash in world.mt to use the redis backend");
|
||||||
|
}
|
||||||
|
const char *addr = tmp.c_str();
|
||||||
|
int port = conf.exists("redis_port") ? conf.getU16("redis_port") : 6379;
|
||||||
|
ctx = redisConnect(addr, port);
|
||||||
|
if(!ctx)
|
||||||
|
throw FileNotGoodException("Cannot allocate redis context");
|
||||||
|
else if(ctx->err) {
|
||||||
|
std::string err = std::string("Connection error: ") + ctx->errstr;
|
||||||
|
redisFree(ctx);
|
||||||
|
throw FileNotGoodException(err);
|
||||||
|
}
|
||||||
|
srvmap = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Database_Redis::Initialized(void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Database_Redis::beginSave() {
|
||||||
|
redisReply *reply;
|
||||||
|
reply = (redisReply*) redisCommand(ctx, "MULTI");
|
||||||
|
if(!reply)
|
||||||
|
throw FileNotGoodException(std::string("redis command 'MULTI' failed: ") + ctx->errstr);
|
||||||
|
freeReplyObject(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Database_Redis::endSave() {
|
||||||
|
redisReply *reply;
|
||||||
|
reply = (redisReply*) redisCommand(ctx, "EXEC");
|
||||||
|
if(!reply)
|
||||||
|
throw FileNotGoodException(std::string("redis command 'EXEC' failed: ") + ctx->errstr);
|
||||||
|
freeReplyObject(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Database_Redis::saveBlock(MapBlock *block)
|
||||||
|
{
|
||||||
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
/*
|
||||||
|
Dummy blocks are not written
|
||||||
|
*/
|
||||||
|
if(block->isDummy())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format used for writing
|
||||||
|
u8 version = SER_FMT_VER_HIGHEST_WRITE;
|
||||||
|
// Get destination
|
||||||
|
v3s16 p3d = block->getPos();
|
||||||
|
|
||||||
|
/*
|
||||||
|
[0] u8 serialization version
|
||||||
|
[1] data
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::ostringstream o(std::ios_base::binary);
|
||||||
|
o.write((char*)&version, 1);
|
||||||
|
// Write basic data
|
||||||
|
block->serialize(o, version, true);
|
||||||
|
// Write block to database
|
||||||
|
std::string tmp1 = o.str();
|
||||||
|
std::string tmp2 = i64tos(getBlockAsInteger(p3d));
|
||||||
|
|
||||||
|
redisReply *reply;
|
||||||
|
reply = (redisReply*) redisCommand(ctx, "HSET %s %s %b", hash.c_str(), tmp2.c_str(), tmp1.c_str(), tmp1.size());
|
||||||
|
if(!reply)
|
||||||
|
throw FileNotGoodException(std::string("redis command 'HSET %s %s %b' failed: ") + ctx->errstr);
|
||||||
|
if(reply->type == REDIS_REPLY_ERROR)
|
||||||
|
throw FileNotGoodException("Failed to store block in Database");
|
||||||
|
|
||||||
|
// We just wrote it to the disk so clear modified flag
|
||||||
|
block->resetModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
MapBlock* Database_Redis::loadBlock(v3s16 blockpos)
|
||||||
|
{
|
||||||
|
v2s16 p2d(blockpos.X, blockpos.Z);
|
||||||
|
|
||||||
|
std::string tmp = i64tos(getBlockAsInteger(blockpos));
|
||||||
|
redisReply *reply;
|
||||||
|
reply = (redisReply*) redisCommand(ctx, "HGET %s %s", hash.c_str(), tmp.c_str());
|
||||||
|
if(!reply)
|
||||||
|
throw FileNotGoodException(std::string("redis command 'HGET %s %s' failed: ") + ctx->errstr);
|
||||||
|
|
||||||
|
if (reply->type == REDIS_REPLY_STRING && reply->len == 0) {
|
||||||
|
freeReplyObject(reply);
|
||||||
|
errorstream << "Blank block data in database (reply->len == 0) ("
|
||||||
|
<< blockpos.X << "," << blockpos.Y << "," << blockpos.Z << ")" << std::endl;
|
||||||
|
|
||||||
|
if (g_settings->getBool("ignore_world_load_errors")) {
|
||||||
|
errorstream << "Ignoring block load error. Duck and cover! "
|
||||||
|
<< "(ignore_world_load_errors)" << std::endl;
|
||||||
|
} else {
|
||||||
|
throw SerializationError("Blank block data in database");
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reply->type == REDIS_REPLY_STRING) {
|
||||||
|
/*
|
||||||
|
Make sure sector is loaded
|
||||||
|
*/
|
||||||
|
MapSector *sector = srvmap->createSector(p2d);
|
||||||
|
|
||||||
|
try {
|
||||||
|
std::istringstream is(std::string(reply->str, reply->len), std::ios_base::binary);
|
||||||
|
freeReplyObject(reply); // std::string copies the memory so we can already do this here
|
||||||
|
u8 version = SER_FMT_VER_INVALID;
|
||||||
|
is.read((char *)&version, 1);
|
||||||
|
|
||||||
|
if (is.fail())
|
||||||
|
throw SerializationError("ServerMap::loadBlock(): Failed"
|
||||||
|
" to read MapBlock version");
|
||||||
|
|
||||||
|
MapBlock *block = NULL;
|
||||||
|
bool created_new = false;
|
||||||
|
block = sector->getBlockNoCreateNoEx(blockpos.Y);
|
||||||
|
if (block == NULL)
|
||||||
|
{
|
||||||
|
block = sector->createBlankBlockNoInsert(blockpos.Y);
|
||||||
|
created_new = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read basic data
|
||||||
|
block->deSerialize(is, version, true);
|
||||||
|
|
||||||
|
// If it's a new block, insert it to the map
|
||||||
|
if (created_new)
|
||||||
|
sector->insertBlock(block);
|
||||||
|
|
||||||
|
// We just loaded it from, so it's up-to-date.
|
||||||
|
block->resetModified();
|
||||||
|
}
|
||||||
|
catch (SerializationError &e)
|
||||||
|
{
|
||||||
|
errorstream << "Invalid block data in database"
|
||||||
|
<< " (" << blockpos.X << "," << blockpos.Y << "," << blockpos.Z
|
||||||
|
<< ") (SerializationError): " << e.what() << std::endl;
|
||||||
|
// TODO: Block should be marked as invalid in memory so that it is
|
||||||
|
// not touched but the game can run
|
||||||
|
|
||||||
|
if (g_settings->getBool("ignore_world_load_errors")) {
|
||||||
|
errorstream << "Ignoring block load error. Duck and cover! "
|
||||||
|
<< "(ignore_world_load_errors)" << std::endl;
|
||||||
|
} else {
|
||||||
|
throw SerializationError("Invalid block data in database");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return srvmap->getBlockNoCreateNoEx(blockpos); // should not be using this here
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Database_Redis::listAllLoadableBlocks(std::list<v3s16> &dst)
|
||||||
|
{
|
||||||
|
redisReply *reply;
|
||||||
|
reply = (redisReply*) redisCommand(ctx, "HKEYS %s", hash.c_str());
|
||||||
|
if(!reply)
|
||||||
|
throw FileNotGoodException(std::string("redis command 'HKEYS %s' failed: ") + ctx->errstr);
|
||||||
|
if(reply->type != REDIS_REPLY_ARRAY)
|
||||||
|
throw FileNotGoodException("Failed to get keys from database");
|
||||||
|
for(size_t i = 0; i < reply->elements; i++)
|
||||||
|
{
|
||||||
|
assert(reply->element[i]->type == REDIS_REPLY_STRING);
|
||||||
|
dst.push_back(getIntegerAsBlock(stoi64(reply->element[i]->str)));
|
||||||
|
}
|
||||||
|
freeReplyObject(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
Database_Redis::~Database_Redis()
|
||||||
|
{
|
||||||
|
redisFree(ctx);
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Minetest
|
Minetest
|
||||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2014 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
@ -17,44 +17,34 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GUIMESSAGEMENU_HEADER
|
#ifndef DATABASE_REDIS_HEADER
|
||||||
#define GUIMESSAGEMENU_HEADER
|
#define DATABASE_REDIS_HEADER
|
||||||
|
|
||||||
#include "irrlichttypes_extrabloated.h"
|
#include "config.h"
|
||||||
#include "modalMenu.h"
|
|
||||||
|
#if USE_REDIS
|
||||||
|
|
||||||
|
#include "database.h"
|
||||||
|
#include <hiredis.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class GUIMessageMenu : public GUIModalMenu
|
class ServerMap;
|
||||||
|
|
||||||
|
class Database_Redis : public Database
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GUIMessageMenu(gui::IGUIEnvironment* env,
|
Database_Redis(ServerMap *map, std::string savedir);
|
||||||
gui::IGUIElement* parent, s32 id,
|
virtual void beginSave();
|
||||||
IMenuManager *menumgr,
|
virtual void endSave();
|
||||||
std::wstring message_text);
|
virtual void saveBlock(MapBlock *block);
|
||||||
~GUIMessageMenu();
|
virtual MapBlock* loadBlock(v3s16 blockpos);
|
||||||
|
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
|
||||||
void removeChildren();
|
virtual int Initialized(void);
|
||||||
/*
|
~Database_Redis();
|
||||||
Remove and re-add (or reposition) stuff
|
|
||||||
*/
|
|
||||||
void regenerateGui(v2u32 screensize);
|
|
||||||
|
|
||||||
void drawMenu();
|
|
||||||
|
|
||||||
bool OnEvent(const SEvent& event);
|
|
||||||
|
|
||||||
/*
|
|
||||||
true = ok'd
|
|
||||||
*/
|
|
||||||
bool getStatus()
|
|
||||||
{
|
|
||||||
return m_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::wstring m_message_text;
|
ServerMap *srvmap;
|
||||||
bool m_status;
|
redisContext *ctx;
|
||||||
|
std::string hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
|
@ -20,33 +20,29 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
#include "irrlichttypes.h"
|
#include "irrlichttypes.h"
|
||||||
|
|
||||||
static s32 unsignedToSigned(s32 i, s32 max_positive)
|
static inline s16 unsigned_to_signed(u16 i, u16 max_positive)
|
||||||
{
|
{
|
||||||
if(i < max_positive)
|
if (i < max_positive) {
|
||||||
return i;
|
return i;
|
||||||
else
|
} else {
|
||||||
return i - 2*max_positive;
|
return i - (max_positive * 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// modulo of a negative number does not work consistently in C
|
|
||||||
static s64 pythonmodulo(s64 i, s64 mod)
|
s64 Database::getBlockAsInteger(const v3s16 pos) const
|
||||||
{
|
{
|
||||||
if(i >= 0)
|
return (((u64) pos.Z) << 24) +
|
||||||
return i % mod;
|
(((u64) pos.Y) << 12) +
|
||||||
return mod - ((-i) % mod);
|
((u64) pos.X);
|
||||||
}
|
}
|
||||||
|
|
||||||
long long Database::getBlockAsInteger(const v3s16 pos) {
|
v3s16 Database::getIntegerAsBlock(const s64 i) const
|
||||||
return (unsigned long long)pos.Z*16777216 +
|
{
|
||||||
(unsigned long long)pos.Y*4096 +
|
v3s16 pos;
|
||||||
(unsigned long long)pos.X;
|
pos.Z = unsigned_to_signed((i >> 24) & 0xFFF, 0x1000 / 2);
|
||||||
|
pos.Y = unsigned_to_signed((i >> 12) & 0xFFF, 0x1000 / 2);
|
||||||
|
pos.X = unsigned_to_signed((i ) & 0xFFF, 0x1000 / 2);
|
||||||
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
v3s16 Database::getIntegerAsBlock(long long i) {
|
|
||||||
s32 x = unsignedToSigned(pythonmodulo(i, 4096), 2048);
|
|
||||||
i = (i - x) / 4096;
|
|
||||||
s32 y = unsignedToSigned(pythonmodulo(i, 4096), 2048);
|
|
||||||
i = (i - y) / 4096;
|
|
||||||
s32 z = unsignedToSigned(pythonmodulo(i, 4096), 2048);
|
|
||||||
return v3s16(x,y,z);
|
|
||||||
}
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include "irr_v3d.h"
|
#include "irr_v3d.h"
|
||||||
|
#include "irrlichttypes.h"
|
||||||
|
|
||||||
class MapBlock;
|
class MapBlock;
|
||||||
|
|
||||||
|
@ -33,8 +34,8 @@ public:
|
||||||
|
|
||||||
virtual void saveBlock(MapBlock *block)=0;
|
virtual void saveBlock(MapBlock *block)=0;
|
||||||
virtual MapBlock* loadBlock(v3s16 blockpos)=0;
|
virtual MapBlock* loadBlock(v3s16 blockpos)=0;
|
||||||
long long getBlockAsInteger(const v3s16 pos);
|
s64 getBlockAsInteger(const v3s16 pos) const;
|
||||||
v3s16 getIntegerAsBlock(long long i);
|
v3s16 getIntegerAsBlock(const s64 i) const;
|
||||||
virtual void listAllLoadableBlocks(std::list<v3s16> &dst)=0;
|
virtual void listAllLoadableBlocks(std::list<v3s16> &dst)=0;
|
||||||
virtual int Initialized(void)=0;
|
virtual int Initialized(void)=0;
|
||||||
virtual ~Database() {};
|
virtual ~Database() {};
|
||||||
|
|
|
@ -53,6 +53,7 @@ void set_default_settings(Settings *settings)
|
||||||
settings->setDefault("keymap_toggle_update_camera", "KEY_F4");
|
settings->setDefault("keymap_toggle_update_camera", "KEY_F4");
|
||||||
settings->setDefault("keymap_toggle_debug", "KEY_F5");
|
settings->setDefault("keymap_toggle_debug", "KEY_F5");
|
||||||
settings->setDefault("keymap_toggle_profiler", "KEY_F6");
|
settings->setDefault("keymap_toggle_profiler", "KEY_F6");
|
||||||
|
settings->setDefault("keymap_camera_mode", "KEY_F7");
|
||||||
settings->setDefault("keymap_increase_viewing_range_min", "+");
|
settings->setDefault("keymap_increase_viewing_range_min", "+");
|
||||||
settings->setDefault("keymap_decrease_viewing_range_min", "-");
|
settings->setDefault("keymap_decrease_viewing_range_min", "-");
|
||||||
settings->setDefault("anaglyph", "false");
|
settings->setDefault("anaglyph", "false");
|
||||||
|
@ -130,8 +131,11 @@ void set_default_settings(Settings *settings)
|
||||||
settings->setDefault("preload_item_visuals", "true");
|
settings->setDefault("preload_item_visuals", "true");
|
||||||
settings->setDefault("enable_bumpmapping", "false");
|
settings->setDefault("enable_bumpmapping", "false");
|
||||||
settings->setDefault("enable_parallax_occlusion", "false");
|
settings->setDefault("enable_parallax_occlusion", "false");
|
||||||
settings->setDefault("parallax_occlusion_scale", "0.08");
|
settings->setDefault("generate_normalmaps", "false");
|
||||||
settings->setDefault("parallax_occlusion_bias", "0.04");
|
settings->setDefault("normalmaps_strength", "0.6");
|
||||||
|
settings->setDefault("normalmaps_smooth", "1");
|
||||||
|
settings->setDefault("parallax_occlusion_scale", "0.06");
|
||||||
|
settings->setDefault("parallax_occlusion_bias", "0.03");
|
||||||
settings->setDefault("enable_waving_water", "false");
|
settings->setDefault("enable_waving_water", "false");
|
||||||
settings->setDefault("water_wave_height", "1.0");
|
settings->setDefault("water_wave_height", "1.0");
|
||||||
settings->setDefault("water_wave_length", "20.0");
|
settings->setDefault("water_wave_length", "20.0");
|
||||||
|
@ -240,13 +244,8 @@ void set_default_settings(Settings *settings)
|
||||||
settings->setDefault("movement_gravity", "9.81");
|
settings->setDefault("movement_gravity", "9.81");
|
||||||
|
|
||||||
//liquid stuff
|
//liquid stuff
|
||||||
settings->setDefault("liquid_finite", "false");
|
|
||||||
settings->setDefault("liquid_loop_max", "10000");
|
settings->setDefault("liquid_loop_max", "10000");
|
||||||
settings->setDefault("liquid_update", "1.0");
|
settings->setDefault("liquid_update", "1.0");
|
||||||
settings->setDefault("liquid_relax", "2");
|
|
||||||
settings->setDefault("liquid_fast_flood", "1");
|
|
||||||
settings->setDefault("underground_springs", "1");
|
|
||||||
settings->setDefault("weather", "false");
|
|
||||||
|
|
||||||
//mapgen stuff
|
//mapgen stuff
|
||||||
settings->setDefault("mg_name", "v6");
|
settings->setDefault("mg_name", "v6");
|
||||||
|
|
|
@ -465,13 +465,15 @@ void *EmergeThread::Thread() {
|
||||||
|
|
||||||
v3s16 last_tried_pos(-32768,-32768,-32768); // For error output
|
v3s16 last_tried_pos(-32768,-32768,-32768); // For error output
|
||||||
v3s16 p;
|
v3s16 p;
|
||||||
u8 flags;
|
u8 flags = 0;
|
||||||
|
|
||||||
map = (ServerMap *)&(m_server->m_env->getMap());
|
map = (ServerMap *)&(m_server->m_env->getMap());
|
||||||
emerge = m_server->m_emerge;
|
emerge = m_server->m_emerge;
|
||||||
mapgen = emerge->mapgen[id];
|
mapgen = emerge->mapgen[id];
|
||||||
enable_mapgen_debug_info = emerge->mapgen_debug_info;
|
enable_mapgen_debug_info = emerge->mapgen_debug_info;
|
||||||
|
|
||||||
|
porting::setThreadName("EmergeThread");
|
||||||
|
|
||||||
while (!StopRequested())
|
while (!StopRequested())
|
||||||
try {
|
try {
|
||||||
if (!popBlockEmerge(&p, &flags)) {
|
if (!popBlockEmerge(&p, &flags)) {
|
||||||
|
|
|
@ -85,19 +85,17 @@ void Environment::addPlayer(Player *player)
|
||||||
void Environment::removePlayer(u16 peer_id)
|
void Environment::removePlayer(u16 peer_id)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
re_search:
|
|
||||||
for(std::list<Player*>::iterator i = m_players.begin();
|
for(std::list<Player*>::iterator i = m_players.begin();
|
||||||
i != m_players.end(); ++i)
|
i != m_players.end();)
|
||||||
{
|
{
|
||||||
Player *player = *i;
|
Player *player = *i;
|
||||||
if(player->peer_id != peer_id)
|
if(player->peer_id == peer_id) {
|
||||||
continue;
|
delete player;
|
||||||
|
i = m_players.erase(i);
|
||||||
delete player;
|
} else {
|
||||||
m_players.erase(i);
|
++i;
|
||||||
// See if there is an another one
|
}
|
||||||
// (shouldn't be, but just to be sure)
|
|
||||||
goto re_search;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +314,6 @@ ServerEnvironment::ServerEnvironment(ServerMap *map,
|
||||||
m_map(map),
|
m_map(map),
|
||||||
m_script(scriptIface),
|
m_script(scriptIface),
|
||||||
m_gamedef(gamedef),
|
m_gamedef(gamedef),
|
||||||
m_random_spawn_timer(3),
|
|
||||||
m_send_recommended_timer(0),
|
m_send_recommended_timer(0),
|
||||||
m_active_block_interval_overload_skip(0),
|
m_active_block_interval_overload_skip(0),
|
||||||
m_game_time(0),
|
m_game_time(0),
|
||||||
|
@ -324,7 +321,6 @@ ServerEnvironment::ServerEnvironment(ServerMap *map,
|
||||||
m_recommended_send_interval(0.1),
|
m_recommended_send_interval(0.1),
|
||||||
m_max_lag_estimate(0.1)
|
m_max_lag_estimate(0.1)
|
||||||
{
|
{
|
||||||
m_use_weather = g_settings->getBool("weather");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerEnvironment::~ServerEnvironment()
|
ServerEnvironment::~ServerEnvironment()
|
||||||
|
@ -712,6 +708,34 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Find out how many objects the given block and its neighbours contain.
|
||||||
|
// Returns the number of objects in the block, and also in 'wider' the
|
||||||
|
// number of objects in the block and all its neighbours. The latter
|
||||||
|
// may an estimate if any neighbours are unloaded.
|
||||||
|
u32 countObjects(MapBlock *block, ServerMap * map, u32 &wider)
|
||||||
|
{
|
||||||
|
wider = 0;
|
||||||
|
u32 wider_unknown_count = 0;
|
||||||
|
for(s16 x=-1; x<=1; x++)
|
||||||
|
for(s16 y=-1; y<=1; y++)
|
||||||
|
for(s16 z=-1; z<=1; z++)
|
||||||
|
{
|
||||||
|
MapBlock *block2 = map->getBlockNoCreateNoEx(
|
||||||
|
block->getPos() + v3s16(x,y,z));
|
||||||
|
if(block2==NULL){
|
||||||
|
wider_unknown_count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
wider += block2->m_static_objects.m_active.size()
|
||||||
|
+ block2->m_static_objects.m_stored.size();
|
||||||
|
}
|
||||||
|
// Extrapolate
|
||||||
|
u32 active_object_count = block->m_static_objects.m_active.size();
|
||||||
|
u32 wider_known_count = 3*3*3 - wider_unknown_count;
|
||||||
|
wider += wider_unknown_count * wider / wider_known_count;
|
||||||
|
return active_object_count;
|
||||||
|
|
||||||
|
}
|
||||||
void apply(MapBlock *block)
|
void apply(MapBlock *block)
|
||||||
{
|
{
|
||||||
if(m_aabms.empty())
|
if(m_aabms.empty())
|
||||||
|
@ -719,6 +743,10 @@ public:
|
||||||
|
|
||||||
ServerMap *map = &m_env->getServerMap();
|
ServerMap *map = &m_env->getServerMap();
|
||||||
|
|
||||||
|
u32 active_object_count_wider;
|
||||||
|
u32 active_object_count = this->countObjects(block, map, active_object_count_wider);
|
||||||
|
m_env->m_added_objects = 0;
|
||||||
|
|
||||||
v3s16 p0;
|
v3s16 p0;
|
||||||
for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
|
for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
|
||||||
for(p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++)
|
for(p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++)
|
||||||
|
@ -762,33 +790,16 @@ public:
|
||||||
}
|
}
|
||||||
neighbor_found:
|
neighbor_found:
|
||||||
|
|
||||||
// Find out how many objects the block contains
|
|
||||||
u32 active_object_count = block->m_static_objects.m_active.size();
|
|
||||||
// Find out how many objects this and all the neighbors contain
|
|
||||||
u32 active_object_count_wider = 0;
|
|
||||||
u32 wider_unknown_count = 0;
|
|
||||||
for(s16 x=-1; x<=1; x++)
|
|
||||||
for(s16 y=-1; y<=1; y++)
|
|
||||||
for(s16 z=-1; z<=1; z++)
|
|
||||||
{
|
|
||||||
MapBlock *block2 = map->getBlockNoCreateNoEx(
|
|
||||||
block->getPos() + v3s16(x,y,z));
|
|
||||||
if(block2==NULL){
|
|
||||||
wider_unknown_count = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
active_object_count_wider +=
|
|
||||||
block2->m_static_objects.m_active.size()
|
|
||||||
+ block2->m_static_objects.m_stored.size();
|
|
||||||
}
|
|
||||||
// Extrapolate
|
|
||||||
u32 wider_known_count = 3*3*3 - wider_unknown_count;
|
|
||||||
active_object_count_wider += wider_unknown_count * active_object_count_wider / wider_known_count;
|
|
||||||
|
|
||||||
// Call all the trigger variations
|
// Call all the trigger variations
|
||||||
i->abm->trigger(m_env, p, n);
|
i->abm->trigger(m_env, p, n);
|
||||||
i->abm->trigger(m_env, p, n,
|
i->abm->trigger(m_env, p, n,
|
||||||
active_object_count, active_object_count_wider);
|
active_object_count, active_object_count_wider);
|
||||||
|
|
||||||
|
// Count surrounding objects again if the abms added any
|
||||||
|
if(m_env->m_added_objects > 0) {
|
||||||
|
active_object_count = countObjects(block, map, active_object_count_wider);
|
||||||
|
m_env->m_added_objects = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1084,7 +1095,7 @@ void ServerEnvironment::step(float dtime)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Move
|
// Move
|
||||||
player->move(dtime, *m_map, 100*BS);
|
player->move(dtime, this, 100*BS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1358,6 +1369,7 @@ u16 getFreeServerActiveObjectId(
|
||||||
u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
|
u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
|
||||||
{
|
{
|
||||||
assert(object);
|
assert(object);
|
||||||
|
m_added_objects++;
|
||||||
u16 id = addActiveObjectRaw(object, true, 0);
|
u16 id = addActiveObjectRaw(object, true, 0);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -2381,7 +2393,7 @@ void ClientEnvironment::step(float dtime)
|
||||||
if(player->isLocal() == false)
|
if(player->isLocal() == false)
|
||||||
{
|
{
|
||||||
// Move
|
// Move
|
||||||
player->move(dtime, *m_map, 100*BS);
|
player->move(dtime, this, 100*BS);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,9 @@ public:
|
||||||
m_day_night_ratio_override = value;
|
m_day_night_ratio_override = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// counter used internally when triggering ABMs
|
||||||
|
u32 m_added_objects;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// peer_ids in here should be unique, except that there may be many 0s
|
// peer_ids in here should be unique, except that there may be many 0s
|
||||||
std::list<Player*> m_players;
|
std::list<Player*> m_players;
|
||||||
|
@ -118,6 +121,7 @@ protected:
|
||||||
// Overriding the day-night ratio is useful for custom sky visuals
|
// Overriding the day-night ratio is useful for custom sky visuals
|
||||||
bool m_enable_day_night_ratio_override;
|
bool m_enable_day_night_ratio_override;
|
||||||
u32 m_day_night_ratio_override;
|
u32 m_day_night_ratio_override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -310,9 +314,6 @@ public:
|
||||||
void reportMaxLagEstimate(float f) { m_max_lag_estimate = f; }
|
void reportMaxLagEstimate(float f) { m_max_lag_estimate = f; }
|
||||||
float getMaxLagEstimate() { return m_max_lag_estimate; }
|
float getMaxLagEstimate() { return m_max_lag_estimate; }
|
||||||
|
|
||||||
// is weather active in this environment?
|
|
||||||
bool m_use_weather;
|
|
||||||
|
|
||||||
std::set<v3s16>* getForceloadedBlocks() { return &m_active_blocks.m_forceloaded_list; };
|
std::set<v3s16>* getForceloadedBlocks() { return &m_active_blocks.m_forceloaded_list; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -370,7 +371,6 @@ private:
|
||||||
// Outgoing network message buffer for active objects
|
// Outgoing network message buffer for active objects
|
||||||
std::list<ActiveObjectMessage> m_active_object_messages;
|
std::list<ActiveObjectMessage> m_active_object_messages;
|
||||||
// Some timers
|
// Some timers
|
||||||
float m_random_spawn_timer; // used for experimental code
|
|
||||||
float m_send_recommended_timer;
|
float m_send_recommended_timer;
|
||||||
IntervalLimiter m_object_management_interval;
|
IntervalLimiter m_object_management_interval;
|
||||||
// List of active blocks
|
// List of active blocks
|
||||||
|
|
|
@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
class BaseException : public std::exception
|
class BaseException : public std::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BaseException(const std::string s) throw()
|
BaseException(const std::string &s) throw()
|
||||||
{
|
{
|
||||||
m_s = s;
|
m_s = s;
|
||||||
}
|
}
|
||||||
|
@ -42,78 +42,83 @@ protected:
|
||||||
|
|
||||||
class AsyncQueuedException : public BaseException {
|
class AsyncQueuedException : public BaseException {
|
||||||
public:
|
public:
|
||||||
AsyncQueuedException(std::string s): BaseException(s) {}
|
AsyncQueuedException(const std::string &s): BaseException(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class NotImplementedException : public BaseException {
|
class NotImplementedException : public BaseException {
|
||||||
public:
|
public:
|
||||||
NotImplementedException(std::string s): BaseException(s) {}
|
NotImplementedException(const std::string &s): BaseException(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class AlreadyExistsException : public BaseException {
|
class AlreadyExistsException : public BaseException {
|
||||||
public:
|
public:
|
||||||
AlreadyExistsException(std::string s): BaseException(s) {}
|
AlreadyExistsException(const std::string &s): BaseException(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class VersionMismatchException : public BaseException {
|
class VersionMismatchException : public BaseException {
|
||||||
public:
|
public:
|
||||||
VersionMismatchException(std::string s): BaseException(s) {}
|
VersionMismatchException(const std::string &s): BaseException(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileNotGoodException : public BaseException {
|
class FileNotGoodException : public BaseException {
|
||||||
public:
|
public:
|
||||||
FileNotGoodException(std::string s): BaseException(s) {}
|
FileNotGoodException(const std::string &s): BaseException(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SerializationError : public BaseException {
|
class SerializationError : public BaseException {
|
||||||
public:
|
public:
|
||||||
SerializationError(std::string s): BaseException(s) {}
|
SerializationError(const std::string &s): BaseException(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LoadError : public BaseException {
|
class LoadError : public BaseException {
|
||||||
public:
|
public:
|
||||||
LoadError(std::string s): BaseException(s) {}
|
LoadError(const std::string &s): BaseException(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ContainerFullException : public BaseException {
|
class ContainerFullException : public BaseException {
|
||||||
public:
|
public:
|
||||||
ContainerFullException(std::string s): BaseException(s) {}
|
ContainerFullException(const std::string &s): BaseException(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SettingNotFoundException : public BaseException {
|
class SettingNotFoundException : public BaseException {
|
||||||
public:
|
public:
|
||||||
SettingNotFoundException(std::string s): BaseException(s) {}
|
SettingNotFoundException(const std::string &s): BaseException(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class InvalidFilenameException : public BaseException {
|
class InvalidFilenameException : public BaseException {
|
||||||
public:
|
public:
|
||||||
InvalidFilenameException(std::string s): BaseException(s) {}
|
InvalidFilenameException(const std::string &s): BaseException(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProcessingLimitException : public BaseException {
|
class ProcessingLimitException : public BaseException {
|
||||||
public:
|
public:
|
||||||
ProcessingLimitException(std::string s): BaseException(s) {}
|
ProcessingLimitException(const std::string &s): BaseException(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CommandLineError : public BaseException {
|
class CommandLineError : public BaseException {
|
||||||
public:
|
public:
|
||||||
CommandLineError(std::string s): BaseException(s) {}
|
CommandLineError(const std::string &s): BaseException(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ItemNotFoundException : public BaseException {
|
class ItemNotFoundException : public BaseException {
|
||||||
public:
|
public:
|
||||||
ItemNotFoundException(std::string s): BaseException(s) {}
|
ItemNotFoundException(const std::string &s): BaseException(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ServerError : public BaseException {
|
class ServerError : public BaseException {
|
||||||
public:
|
public:
|
||||||
ServerError(std::string s): BaseException(s) {}
|
ServerError(const std::string &s): BaseException(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Only used on Windows (SEH)
|
// Only used on Windows (SEH)
|
||||||
class FatalSystemException : public BaseException {
|
class FatalSystemException : public BaseException {
|
||||||
public:
|
public:
|
||||||
FatalSystemException(std::string s): BaseException(s) {}
|
FatalSystemException(const std::string &s): BaseException(s) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ClientStateError : public BaseException {
|
||||||
|
public:
|
||||||
|
ClientStateError(std::string s): BaseException(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -126,7 +131,7 @@ public:
|
||||||
InvalidPositionException():
|
InvalidPositionException():
|
||||||
BaseException("Somebody tried to get/set something in a nonexistent position.")
|
BaseException("Somebody tried to get/set something in a nonexistent position.")
|
||||||
{}
|
{}
|
||||||
InvalidPositionException(std::string s):
|
InvalidPositionException(const std::string &s):
|
||||||
BaseException(s)
|
BaseException(s)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
382
src/game.cpp
382
src/game.cpp
|
@ -28,7 +28,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "IMeshCache.h"
|
#include "IMeshCache.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "guiPauseMenu.h"
|
|
||||||
#include "guiPasswordChange.h"
|
#include "guiPasswordChange.h"
|
||||||
#include "guiVolumeChange.h"
|
#include "guiVolumeChange.h"
|
||||||
#include "guiFormSpecMenu.h"
|
#include "guiFormSpecMenu.h"
|
||||||
|
@ -75,24 +74,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Text input system
|
Text input system
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct TextDestChat : public TextDest
|
|
||||||
{
|
|
||||||
TextDestChat(Client *client)
|
|
||||||
{
|
|
||||||
m_client = client;
|
|
||||||
}
|
|
||||||
void gotText(std::wstring text)
|
|
||||||
{
|
|
||||||
m_client->typeChatMessage(text);
|
|
||||||
}
|
|
||||||
void gotText(std::map<std::string, std::string> fields)
|
|
||||||
{
|
|
||||||
m_client->typeChatMessage(narrow_to_wide(fields["text"]));
|
|
||||||
}
|
|
||||||
|
|
||||||
Client *m_client;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TextDestNodeMetadata : public TextDest
|
struct TextDestNodeMetadata : public TextDest
|
||||||
{
|
{
|
||||||
TextDestNodeMetadata(v3s16 p, Client *client)
|
TextDestNodeMetadata(v3s16 p, Client *client)
|
||||||
|
@ -136,12 +117,81 @@ struct TextDestPlayerInventory : public TextDest
|
||||||
m_client->sendInventoryFields(m_formname, fields);
|
m_client->sendInventoryFields(m_formname, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFormName(std::string formname) {
|
Client *m_client;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LocalFormspecHandler : public TextDest
|
||||||
|
{
|
||||||
|
LocalFormspecHandler();
|
||||||
|
LocalFormspecHandler(std::string formname) {
|
||||||
m_formname = formname;
|
m_formname = formname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LocalFormspecHandler(std::string formname,Client *client) {
|
||||||
|
m_formname = formname;
|
||||||
|
m_client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gotText(std::wstring message) {
|
||||||
|
errorstream << "LocalFormspecHandler::gotText old style message received" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gotText(std::map<std::string, std::string> fields)
|
||||||
|
{
|
||||||
|
if (m_formname == "MT_PAUSE_MENU") {
|
||||||
|
if (fields.find("btn_sound") != fields.end()) {
|
||||||
|
g_gamecallback->changeVolume();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fields.find("btn_exit_menu") != fields.end()) {
|
||||||
|
g_gamecallback->disconnect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fields.find("btn_exit_os") != fields.end()) {
|
||||||
|
g_gamecallback->exitToOS();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fields.find("btn_change_password") != fields.end()) {
|
||||||
|
g_gamecallback->changePassword();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fields.find("quit") != fields.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fields.find("btn_continue") != fields.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_formname == "MT_CHAT_MENU") {
|
||||||
|
if ((fields.find("btn_send") != fields.end()) ||
|
||||||
|
(fields.find("quit") != fields.end())) {
|
||||||
|
if (fields.find("f_text") != fields.end()) {
|
||||||
|
if (m_client != 0) {
|
||||||
|
m_client->typeChatMessage(narrow_to_wide(fields["f_text"]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
errorstream << "LocalFormspecHandler::gotText received chat message but m_client is NULL" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errorstream << "LocalFormspecHandler::gotText unhandled >" << m_formname << "< event" << std::endl;
|
||||||
|
int i = 0;
|
||||||
|
for (std::map<std::string,std::string>::iterator iter = fields.begin();
|
||||||
|
iter != fields.end(); iter++) {
|
||||||
|
errorstream << "\t"<< i << ": " << iter->first << "=" << iter->second << std::endl;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Client *m_client;
|
Client *m_client;
|
||||||
std::string m_formname;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Respawn menu callback */
|
/* Respawn menu callback */
|
||||||
|
@ -224,13 +274,9 @@ inline bool isPointableNode(const MapNode& n,
|
||||||
Find what the player is pointing at
|
Find what the player is pointing at
|
||||||
*/
|
*/
|
||||||
PointedThing getPointedThing(Client *client, v3f player_position,
|
PointedThing getPointedThing(Client *client, v3f player_position,
|
||||||
v3f camera_direction, v3f camera_position,
|
v3f camera_direction, v3f camera_position, core::line3d<f32> shootline,
|
||||||
core::line3d<f32> shootline, f32 d,
|
f32 d, bool liquids_pointable, bool look_for_object, v3s16 camera_offset,
|
||||||
bool liquids_pointable,
|
std::vector<aabb3f> &hilightboxes, ClientActiveObject *&selected_object)
|
||||||
bool look_for_object,
|
|
||||||
v3s16 camera_offset,
|
|
||||||
std::vector<aabb3f> &hilightboxes,
|
|
||||||
ClientActiveObject *&selected_object)
|
|
||||||
{
|
{
|
||||||
PointedThing result;
|
PointedThing result;
|
||||||
|
|
||||||
|
@ -379,9 +425,8 @@ PointedThing getPointedThing(Client *client, v3f player_position,
|
||||||
Additionally, a progressbar can be drawn when percent is set between 0 and 100.
|
Additionally, a progressbar can be drawn when percent is set between 0 and 100.
|
||||||
*/
|
*/
|
||||||
/*gui::IGUIStaticText **/
|
/*gui::IGUIStaticText **/
|
||||||
void draw_load_screen(const std::wstring &text,
|
void draw_load_screen(const std::wstring &text, IrrlichtDevice* device,
|
||||||
IrrlichtDevice* device, gui::IGUIFont* font,
|
gui::IGUIFont* font, float dtime=0 ,int percent=0, bool clouds=true)
|
||||||
float dtime=0 ,int percent=0, bool clouds=true)
|
|
||||||
{
|
{
|
||||||
video::IVideoDriver* driver = device->getVideoDriver();
|
video::IVideoDriver* driver = device->getVideoDriver();
|
||||||
v2u32 screensize = driver->getScreenSize();
|
v2u32 screensize = driver->getScreenSize();
|
||||||
|
@ -430,8 +475,8 @@ void draw_load_screen(const std::wstring &text,
|
||||||
/* Profiler display */
|
/* Profiler display */
|
||||||
|
|
||||||
void update_profiler_gui(gui::IGUIStaticText *guitext_profiler,
|
void update_profiler_gui(gui::IGUIStaticText *guitext_profiler,
|
||||||
gui::IGUIFont *font, u32 text_height,
|
gui::IGUIFont *font, u32 text_height, u32 show_profiler,
|
||||||
u32 show_profiler, u32 show_profiler_max)
|
u32 show_profiler_max)
|
||||||
{
|
{
|
||||||
if(show_profiler == 0)
|
if(show_profiler == 0)
|
||||||
{
|
{
|
||||||
|
@ -818,14 +863,17 @@ public:
|
||||||
services->setPixelShaderConstant("eyePosition", (irr::f32*)&eye_position, 3);
|
services->setPixelShaderConstant("eyePosition", (irr::f32*)&eye_position, 3);
|
||||||
services->setVertexShaderConstant("eyePosition", (irr::f32*)&eye_position, 3);
|
services->setVertexShaderConstant("eyePosition", (irr::f32*)&eye_position, 3);
|
||||||
|
|
||||||
// Normal map texture layer
|
// Uniform sampler layers
|
||||||
|
int layer0 = 0;
|
||||||
int layer1 = 1;
|
int layer1 = 1;
|
||||||
int layer2 = 2;
|
int layer2 = 2;
|
||||||
// before 1.8 there isn't a "integer interface", only float
|
// before 1.8 there isn't a "integer interface", only float
|
||||||
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
|
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
|
||||||
|
services->setPixelShaderConstant("baseTexture" , (irr::f32*)&layer0, 1);
|
||||||
services->setPixelShaderConstant("normalTexture" , (irr::f32*)&layer1, 1);
|
services->setPixelShaderConstant("normalTexture" , (irr::f32*)&layer1, 1);
|
||||||
services->setPixelShaderConstant("useNormalmap" , (irr::f32*)&layer2, 1);
|
services->setPixelShaderConstant("useNormalmap" , (irr::f32*)&layer2, 1);
|
||||||
#else
|
#else
|
||||||
|
services->setPixelShaderConstant("baseTexture" , (irr::s32*)&layer0, 1);
|
||||||
services->setPixelShaderConstant("normalTexture" , (irr::s32*)&layer1, 1);
|
services->setPixelShaderConstant("normalTexture" , (irr::s32*)&layer1, 1);
|
||||||
services->setPixelShaderConstant("useNormalmap" , (irr::s32*)&layer2, 1);
|
services->setPixelShaderConstant("useNormalmap" , (irr::s32*)&layer2, 1);
|
||||||
#endif
|
#endif
|
||||||
|
@ -833,8 +881,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
bool nodePlacementPrediction(Client &client,
|
bool nodePlacementPrediction(Client &client,
|
||||||
const ItemDefinition &playeritem_def,
|
const ItemDefinition &playeritem_def, v3s16 nodepos, v3s16 neighbourpos)
|
||||||
v3s16 nodepos, v3s16 neighbourpos)
|
|
||||||
{
|
{
|
||||||
std::string prediction = playeritem_def.node_placement_prediction;
|
std::string prediction = playeritem_def.node_placement_prediction;
|
||||||
INodeDefManager *nodedef = client.ndef();
|
INodeDefManager *nodedef = client.ndef();
|
||||||
|
@ -930,26 +977,98 @@ bool nodePlacementPrediction(Client &client,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void show_chat_menu(FormspecFormSource* current_formspec,
|
||||||
|
TextDest* current_textdest, IWritableTextureSource* tsrc,
|
||||||
|
IrrlichtDevice * device, Client* client, std::string text)
|
||||||
|
{
|
||||||
|
std::string formspec =
|
||||||
|
"size[11,5.5,true]"
|
||||||
|
"field[3,2.35;6,0.5;f_text;;" + text + "]"
|
||||||
|
"button_exit[4,3;3,0.5;btn_send;" + wide_to_narrow(wstrgettext("Proceed")) + "]"
|
||||||
|
;
|
||||||
|
|
||||||
void the_game(
|
/* Create menu */
|
||||||
bool &kill,
|
/* Note: FormspecFormSource and LocalFormspecHandler
|
||||||
bool random_input,
|
* are deleted by guiFormSpecMenu */
|
||||||
InputHandler *input,
|
current_formspec = new FormspecFormSource(formspec,¤t_formspec);
|
||||||
IrrlichtDevice *device,
|
current_textdest = new LocalFormspecHandler("MT_CHAT_MENU",client);
|
||||||
gui::IGUIFont* font,
|
GUIFormSpecMenu *menu =
|
||||||
std::string map_dir,
|
new GUIFormSpecMenu(device, guiroot, -1,
|
||||||
std::string playername,
|
&g_menumgr,
|
||||||
std::string password,
|
NULL, NULL, tsrc);
|
||||||
std::string address, // If "", local server is used
|
menu->doPause = false;
|
||||||
u16 port,
|
menu->setFormSource(current_formspec);
|
||||||
std::wstring &error_message,
|
menu->setTextDest(current_textdest);
|
||||||
ChatBackend &chat_backend,
|
menu->drop();
|
||||||
const SubgameSpec &gamespec, // Used for local game,
|
}
|
||||||
bool simple_singleplayer_mode
|
|
||||||
)
|
/******************************************************************************/
|
||||||
|
static void show_pause_menu(FormspecFormSource* current_formspec,
|
||||||
|
TextDest* current_textdest, IWritableTextureSource* tsrc,
|
||||||
|
IrrlichtDevice * device, bool singleplayermode)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::string control_text = wide_to_narrow(wstrgettext("Default Controls:\n"
|
||||||
|
"- WASD: move\n"
|
||||||
|
"- Space: jump/climb\n"
|
||||||
|
"- Shift: sneak/go down\n"
|
||||||
|
"- Q: drop item\n"
|
||||||
|
"- I: inventory\n"
|
||||||
|
"- Mouse: turn/look\n"
|
||||||
|
"- Mouse left: dig/punch\n"
|
||||||
|
"- Mouse right: place/use\n"
|
||||||
|
"- Mouse wheel: select item\n"
|
||||||
|
"- T: chat\n"
|
||||||
|
));
|
||||||
|
|
||||||
|
float ypos = singleplayermode ? 1.0 : 0.5;
|
||||||
|
std::ostringstream os;
|
||||||
|
|
||||||
|
os << "size[11,5.5,true]"
|
||||||
|
<< "button_exit[4," << (ypos++) << ";3,0.5;btn_continue;"
|
||||||
|
<< wide_to_narrow(wstrgettext("Continue")) << "]";
|
||||||
|
|
||||||
|
if (!singleplayermode) {
|
||||||
|
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_change_password;"
|
||||||
|
<< wide_to_narrow(wstrgettext("Change Password")) << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_sound;"
|
||||||
|
<< wide_to_narrow(wstrgettext("Sound Volume")) << "]";
|
||||||
|
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_exit_menu;"
|
||||||
|
<< wide_to_narrow(wstrgettext("Exit to Menu")) << "]";
|
||||||
|
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_exit_os;"
|
||||||
|
<< wide_to_narrow(wstrgettext("Exit to OS")) << "]"
|
||||||
|
<< "textarea[7.5,0.25;3.75,6;;" << control_text << ";]"
|
||||||
|
<< "textarea[0.4,0.25;3.5,6;;" << "Minetest\n"
|
||||||
|
<< minetest_build_info << "\n"
|
||||||
|
<< "path_user = " << wrap_rows(porting::path_user, 20)
|
||||||
|
<< "\n;]";
|
||||||
|
|
||||||
|
/* Create menu */
|
||||||
|
/* Note: FormspecFormSource and LocalFormspecHandler *
|
||||||
|
* are deleted by guiFormSpecMenu */
|
||||||
|
current_formspec = new FormspecFormSource(os.str(),¤t_formspec);
|
||||||
|
current_textdest = new LocalFormspecHandler("MT_PAUSE_MENU");
|
||||||
|
GUIFormSpecMenu *menu =
|
||||||
|
new GUIFormSpecMenu(device, guiroot, -1, &g_menumgr, NULL, NULL, tsrc);
|
||||||
|
menu->doPause = true;
|
||||||
|
menu->setFormSource(current_formspec);
|
||||||
|
menu->setTextDest(current_textdest);
|
||||||
|
menu->drop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
void the_game(bool &kill, bool random_input, InputHandler *input,
|
||||||
|
IrrlichtDevice *device, gui::IGUIFont* font, std::string map_dir,
|
||||||
|
std::string playername, std::string password,
|
||||||
|
std::string address /* If "", local server is used */,
|
||||||
|
u16 port, std::wstring &error_message, ChatBackend &chat_backend,
|
||||||
|
const SubgameSpec &gamespec /* Used for local game */,
|
||||||
|
bool simple_singleplayer_mode)
|
||||||
{
|
{
|
||||||
FormspecFormSource* current_formspec = 0;
|
FormspecFormSource* current_formspec = 0;
|
||||||
TextDestPlayerInventory* current_textdest = 0;
|
TextDest* current_textdest = 0;
|
||||||
video::IVideoDriver* driver = device->getVideoDriver();
|
video::IVideoDriver* driver = device->getVideoDriver();
|
||||||
scene::ISceneManager* smgr = device->getSceneManager();
|
scene::ISceneManager* smgr = device->getSceneManager();
|
||||||
|
|
||||||
|
@ -1028,27 +1147,34 @@ void the_game(
|
||||||
draw_load_screen(text, device, font,0,25);
|
draw_load_screen(text, device, font,0,25);
|
||||||
delete[] text;
|
delete[] text;
|
||||||
infostream<<"Creating server"<<std::endl;
|
infostream<<"Creating server"<<std::endl;
|
||||||
server = new Server(map_dir, gamespec,
|
|
||||||
simple_singleplayer_mode);
|
|
||||||
|
|
||||||
std::string bind_str = g_settings->get("bind_address");
|
std::string bind_str = g_settings->get("bind_address");
|
||||||
Address bind_addr(0,0,0,0, port);
|
Address bind_addr(0,0,0,0, port);
|
||||||
|
|
||||||
if (bind_str != "")
|
if (g_settings->getBool("ipv6_server")) {
|
||||||
{
|
bind_addr.setAddress((IPv6AddressBytes*) NULL);
|
||||||
try {
|
|
||||||
bind_addr.Resolve(bind_str.c_str());
|
|
||||||
address = bind_str;
|
|
||||||
} catch (ResolveError &e) {
|
|
||||||
infostream << "Resolving bind address \"" << bind_str
|
|
||||||
<< "\" failed: " << e.what()
|
|
||||||
<< " -- Listening on all addresses." << std::endl;
|
|
||||||
|
|
||||||
if (g_settings->getBool("ipv6_server")) {
|
|
||||||
bind_addr.setAddress((IPv6AddressBytes*) NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
bind_addr.Resolve(bind_str.c_str());
|
||||||
|
address = bind_str;
|
||||||
|
} catch (ResolveError &e) {
|
||||||
|
infostream << "Resolving bind address \"" << bind_str
|
||||||
|
<< "\" failed: " << e.what()
|
||||||
|
<< " -- Listening on all addresses." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bind_addr.isIPv6() && !g_settings->getBool("enable_ipv6")) {
|
||||||
|
error_message = L"Unable to listen on " +
|
||||||
|
narrow_to_wide(bind_addr.serializeString()) +
|
||||||
|
L" because IPv6 is disabled";
|
||||||
|
errorstream<<wide_to_narrow(error_message)<<std::endl;
|
||||||
|
// Break out of client scope
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
server = new Server(map_dir, gamespec,
|
||||||
|
simple_singleplayer_mode,
|
||||||
|
bind_addr.isIPv6());
|
||||||
|
|
||||||
server->start(bind_addr);
|
server->start(bind_addr);
|
||||||
}
|
}
|
||||||
|
@ -1074,31 +1200,33 @@ void the_game(
|
||||||
delete[] text;
|
delete[] text;
|
||||||
}
|
}
|
||||||
Address connect_address(0,0,0,0, port);
|
Address connect_address(0,0,0,0, port);
|
||||||
try{
|
try {
|
||||||
if(address == "")
|
connect_address.Resolve(address.c_str());
|
||||||
{
|
if (connect_address.isZero()) { // i.e. INADDR_ANY, IN6ADDR_ANY
|
||||||
//connect_address.Resolve("localhost");
|
//connect_address.Resolve("localhost");
|
||||||
if(g_settings->getBool("enable_ipv6") && g_settings->getBool("ipv6_server"))
|
if (connect_address.isIPv6()) {
|
||||||
{
|
|
||||||
IPv6AddressBytes addr_bytes;
|
IPv6AddressBytes addr_bytes;
|
||||||
addr_bytes.bytes[15] = 1;
|
addr_bytes.bytes[15] = 1;
|
||||||
connect_address.setAddress(&addr_bytes);
|
connect_address.setAddress(&addr_bytes);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
connect_address.setAddress(127,0,0,1);
|
connect_address.setAddress(127,0,0,1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
connect_address.Resolve(address.c_str());
|
|
||||||
}
|
}
|
||||||
catch(ResolveError &e)
|
catch(ResolveError &e) {
|
||||||
{
|
|
||||||
error_message = L"Couldn't resolve address: " + narrow_to_wide(e.what());
|
error_message = L"Couldn't resolve address: " + narrow_to_wide(e.what());
|
||||||
errorstream<<wide_to_narrow(error_message)<<std::endl;
|
errorstream<<wide_to_narrow(error_message)<<std::endl;
|
||||||
// Break out of client scope
|
// Break out of client scope
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if(connect_address.isIPv6() && !g_settings->getBool("enable_ipv6")) {
|
||||||
|
error_message = L"Unable to connect to " +
|
||||||
|
narrow_to_wide(connect_address.serializeString()) +
|
||||||
|
L" because IPv6 is disabled";
|
||||||
|
errorstream<<wide_to_narrow(error_message)<<std::endl;
|
||||||
|
// Break out of client scope
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create client
|
Create client
|
||||||
|
@ -1147,7 +1275,7 @@ void the_game(
|
||||||
server->step(dtime);
|
server->step(dtime);
|
||||||
|
|
||||||
// End condition
|
// End condition
|
||||||
if(client.connectedAndInitialized()){
|
if(client.getState() == LC_Init){
|
||||||
could_connect = true;
|
could_connect = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1254,7 +1382,7 @@ void the_game(
|
||||||
errorstream<<wide_to_narrow(error_message)<<std::endl;
|
errorstream<<wide_to_narrow(error_message)<<std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!client.connectedAndInitialized()){
|
if(client.getState() < LC_Init){
|
||||||
error_message = L"Client disconnected";
|
error_message = L"Client disconnected";
|
||||||
errorstream<<wide_to_narrow(error_message)<<std::endl;
|
errorstream<<wide_to_narrow(error_message)<<std::endl;
|
||||||
break;
|
break;
|
||||||
|
@ -1342,6 +1470,8 @@ void the_game(
|
||||||
f32 camera_yaw = 0; // "right/left"
|
f32 camera_yaw = 0; // "right/left"
|
||||||
f32 camera_pitch = 0; // "up/down"
|
f32 camera_pitch = 0; // "up/down"
|
||||||
|
|
||||||
|
int current_camera_mode = CAMERA_MODE_FIRST; // start in first-person view
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Clouds
|
Clouds
|
||||||
*/
|
*/
|
||||||
|
@ -1512,8 +1642,6 @@ void the_game(
|
||||||
Hud hud(driver, smgr, guienv, font, text_height,
|
Hud hud(driver, smgr, guienv, font, text_height,
|
||||||
gamedef, player, &local_inventory);
|
gamedef, player, &local_inventory);
|
||||||
|
|
||||||
bool use_weather = g_settings->getBool("weather");
|
|
||||||
|
|
||||||
core::stringw str = L"Minetest [";
|
core::stringw str = L"Minetest [";
|
||||||
str += driver->getName();
|
str += driver->getName();
|
||||||
str += "]";
|
str += "]";
|
||||||
|
@ -1781,6 +1909,7 @@ void the_game(
|
||||||
|
|
||||||
PlayerInventoryFormSource *src = new PlayerInventoryFormSource(&client);
|
PlayerInventoryFormSource *src = new PlayerInventoryFormSource(&client);
|
||||||
assert(src);
|
assert(src);
|
||||||
|
menu->doPause = false;
|
||||||
menu->setFormSpec(src->getForm(), inventoryloc);
|
menu->setFormSpec(src->getForm(), inventoryloc);
|
||||||
menu->setFormSource(src);
|
menu->setFormSource(src);
|
||||||
menu->setTextDest(new TextDestPlayerInventory(&client));
|
menu->setTextDest(new TextDestPlayerInventory(&client));
|
||||||
|
@ -1788,33 +1917,16 @@ void the_game(
|
||||||
}
|
}
|
||||||
else if(input->wasKeyDown(EscapeKey))
|
else if(input->wasKeyDown(EscapeKey))
|
||||||
{
|
{
|
||||||
infostream<<"the_game: "
|
show_pause_menu(current_formspec, current_textdest, tsrc, device,
|
||||||
<<"Launching pause menu"<<std::endl;
|
simple_singleplayer_mode);
|
||||||
// It will delete itself by itself
|
|
||||||
(new GUIPauseMenu(guienv, guiroot, -1, g_gamecallback,
|
|
||||||
&g_menumgr, simple_singleplayer_mode))->drop();
|
|
||||||
|
|
||||||
// Move mouse cursor on top of the disconnect button
|
|
||||||
if(simple_singleplayer_mode)
|
|
||||||
input->setMousePos(displaycenter.X, displaycenter.Y+0);
|
|
||||||
else
|
|
||||||
input->setMousePos(displaycenter.X, displaycenter.Y+25);
|
|
||||||
}
|
}
|
||||||
else if(input->wasKeyDown(getKeySetting("keymap_chat")))
|
else if(input->wasKeyDown(getKeySetting("keymap_chat")))
|
||||||
{
|
{
|
||||||
TextDest *dest = new TextDestChat(&client);
|
show_chat_menu(current_formspec, current_textdest, tsrc, device, &client,"");
|
||||||
|
|
||||||
(new GUITextInputMenu(guienv, guiroot, -1,
|
|
||||||
&g_menumgr, dest,
|
|
||||||
L""))->drop();
|
|
||||||
}
|
}
|
||||||
else if(input->wasKeyDown(getKeySetting("keymap_cmd")))
|
else if(input->wasKeyDown(getKeySetting("keymap_cmd")))
|
||||||
{
|
{
|
||||||
TextDest *dest = new TextDestChat(&client);
|
show_chat_menu(current_formspec, current_textdest, tsrc, device, &client,"/");
|
||||||
|
|
||||||
(new GUITextInputMenu(guienv, guiroot, -1,
|
|
||||||
&g_menumgr, dest,
|
|
||||||
L"/"))->drop();
|
|
||||||
}
|
}
|
||||||
else if(input->wasKeyDown(getKeySetting("keymap_console")))
|
else if(input->wasKeyDown(getKeySetting("keymap_console")))
|
||||||
{
|
{
|
||||||
|
@ -2139,7 +2251,7 @@ void the_game(
|
||||||
else{
|
else{
|
||||||
s32 dx = input->getMousePos().X - displaycenter.X;
|
s32 dx = input->getMousePos().X - displaycenter.X;
|
||||||
s32 dy = input->getMousePos().Y - displaycenter.Y;
|
s32 dy = input->getMousePos().Y - displaycenter.Y;
|
||||||
if(invert_mouse)
|
if(invert_mouse || player->camera_mode == CAMERA_MODE_THIRD_FRONT)
|
||||||
dy = -dy;
|
dy = -dy;
|
||||||
//infostream<<"window active, pos difference "<<dx<<","<<dy<<std::endl;
|
//infostream<<"window active, pos difference "<<dx<<","<<dy<<std::endl;
|
||||||
|
|
||||||
|
@ -2204,18 +2316,17 @@ void the_game(
|
||||||
camera_yaw
|
camera_yaw
|
||||||
);
|
);
|
||||||
client.setPlayerControl(control);
|
client.setPlayerControl(control);
|
||||||
u32 keyPressed=
|
|
||||||
1*(int)input->isKeyDown(getKeySetting("keymap_forward"))+
|
|
||||||
2*(int)input->isKeyDown(getKeySetting("keymap_backward"))+
|
|
||||||
4*(int)input->isKeyDown(getKeySetting("keymap_left"))+
|
|
||||||
8*(int)input->isKeyDown(getKeySetting("keymap_right"))+
|
|
||||||
16*(int)input->isKeyDown(getKeySetting("keymap_jump"))+
|
|
||||||
32*(int)input->isKeyDown(getKeySetting("keymap_special1"))+
|
|
||||||
64*(int)input->isKeyDown(getKeySetting("keymap_sneak"))+
|
|
||||||
128*(int)input->getLeftState()+
|
|
||||||
256*(int)input->getRightState();
|
|
||||||
LocalPlayer* player = client.getEnv().getLocalPlayer();
|
LocalPlayer* player = client.getEnv().getLocalPlayer();
|
||||||
player->keyPressed=keyPressed;
|
player->keyPressed=
|
||||||
|
(((int)input->isKeyDown(getKeySetting("keymap_forward")) & 0x1) << 0) |
|
||||||
|
(((int)input->isKeyDown(getKeySetting("keymap_backward")) & 0x1) << 1) |
|
||||||
|
(((int)input->isKeyDown(getKeySetting("keymap_left")) & 0x1) << 2) |
|
||||||
|
(((int)input->isKeyDown(getKeySetting("keymap_right")) & 0x1) << 3) |
|
||||||
|
(((int)input->isKeyDown(getKeySetting("keymap_jump")) & 0x1) << 4) |
|
||||||
|
(((int)input->isKeyDown(getKeySetting("keymap_special1")) & 0x1) << 5) |
|
||||||
|
(((int)input->isKeyDown(getKeySetting("keymap_sneak")) & 0x1) << 6) |
|
||||||
|
(((int)input->getLeftState() & 0x1) << 7) |
|
||||||
|
(((int)input->getRightState() & 0x1) << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2317,6 +2428,7 @@ void the_game(
|
||||||
new GUIFormSpecMenu(device, guiroot, -1,
|
new GUIFormSpecMenu(device, guiroot, -1,
|
||||||
&g_menumgr,
|
&g_menumgr,
|
||||||
&client, gamedef, tsrc);
|
&client, gamedef, tsrc);
|
||||||
|
menu->doPause = false;
|
||||||
menu->setFormSource(current_formspec);
|
menu->setFormSource(current_formspec);
|
||||||
menu->setTextDest(current_textdest);
|
menu->setTextDest(current_textdest);
|
||||||
menu->drop();
|
menu->drop();
|
||||||
|
@ -2547,13 +2659,24 @@ void the_game(
|
||||||
LocalPlayer* player = client.getEnv().getLocalPlayer();
|
LocalPlayer* player = client.getEnv().getLocalPlayer();
|
||||||
float full_punch_interval = playeritem_toolcap.full_punch_interval;
|
float full_punch_interval = playeritem_toolcap.full_punch_interval;
|
||||||
float tool_reload_ratio = time_from_last_punch / full_punch_interval;
|
float tool_reload_ratio = time_from_last_punch / full_punch_interval;
|
||||||
|
|
||||||
|
if(input->wasKeyDown(getKeySetting("keymap_camera_mode"))) {
|
||||||
|
|
||||||
|
if (current_camera_mode == CAMERA_MODE_FIRST)
|
||||||
|
current_camera_mode = CAMERA_MODE_THIRD;
|
||||||
|
else if (current_camera_mode == CAMERA_MODE_THIRD)
|
||||||
|
current_camera_mode = CAMERA_MODE_THIRD_FRONT;
|
||||||
|
else
|
||||||
|
current_camera_mode = CAMERA_MODE_FIRST;
|
||||||
|
|
||||||
|
}
|
||||||
|
player->camera_mode = current_camera_mode;
|
||||||
tool_reload_ratio = MYMIN(tool_reload_ratio, 1.0);
|
tool_reload_ratio = MYMIN(tool_reload_ratio, 1.0);
|
||||||
camera.update(player, dtime, busytime, screensize,
|
camera.update(player, dtime, busytime, screensize, tool_reload_ratio,
|
||||||
tool_reload_ratio);
|
current_camera_mode, client.getEnv());
|
||||||
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();
|
||||||
|
@ -2573,7 +2696,7 @@ void the_game(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update sound listener
|
// Update sound listener
|
||||||
sound->updateListener(camera.getCameraNode()->getPosition(),
|
sound->updateListener(camera.getCameraNode()->getPosition()+intToFloat(camera_offset, BS),
|
||||||
v3f(0,0,0), // velocity
|
v3f(0,0,0), // velocity
|
||||||
camera.getDirection(),
|
camera.getDirection(),
|
||||||
camera.getCameraNode()->getUpVector());
|
camera.getCameraNode()->getUpVector());
|
||||||
|
@ -2605,6 +2728,10 @@ void the_game(
|
||||||
core::line3d<f32> shootline(camera_position,
|
core::line3d<f32> shootline(camera_position,
|
||||||
camera_position + camera_direction * BS * (d+1));
|
camera_position + camera_direction * BS * (d+1));
|
||||||
|
|
||||||
|
// prevent player pointing anything in front-view
|
||||||
|
if (current_camera_mode == CAMERA_MODE_THIRD_FRONT)
|
||||||
|
shootline = core::line3d<f32>(0,0,0,0,0,0);
|
||||||
|
|
||||||
ClientActiveObject *selected_object = NULL;
|
ClientActiveObject *selected_object = NULL;
|
||||||
|
|
||||||
PointedThing pointed = getPointedThing(
|
PointedThing pointed = getPointedThing(
|
||||||
|
@ -2871,6 +2998,7 @@ void the_game(
|
||||||
new GUIFormSpecMenu(device, guiroot, -1,
|
new GUIFormSpecMenu(device, guiroot, -1,
|
||||||
&g_menumgr,
|
&g_menumgr,
|
||||||
&client, gamedef, tsrc);
|
&client, gamedef, tsrc);
|
||||||
|
menu->doPause = false;
|
||||||
menu->setFormSpec(meta->getString("formspec"),
|
menu->setFormSpec(meta->getString("formspec"),
|
||||||
inventoryloc);
|
inventoryloc);
|
||||||
menu->setFormSource(new NodeMetadataFormSource(
|
menu->setFormSource(new NodeMetadataFormSource(
|
||||||
|
@ -2980,8 +3108,6 @@ void the_game(
|
||||||
fog_range = 100000*BS;
|
fog_range = 100000*BS;
|
||||||
else {
|
else {
|
||||||
fog_range = draw_control.wanted_range*BS + 0.0*MAP_BLOCKSIZE*BS;
|
fog_range = draw_control.wanted_range*BS + 0.0*MAP_BLOCKSIZE*BS;
|
||||||
if(use_weather)
|
|
||||||
fog_range *= (1.5 - 1.4*(float)client.getEnv().getClientMap().getHumidity(pos_i)/100);
|
|
||||||
fog_range = MYMIN(fog_range, (draw_control.farthest_drawn+20)*BS);
|
fog_range = MYMIN(fog_range, (draw_control.farthest_drawn+20)*BS);
|
||||||
fog_range *= 0.9;
|
fog_range *= 0.9;
|
||||||
}
|
}
|
||||||
|
@ -3131,9 +3257,7 @@ 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))
|
||||||
<<") (t="<<client.getEnv().getClientMap().getHeat(pos_i)
|
<<") (seed = "<<((u64)client.getMapSeed())
|
||||||
<<"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);
|
||||||
|
@ -3394,7 +3518,9 @@ void the_game(
|
||||||
/*
|
/*
|
||||||
Wielded tool
|
Wielded tool
|
||||||
*/
|
*/
|
||||||
if(show_hud && (player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE))
|
if(show_hud &&
|
||||||
|
(player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE) &&
|
||||||
|
current_camera_mode < CAMERA_MODE_THIRD)
|
||||||
{
|
{
|
||||||
// Warning: This clears the Z buffer.
|
// Warning: This clears the Z buffer.
|
||||||
camera.drawWieldedTool();
|
camera.drawWieldedTool();
|
||||||
|
|
|
@ -66,12 +66,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
|
GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
|
||||||
gui::IGUIElement* parent, s32 id,
|
gui::IGUIElement* parent, s32 id, IMenuManager *menumgr,
|
||||||
IMenuManager *menumgr,
|
InventoryManager *invmgr, IGameDef *gamedef,
|
||||||
InventoryManager *invmgr,
|
ISimpleTextureSource *tsrc) :
|
||||||
IGameDef *gamedef,
|
|
||||||
ISimpleTextureSource *tsrc
|
|
||||||
):
|
|
||||||
GUIModalMenu(dev->getGUIEnvironment(), parent, id, menumgr),
|
GUIModalMenu(dev->getGUIEnvironment(), parent, id, menumgr),
|
||||||
m_device(dev),
|
m_device(dev),
|
||||||
m_invmgr(invmgr),
|
m_invmgr(invmgr),
|
||||||
|
@ -248,10 +245,11 @@ std::vector<std::string> split(const std::string &s, char delim) {
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseSize(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseSize(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,',');
|
std::vector<std::string> parts = split(element,',');
|
||||||
|
|
||||||
if (parts.size() == 2) {
|
if ((parts.size() == 2) || parts.size() == 3) {
|
||||||
v2f invsize;
|
v2f invsize;
|
||||||
|
|
||||||
if (parts[1].find(';') != std::string::npos)
|
if (parts[1].find(';') != std::string::npos)
|
||||||
|
@ -260,6 +258,13 @@ void GUIFormSpecMenu::parseSize(parserData* data,std::string element) {
|
||||||
invsize.X = stof(parts[0]);
|
invsize.X = stof(parts[0]);
|
||||||
invsize.Y = stof(parts[1]);
|
invsize.Y = stof(parts[1]);
|
||||||
|
|
||||||
|
lockSize(false);
|
||||||
|
if (parts.size() == 3) {
|
||||||
|
if (parts[2] == "true") {
|
||||||
|
lockSize(true,v2u32(800,600));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_lock) {
|
if (m_lock) {
|
||||||
v2u32 current_screensize = m_device->getVideoDriver()->getScreenSize();
|
v2u32 current_screensize = m_device->getVideoDriver()->getScreenSize();
|
||||||
v2u32 delta = current_screensize - m_lockscreensize;
|
v2u32 delta = current_screensize - m_lockscreensize;
|
||||||
|
@ -305,8 +310,8 @@ void GUIFormSpecMenu::parseSize(parserData* data,std::string element) {
|
||||||
errorstream<< "Invalid size element (" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid size element (" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseList(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseList(parserData* data,std::string element)
|
||||||
|
{
|
||||||
if (m_gamedef == 0) {
|
if (m_gamedef == 0) {
|
||||||
errorstream<<"WARNING: invalid use of 'list' with m_gamedef==0"<<std::endl;
|
errorstream<<"WARNING: invalid use of 'list' with m_gamedef==0"<<std::endl;
|
||||||
return;
|
return;
|
||||||
|
@ -358,7 +363,8 @@ void GUIFormSpecMenu::parseList(parserData* data,std::string element) {
|
||||||
errorstream<< "Invalid list element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid list element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if ((parts.size() == 3) || (parts.size() == 4)) {
|
if ((parts.size() == 3) || (parts.size() == 4)) {
|
||||||
|
@ -408,7 +414,8 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element) {
|
||||||
errorstream<< "Invalid checkbox element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid checkbox element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseImage(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseImage(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if (parts.size() == 3) {
|
if (parts.size() == 3) {
|
||||||
|
@ -451,7 +458,8 @@ void GUIFormSpecMenu::parseImage(parserData* data,std::string element) {
|
||||||
errorstream<< "Invalid image element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid image element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseItemImage(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseItemImage(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if (parts.size() == 3) {
|
if (parts.size() == 3) {
|
||||||
|
@ -478,7 +486,9 @@ void GUIFormSpecMenu::parseItemImage(parserData* data,std::string element) {
|
||||||
errorstream<< "Invalid ItemImage element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid ItemImage element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseButton(parserData* data,std::string element,std::string type) {
|
void GUIFormSpecMenu::parseButton(parserData* data,std::string element,
|
||||||
|
std::string type)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if (parts.size() == 4) {
|
if (parts.size() == 4) {
|
||||||
|
@ -530,7 +540,8 @@ void GUIFormSpecMenu::parseButton(parserData* data,std::string element,std::stri
|
||||||
errorstream<< "Invalid button element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid button element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseBackground(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseBackground(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if ((parts.size() == 3) || (parts.size() == 4)) {
|
if ((parts.size() == 3) || (parts.size() == 4)) {
|
||||||
|
@ -565,7 +576,8 @@ void GUIFormSpecMenu::parseBackground(parserData* data,std::string element) {
|
||||||
errorstream<< "Invalid background element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid background element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseTableOptions(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseTableOptions(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
data->table_options.clear();
|
data->table_options.clear();
|
||||||
|
@ -576,7 +588,8 @@ void GUIFormSpecMenu::parseTableOptions(parserData* data,std::string element) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseTableColumns(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseTableColumns(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
data->table_columns.clear();
|
data->table_columns.clear();
|
||||||
|
@ -595,7 +608,8 @@ void GUIFormSpecMenu::parseTableColumns(parserData* data,std::string element) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseTable(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseTable(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if ((parts.size() == 4) || (parts.size() == 5)) {
|
if ((parts.size() == 4) || (parts.size() == 5)) {
|
||||||
|
@ -664,7 +678,8 @@ void GUIFormSpecMenu::parseTable(parserData* data,std::string element) {
|
||||||
errorstream<< "Invalid table element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid table element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseTextList(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseTextList(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if ((parts.size() == 4) || (parts.size() == 5) || (parts.size() == 6)) {
|
if ((parts.size() == 4) || (parts.size() == 5) || (parts.size() == 6)) {
|
||||||
|
@ -737,7 +752,8 @@ void GUIFormSpecMenu::parseTextList(parserData* data,std::string element) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if (parts.size() == 5) {
|
if (parts.size() == 5) {
|
||||||
|
@ -790,7 +806,8 @@ void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element) {
|
||||||
<< element << "'" << std::endl;
|
<< element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if (parts.size() == 4) {
|
if (parts.size() == 4) {
|
||||||
|
@ -856,7 +873,9 @@ void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element) {
|
||||||
errorstream<< "Invalid pwdfield element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid pwdfield element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseSimpleField(parserData* data,std::vector<std::string> &parts) {
|
void GUIFormSpecMenu::parseSimpleField(parserData* data,
|
||||||
|
std::vector<std::string> &parts)
|
||||||
|
{
|
||||||
std::string name = parts[0];
|
std::string name = parts[0];
|
||||||
std::string label = parts[1];
|
std::string label = parts[1];
|
||||||
std::string default_val = parts[2];
|
std::string default_val = parts[2];
|
||||||
|
@ -935,7 +954,9 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data,std::vector<std::string>
|
||||||
m_fields.push_back(spec);
|
m_fields.push_back(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseTextArea(parserData* data,std::vector<std::string>& parts,std::string type) {
|
void GUIFormSpecMenu::parseTextArea(parserData* data,
|
||||||
|
std::vector<std::string>& parts,std::string type)
|
||||||
|
{
|
||||||
|
|
||||||
std::vector<std::string> v_pos = split(parts[0],',');
|
std::vector<std::string> v_pos = split(parts[0],',');
|
||||||
std::vector<std::string> v_geom = split(parts[1],',');
|
std::vector<std::string> v_geom = split(parts[1],',');
|
||||||
|
@ -1026,7 +1047,9 @@ void GUIFormSpecMenu::parseTextArea(parserData* data,std::vector<std::string>& p
|
||||||
m_fields.push_back(spec);
|
m_fields.push_back(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseField(parserData* data,std::string element,std::string type) {
|
void GUIFormSpecMenu::parseField(parserData* data,std::string element,
|
||||||
|
std::string type)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if (parts.size() == 3) {
|
if (parts.size() == 3) {
|
||||||
|
@ -1041,7 +1064,8 @@ void GUIFormSpecMenu::parseField(parserData* data,std::string element,std::strin
|
||||||
errorstream<< "Invalid field element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid field element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseLabel(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseLabel(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if (parts.size() == 2) {
|
if (parts.size() == 2) {
|
||||||
|
@ -1076,7 +1100,8 @@ void GUIFormSpecMenu::parseLabel(parserData* data,std::string element) {
|
||||||
errorstream<< "Invalid label element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid label element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if (parts.size() == 2) {
|
if (parts.size() == 2) {
|
||||||
|
@ -1116,7 +1141,9 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element) {
|
||||||
errorstream<< "Invalid vertlabel element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid vertlabel element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element,std::string type) {
|
void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element,
|
||||||
|
std::string type)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if ((parts.size() == 5) || (parts.size() == 7) || (parts.size() == 8)) {
|
if ((parts.size() == 5) || (parts.size() == 7) || (parts.size() == 8)) {
|
||||||
|
@ -1202,7 +1229,8 @@ void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element,std:
|
||||||
errorstream<< "Invalid imagebutton element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid imagebutton element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if ((parts.size() == 4) || (parts.size() == 6)) {
|
if ((parts.size() == 4) || (parts.size() == 6)) {
|
||||||
|
@ -1269,7 +1297,8 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element) {
|
||||||
errorstream<< "Invalid TabHeader element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid TabHeader element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
|
||||||
|
{
|
||||||
|
|
||||||
if (m_gamedef == 0) {
|
if (m_gamedef == 0) {
|
||||||
errorstream<<"WARNING: invalid use of item_image_button with m_gamedef==0"<<std::endl;
|
errorstream<<"WARNING: invalid use of item_image_button with m_gamedef==0"<<std::endl;
|
||||||
|
@ -1335,7 +1364,8 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
|
||||||
errorstream<< "Invalid ItemImagebutton element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid ItemImagebutton element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseBox(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseBox(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if (parts.size() == 3) {
|
if (parts.size() == 3) {
|
||||||
|
@ -1368,7 +1398,8 @@ void GUIFormSpecMenu::parseBox(parserData* data,std::string element) {
|
||||||
errorstream<< "Invalid Box element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid Box element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseBackgroundColor(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseBackgroundColor(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if ((parts.size() == 1) || (parts.size() == 2)) {
|
if ((parts.size() == 1) || (parts.size() == 2)) {
|
||||||
|
@ -1383,7 +1414,8 @@ void GUIFormSpecMenu::parseBackgroundColor(parserData* data,std::string element)
|
||||||
errorstream<< "Invalid bgcolor element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid bgcolor element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseListColors(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseListColors(parserData* data,std::string element)
|
||||||
|
{
|
||||||
std::vector<std::string> parts = split(element,';');
|
std::vector<std::string> parts = split(element,';');
|
||||||
|
|
||||||
if ((parts.size() == 2) || (parts.size() == 3) || (parts.size() == 5)) {
|
if ((parts.size() == 2) || (parts.size() == 3) || (parts.size() == 5)) {
|
||||||
|
@ -1408,8 +1440,8 @@ void GUIFormSpecMenu::parseListColors(parserData* data,std::string element) {
|
||||||
errorstream<< "Invalid listcolors element(" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid listcolors element(" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseElement(parserData* data,std::string element) {
|
void GUIFormSpecMenu::parseElement(parserData* data,std::string element)
|
||||||
|
{
|
||||||
//some prechecks
|
//some prechecks
|
||||||
if (element == "")
|
if (element == "")
|
||||||
return;
|
return;
|
||||||
|
@ -2132,16 +2164,22 @@ ItemStack GUIFormSpecMenu::verifySelectedItem()
|
||||||
return ItemStack();
|
return ItemStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::acceptInput(bool quit=false)
|
void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode=quit_mode_no)
|
||||||
{
|
{
|
||||||
if(m_text_dst)
|
if(m_text_dst)
|
||||||
{
|
{
|
||||||
std::map<std::string, std::string> fields;
|
std::map<std::string, std::string> fields;
|
||||||
|
|
||||||
if (quit) {
|
if (quitmode == quit_mode_accept) {
|
||||||
fields["quit"] = "true";
|
fields["quit"] = "true";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (quitmode == quit_mode_cancel) {
|
||||||
|
fields["quit"] = "true";
|
||||||
|
m_text_dst->gotText(fields);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (current_keys_pending.key_down) {
|
if (current_keys_pending.key_down) {
|
||||||
fields["key_down"] = "true";
|
fields["key_down"] = "true";
|
||||||
current_keys_pending.key_down = false;
|
current_keys_pending.key_down = false;
|
||||||
|
@ -2281,10 +2319,11 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
|
||||||
if (event.KeyInput.PressedDown && (kp == EscapeKey ||
|
if (event.KeyInput.PressedDown && (kp == EscapeKey ||
|
||||||
kp == getKeySetting("keymap_inventory")))
|
kp == getKeySetting("keymap_inventory")))
|
||||||
{
|
{
|
||||||
if (m_allowclose) {
|
if (m_allowclose){
|
||||||
acceptInput(true);
|
doPause = false;
|
||||||
|
acceptInput(quit_mode_cancel);
|
||||||
quitMenu();
|
quitMenu();
|
||||||
} else {
|
} else {
|
||||||
m_text_dst->gotText(narrow_to_wide("MenuQuit"));
|
m_text_dst->gotText(narrow_to_wide("MenuQuit"));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -2313,7 +2352,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (current_keys_pending.key_enter && m_allowclose) {
|
if (current_keys_pending.key_enter && m_allowclose) {
|
||||||
acceptInput(true);
|
acceptInput(quit_mode_accept);
|
||||||
quitMenu();
|
quitMenu();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2643,7 +2682,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
|
||||||
|
|
||||||
if (btn_id == 257) {
|
if (btn_id == 257) {
|
||||||
if (m_allowclose) {
|
if (m_allowclose) {
|
||||||
acceptInput(true);
|
acceptInput(quit_mode_accept);
|
||||||
quitMenu();
|
quitMenu();
|
||||||
} else {
|
} else {
|
||||||
acceptInput();
|
acceptInput();
|
||||||
|
@ -2663,16 +2702,16 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
|
||||||
(s.fid == event.GUIEvent.Caller->getID()))
|
(s.fid == event.GUIEvent.Caller->getID()))
|
||||||
{
|
{
|
||||||
s.send = true;
|
s.send = true;
|
||||||
acceptInput();
|
|
||||||
if(s.is_exit){
|
if(s.is_exit){
|
||||||
if (m_allowclose) {
|
if (m_allowclose) {
|
||||||
acceptInput(true);
|
acceptInput(quit_mode_accept);
|
||||||
quitMenu();
|
quitMenu();
|
||||||
} else {
|
} else {
|
||||||
m_text_dst->gotText(narrow_to_wide("ExitButton"));
|
m_text_dst->gotText(narrow_to_wide("ExitButton"));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}else{
|
}else{
|
||||||
|
acceptInput();
|
||||||
s.send = false;
|
s.send = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2685,7 +2724,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (m_allowclose) {
|
if (m_allowclose) {
|
||||||
acceptInput(true);
|
acceptInput(quit_mode_accept);
|
||||||
quitMenu();
|
quitMenu();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2723,7 +2762,8 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
|
||||||
return Parent ? Parent->OnEvent(event) : false;
|
return Parent ? Parent->OnEvent(event) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GUIFormSpecMenu::parseColor(const std::string &value, video::SColor &color, bool quiet)
|
bool GUIFormSpecMenu::parseColor(const std::string &value, video::SColor &color,
|
||||||
|
bool quiet)
|
||||||
{
|
{
|
||||||
const char *hexpattern = NULL;
|
const char *hexpattern = NULL;
|
||||||
if (value[0] == '#') {
|
if (value[0] == '#') {
|
||||||
|
|
|
@ -42,12 +42,22 @@ typedef enum {
|
||||||
f_Unknown
|
f_Unknown
|
||||||
} FormspecFieldType;
|
} FormspecFieldType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
quit_mode_no,
|
||||||
|
quit_mode_accept,
|
||||||
|
quit_mode_cancel
|
||||||
|
} FormspecQuitMode;
|
||||||
|
|
||||||
struct TextDest
|
struct TextDest
|
||||||
{
|
{
|
||||||
virtual ~TextDest() {};
|
virtual ~TextDest() {};
|
||||||
// This is deprecated I guess? -celeron55
|
// This is deprecated I guess? -celeron55
|
||||||
virtual void gotText(std::wstring text){}
|
virtual void gotText(std::wstring text){}
|
||||||
virtual void gotText(std::map<std::string, std::string> fields) = 0;
|
virtual void gotText(std::map<std::string, std::string> fields) = 0;
|
||||||
|
virtual void setFormName(std::string formname)
|
||||||
|
{ m_formname = formname;};
|
||||||
|
|
||||||
|
std::string m_formname;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IFormSource
|
class IFormSource
|
||||||
|
@ -139,7 +149,8 @@ class GUIFormSpecMenu : public GUIModalMenu
|
||||||
FieldSpec()
|
FieldSpec()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
FieldSpec(const std::wstring name, const std::wstring label, const std::wstring fdeflt, int id):
|
FieldSpec(const std::wstring &name, const std::wstring &label,
|
||||||
|
const std::wstring &fdeflt, int id) :
|
||||||
fname(name),
|
fname(name),
|
||||||
flabel(label),
|
flabel(label),
|
||||||
fdefault(fdeflt),
|
fdefault(fdeflt),
|
||||||
|
@ -228,9 +239,11 @@ public:
|
||||||
void updateSelectedItem();
|
void updateSelectedItem();
|
||||||
ItemStack verifySelectedItem();
|
ItemStack verifySelectedItem();
|
||||||
|
|
||||||
void acceptInput(bool quit);
|
void acceptInput(FormspecQuitMode quitmode);
|
||||||
bool preprocessEvent(const SEvent& event);
|
bool preprocessEvent(const SEvent& event);
|
||||||
bool OnEvent(const SEvent& event);
|
bool OnEvent(const SEvent& event);
|
||||||
|
bool doPause;
|
||||||
|
bool pausesGame() { return doPause; }
|
||||||
|
|
||||||
GUITable* getTable(std::wstring tablename);
|
GUITable* getTable(std::wstring tablename);
|
||||||
|
|
||||||
|
@ -332,7 +345,8 @@ private:
|
||||||
void parsePwdField(parserData* data,std::string element);
|
void parsePwdField(parserData* data,std::string element);
|
||||||
void parseField(parserData* data,std::string element,std::string type);
|
void parseField(parserData* data,std::string element,std::string type);
|
||||||
void parseSimpleField(parserData* data,std::vector<std::string> &parts);
|
void parseSimpleField(parserData* data,std::vector<std::string> &parts);
|
||||||
void parseTextArea(parserData* data,std::vector<std::string>& parts,std::string type);
|
void parseTextArea(parserData* data,std::vector<std::string>& parts,
|
||||||
|
std::string type);
|
||||||
void parseLabel(parserData* data,std::string element);
|
void parseLabel(parserData* data,std::string element);
|
||||||
void parseVertLabel(parserData* data,std::string element);
|
void parseVertLabel(parserData* data,std::string element);
|
||||||
void parseImageButton(parserData* data,std::string element,std::string type);
|
void parseImageButton(parserData* data,std::string element,std::string type);
|
||||||
|
|
|
@ -1,173 +0,0 @@
|
||||||
/*
|
|
||||||
Minetest
|
|
||||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2.1 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "guiMessageMenu.h"
|
|
||||||
#include "debug.h"
|
|
||||||
#include "serialization.h"
|
|
||||||
#include <string>
|
|
||||||
#include <IGUICheckBox.h>
|
|
||||||
#include <IGUIEditBox.h>
|
|
||||||
#include <IGUIButton.h>
|
|
||||||
#include <IGUIStaticText.h>
|
|
||||||
#include <IGUIFont.h>
|
|
||||||
|
|
||||||
#include "gettext.h"
|
|
||||||
|
|
||||||
GUIMessageMenu::GUIMessageMenu(gui::IGUIEnvironment* env,
|
|
||||||
gui::IGUIElement* parent, s32 id,
|
|
||||||
IMenuManager *menumgr,
|
|
||||||
std::wstring message_text
|
|
||||||
):
|
|
||||||
GUIModalMenu(env, parent, id, menumgr),
|
|
||||||
m_message_text(message_text),
|
|
||||||
m_status(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
GUIMessageMenu::~GUIMessageMenu()
|
|
||||||
{
|
|
||||||
removeChildren();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUIMessageMenu::removeChildren()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
gui::IGUIElement *e = getElementFromId(256);
|
|
||||||
if(e != NULL)
|
|
||||||
e->remove();
|
|
||||||
}
|
|
||||||
{
|
|
||||||
gui::IGUIElement *e = getElementFromId(257);
|
|
||||||
if(e != NULL)
|
|
||||||
e->remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUIMessageMenu::regenerateGui(v2u32 screensize)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Remove stuff
|
|
||||||
*/
|
|
||||||
removeChildren();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Calculate new sizes and positions
|
|
||||||
*/
|
|
||||||
core::rect<s32> rect(
|
|
||||||
screensize.X/2 - 580/2,
|
|
||||||
screensize.Y/2 - 300/2,
|
|
||||||
screensize.X/2 + 580/2,
|
|
||||||
screensize.Y/2 + 300/2
|
|
||||||
);
|
|
||||||
|
|
||||||
DesiredRect = rect;
|
|
||||||
recalculateAbsolutePosition(false);
|
|
||||||
|
|
||||||
v2s32 size = rect.getSize();
|
|
||||||
|
|
||||||
gui::IGUISkin *skin = Environment->getSkin();
|
|
||||||
gui::IGUIFont *font = skin->getFont();
|
|
||||||
s32 msg_h = font->getDimension(m_message_text.c_str()).Height;
|
|
||||||
s32 msg_w = font->getDimension(m_message_text.c_str()).Width;
|
|
||||||
if(msg_h > 200)
|
|
||||||
msg_h = 200;
|
|
||||||
if(msg_w > 540)
|
|
||||||
msg_w = 540;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Add stuff
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
core::rect<s32> rect(0, 0, msg_w, msg_h);
|
|
||||||
rect += v2s32(size.X/2-msg_w/2, size.Y/2-30/2 - msg_h/2);
|
|
||||||
Environment->addStaticText(m_message_text.c_str(),
|
|
||||||
rect, false, true, this, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int bw = 140;
|
|
||||||
{
|
|
||||||
core::rect<s32> rect(0, 0, bw, 30);
|
|
||||||
rect = rect + v2s32(size.X/2-bw/2, size.Y/2-30/2+5 + msg_h/2);
|
|
||||||
wchar_t* text = wgettext("Proceed");
|
|
||||||
gui::IGUIElement *e =
|
|
||||||
Environment->addButton(rect, this, 257,
|
|
||||||
text);
|
|
||||||
Environment->setFocus(e);
|
|
||||||
delete[] text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUIMessageMenu::drawMenu()
|
|
||||||
{
|
|
||||||
gui::IGUISkin* skin = Environment->getSkin();
|
|
||||||
if (!skin)
|
|
||||||
return;
|
|
||||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
|
||||||
|
|
||||||
video::SColor bgcolor(140,0,0,0);
|
|
||||||
driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
|
|
||||||
|
|
||||||
gui::IGUIElement::draw();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GUIMessageMenu::OnEvent(const SEvent& event)
|
|
||||||
{
|
|
||||||
if(event.EventType==EET_KEY_INPUT_EVENT)
|
|
||||||
{
|
|
||||||
if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
|
|
||||||
{
|
|
||||||
m_status = true;
|
|
||||||
quitMenu();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
|
|
||||||
{
|
|
||||||
m_status = true;
|
|
||||||
quitMenu();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(event.EventType==EET_GUI_EVENT)
|
|
||||||
{
|
|
||||||
if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
|
|
||||||
&& isVisible())
|
|
||||||
{
|
|
||||||
if(!canTakeFocus(event.GUIEvent.Element))
|
|
||||||
{
|
|
||||||
dstream<<"GUIMessageMenu: Not allowing focus change."
|
|
||||||
<<std::endl;
|
|
||||||
// Returning true disables focus change
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
|
|
||||||
{
|
|
||||||
switch(event.GUIEvent.Caller->getID())
|
|
||||||
{
|
|
||||||
case 257:
|
|
||||||
m_status = true;
|
|
||||||
quitMenu();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Parent ? Parent->OnEvent(event) : false;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,280 +0,0 @@
|
||||||
/*
|
|
||||||
Minetest
|
|
||||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2.1 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "guiPauseMenu.h"
|
|
||||||
#include "debug.h"
|
|
||||||
#include "serialization.h"
|
|
||||||
#include "porting.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "version.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include <IGUICheckBox.h>
|
|
||||||
#include <IGUIEditBox.h>
|
|
||||||
#include <IGUIButton.h>
|
|
||||||
#include <IGUIStaticText.h>
|
|
||||||
#include <IGUIFont.h>
|
|
||||||
#include "gettext.h"
|
|
||||||
#include "util/string.h"
|
|
||||||
|
|
||||||
GUIPauseMenu::GUIPauseMenu(gui::IGUIEnvironment* env,
|
|
||||||
gui::IGUIElement* parent, s32 id,
|
|
||||||
IGameCallback *gamecallback,
|
|
||||||
IMenuManager *menumgr,
|
|
||||||
bool simple_singleplayer_mode):
|
|
||||||
GUIModalMenu(env, parent, id, menumgr),
|
|
||||||
m_gamecallback(gamecallback),
|
|
||||||
m_simple_singleplayer_mode(simple_singleplayer_mode)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
GUIPauseMenu::~GUIPauseMenu()
|
|
||||||
{
|
|
||||||
removeChildren();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUIPauseMenu::removeChildren()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
gui::IGUIElement *e = getElementFromId(256);
|
|
||||||
if(e != NULL)
|
|
||||||
e->remove();
|
|
||||||
}
|
|
||||||
{
|
|
||||||
gui::IGUIElement *e = getElementFromId(257);
|
|
||||||
if(e != NULL)
|
|
||||||
e->remove();
|
|
||||||
}
|
|
||||||
{
|
|
||||||
gui::IGUIElement *e = getElementFromId(258);
|
|
||||||
if(e != NULL)
|
|
||||||
e->remove();
|
|
||||||
}
|
|
||||||
{
|
|
||||||
gui::IGUIElement *e = getElementFromId(259);
|
|
||||||
if(e != NULL)
|
|
||||||
e->remove();
|
|
||||||
}
|
|
||||||
{
|
|
||||||
gui::IGUIElement *e = getElementFromId(260);
|
|
||||||
if(e != NULL)
|
|
||||||
e->remove();
|
|
||||||
}
|
|
||||||
{
|
|
||||||
gui::IGUIElement *e = getElementFromId(261);
|
|
||||||
if(e != NULL)
|
|
||||||
e->remove();
|
|
||||||
}
|
|
||||||
{
|
|
||||||
gui::IGUIElement *e = getElementFromId(262);
|
|
||||||
if(e != NULL)
|
|
||||||
e->remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUIPauseMenu::regenerateGui(v2u32 screensize)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Remove stuff
|
|
||||||
*/
|
|
||||||
removeChildren();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Calculate new sizes and positions
|
|
||||||
*/
|
|
||||||
core::rect<s32> rect(
|
|
||||||
screensize.X/2 - 580/2,
|
|
||||||
screensize.Y/2 - 300/2,
|
|
||||||
screensize.X/2 + 580/2,
|
|
||||||
screensize.Y/2 + 300/2
|
|
||||||
);
|
|
||||||
|
|
||||||
DesiredRect = rect;
|
|
||||||
recalculateAbsolutePosition(false);
|
|
||||||
|
|
||||||
v2s32 size = rect.getSize();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Add stuff
|
|
||||||
*/
|
|
||||||
const s32 btn_height = 30;
|
|
||||||
const s32 btn_gap = 20;
|
|
||||||
const s32 btn_num = m_simple_singleplayer_mode ? 4 : 5;
|
|
||||||
s32 btn_y = size.Y/2-((btn_num*btn_height+(btn_num-1)*btn_gap))/2;
|
|
||||||
{
|
|
||||||
core::rect<s32> rect(0, 0, 140, btn_height);
|
|
||||||
rect = rect + v2s32(size.X/2-140/2, btn_y);
|
|
||||||
wchar_t* text = wgettext("Continue");
|
|
||||||
Environment->addButton(rect, this, 256,
|
|
||||||
text);
|
|
||||||
delete[] text;
|
|
||||||
}
|
|
||||||
btn_y += btn_height + btn_gap;
|
|
||||||
if(!m_simple_singleplayer_mode)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
core::rect<s32> rect(0, 0, 140, btn_height);
|
|
||||||
rect = rect + v2s32(size.X/2-140/2, btn_y);
|
|
||||||
wchar_t* text = wgettext("Change Password");
|
|
||||||
Environment->addButton(rect, this, 261,
|
|
||||||
text);
|
|
||||||
delete[] text;
|
|
||||||
}
|
|
||||||
btn_y += btn_height + btn_gap;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
core::rect<s32> rect(0, 0, 140, btn_height);
|
|
||||||
rect = rect + v2s32(size.X/2-140/2, btn_y);
|
|
||||||
wchar_t* text = wgettext("Sound Volume");
|
|
||||||
Environment->addButton(rect, this, 262,
|
|
||||||
text);
|
|
||||||
delete[] text;
|
|
||||||
}
|
|
||||||
btn_y += btn_height + btn_gap;
|
|
||||||
{
|
|
||||||
core::rect<s32> rect(0, 0, 140, btn_height);
|
|
||||||
rect = rect + v2s32(size.X/2-140/2, btn_y);
|
|
||||||
wchar_t* text = wgettext("Exit to Menu");
|
|
||||||
Environment->addButton(rect, this, 260,
|
|
||||||
text);
|
|
||||||
delete[] text;
|
|
||||||
}
|
|
||||||
btn_y += btn_height + btn_gap;
|
|
||||||
{
|
|
||||||
core::rect<s32> rect(0, 0, 140, btn_height);
|
|
||||||
rect = rect + v2s32(size.X/2-140/2, btn_y);
|
|
||||||
wchar_t* text = wgettext("Exit to OS");
|
|
||||||
Environment->addButton(rect, this, 257,
|
|
||||||
text);
|
|
||||||
delete[] text;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
core::rect<s32> rect(0, 0, 180, 240);
|
|
||||||
rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2);
|
|
||||||
wchar_t* text = wgettext("Default Controls:\n"
|
|
||||||
"- WASD: move\n"
|
|
||||||
"- Space: jump/climb\n"
|
|
||||||
"- Shift: sneak/go down\n"
|
|
||||||
"- Q: drop item\n"
|
|
||||||
"- I: inventory\n"
|
|
||||||
"- Mouse: turn/look\n"
|
|
||||||
"- Mouse left: dig/punch\n"
|
|
||||||
"- Mouse right: place/use\n"
|
|
||||||
"- Mouse wheel: select item\n"
|
|
||||||
"- T: chat\n"
|
|
||||||
);
|
|
||||||
Environment->addStaticText(text, rect, false, true, this, 258);
|
|
||||||
delete[] text;
|
|
||||||
|
|
||||||
}
|
|
||||||
{
|
|
||||||
core::rect<s32> rect(0, 0, 180, 220);
|
|
||||||
rect = rect + v2s32(size.X/2 - 90 - rect.getWidth(), size.Y/2-rect.getHeight()/2);
|
|
||||||
|
|
||||||
v2u32 max_texture_size;
|
|
||||||
{
|
|
||||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
|
||||||
max_texture_size = driver->getMaxTextureSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostringstream os;
|
|
||||||
os<<"Minetest\n";
|
|
||||||
os<<minetest_build_info<<"\n";
|
|
||||||
os<<"path_user = "<<wrap_rows(porting::path_user, 20)<<"\n";
|
|
||||||
|
|
||||||
Environment->addStaticText(narrow_to_wide(os.str()).c_str(), rect, false, true, this, 259);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUIPauseMenu::drawMenu()
|
|
||||||
{
|
|
||||||
gui::IGUISkin* skin = Environment->getSkin();
|
|
||||||
if (!skin)
|
|
||||||
return;
|
|
||||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
|
||||||
|
|
||||||
video::SColor bgcolor(140,0,0,0);
|
|
||||||
driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
|
|
||||||
|
|
||||||
gui::IGUIElement::draw();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GUIPauseMenu::OnEvent(const SEvent& event)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(event.EventType==EET_KEY_INPUT_EVENT)
|
|
||||||
{
|
|
||||||
if(event.KeyInput.PressedDown)
|
|
||||||
{
|
|
||||||
if(event.KeyInput.Key==KEY_ESCAPE)
|
|
||||||
{
|
|
||||||
quitMenu();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if(event.KeyInput.Key==KEY_RETURN)
|
|
||||||
{
|
|
||||||
quitMenu();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(event.EventType==EET_GUI_EVENT)
|
|
||||||
{
|
|
||||||
if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
|
|
||||||
&& isVisible())
|
|
||||||
{
|
|
||||||
if(!canTakeFocus(event.GUIEvent.Element))
|
|
||||||
{
|
|
||||||
dstream<<"GUIPauseMenu: Not allowing focus change."
|
|
||||||
<<std::endl;
|
|
||||||
// Returning true disables focus change
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
|
|
||||||
{
|
|
||||||
switch(event.GUIEvent.Caller->getID())
|
|
||||||
{
|
|
||||||
case 256: // continue
|
|
||||||
quitMenu();
|
|
||||||
// ALWAYS return immediately after quitMenu()
|
|
||||||
return true;
|
|
||||||
case 261:
|
|
||||||
m_gamecallback->changePassword();
|
|
||||||
quitMenu();
|
|
||||||
return true;
|
|
||||||
case 262:
|
|
||||||
m_gamecallback->changeVolume();
|
|
||||||
quitMenu();
|
|
||||||
return true;
|
|
||||||
case 260: // disconnect
|
|
||||||
m_gamecallback->disconnect();
|
|
||||||
quitMenu();
|
|
||||||
return true;
|
|
||||||
case 257: // exit
|
|
||||||
m_gamecallback->exitToOS();
|
|
||||||
quitMenu();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Parent ? Parent->OnEvent(event) : false;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
Minetest
|
|
||||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2.1 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GUIPAUSEMENU_HEADER
|
|
||||||
#define GUIPAUSEMENU_HEADER
|
|
||||||
|
|
||||||
#include "irrlichttypes_extrabloated.h"
|
|
||||||
#include "modalMenu.h"
|
|
||||||
|
|
||||||
class IGameCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual void exitToOS() = 0;
|
|
||||||
virtual void disconnect() = 0;
|
|
||||||
virtual void changePassword() = 0;
|
|
||||||
virtual void changeVolume() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class GUIPauseMenu : public GUIModalMenu
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GUIPauseMenu(gui::IGUIEnvironment* env,
|
|
||||||
gui::IGUIElement* parent, s32 id,
|
|
||||||
IGameCallback *gamecallback,
|
|
||||||
IMenuManager *menumgr,
|
|
||||||
bool simple_singleplayer_mode);
|
|
||||||
~GUIPauseMenu();
|
|
||||||
|
|
||||||
void removeChildren();
|
|
||||||
/*
|
|
||||||
Remove and re-add (or reposition) stuff
|
|
||||||
*/
|
|
||||||
void regenerateGui(v2u32 screensize);
|
|
||||||
|
|
||||||
void drawMenu();
|
|
||||||
|
|
||||||
bool OnEvent(const SEvent& event);
|
|
||||||
|
|
||||||
bool pausesGame(){ return true; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
IGameCallback *m_gamecallback;
|
|
||||||
bool m_simple_singleplayer_mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -41,8 +41,7 @@ GUIVolumeChange::GUIVolumeChange(gui::IGUIEnvironment* env,
|
||||||
IMenuManager *menumgr,
|
IMenuManager *menumgr,
|
||||||
Client* client
|
Client* client
|
||||||
):
|
):
|
||||||
GUIModalMenu(env, parent, id, menumgr),
|
GUIModalMenu(env, parent, id, menumgr)
|
||||||
m_client(client)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,11 +44,7 @@ public:
|
||||||
|
|
||||||
bool OnEvent(const SEvent& event);
|
bool OnEvent(const SEvent& event);
|
||||||
|
|
||||||
bool pausesGame(){ return true; }
|
bool pausesGame() { return true; }
|
||||||
|
|
||||||
private:
|
|
||||||
Client* m_client;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -566,6 +566,8 @@ protected:
|
||||||
log_register_thread("CurlFetchThread");
|
log_register_thread("CurlFetchThread");
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
|
porting::setThreadName("CurlFetchThread");
|
||||||
|
|
||||||
CurlHandlePool pool;
|
CurlHandlePool pool;
|
||||||
|
|
||||||
m_multi = curl_multi_init();
|
m_multi = curl_multi_init();
|
||||||
|
|
|
@ -143,7 +143,7 @@ void Hud::drawItem(v2s32 upperleftpos, s32 imgsize, s32 itemcount,
|
||||||
steppos = v2s32(padding, -(padding + i * fullimglen));
|
steppos = v2s32(padding, -(padding + i * fullimglen));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
steppos = v2s32(padding + i * fullimglen, padding);
|
steppos = v2s32(padding + i * fullimglen, padding);
|
||||||
}
|
}
|
||||||
|
|
||||||
core::rect<s32> rect = imgrect + pos + steppos;
|
core::rect<s32> rect = imgrect + pos + steppos;
|
||||||
|
@ -334,7 +334,7 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s
|
||||||
steppos = v2s32(0, -1);
|
steppos = v2s32(0, -1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
steppos = v2s32(1, 0);
|
steppos = v2s32(1, 0);
|
||||||
}
|
}
|
||||||
steppos.X *= srcd.Width;
|
steppos.X *= srcd.Width;
|
||||||
steppos.Y *= srcd.Height;
|
steppos.Y *= srcd.Height;
|
||||||
|
@ -363,7 +363,7 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s
|
||||||
void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem, s32 breath) {
|
void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem, s32 breath) {
|
||||||
InventoryList *mainlist = inventory->getList("main");
|
InventoryList *mainlist = inventory->getList("main");
|
||||||
if (mainlist == NULL) {
|
if (mainlist == NULL) {
|
||||||
errorstream << "draw_hotbar(): mainlist == NULL" << std::endl;
|
//silently ignore this we may not be initialized completely
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,7 +384,8 @@ void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem, s
|
||||||
|
|
||||||
|
|
||||||
void Hud::drawCrosshair() {
|
void Hud::drawCrosshair() {
|
||||||
if (!(player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE))
|
if (!(player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) ||
|
||||||
|
player->camera_mode == CAMERA_MODE_THIRD_FRONT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (use_crosshair_image) {
|
if (use_crosshair_image) {
|
||||||
|
|
|
@ -43,6 +43,10 @@ LocalPlayer::LocalPlayer(IGameDef *gamedef):
|
||||||
last_pitch(0),
|
last_pitch(0),
|
||||||
last_yaw(0),
|
last_yaw(0),
|
||||||
last_keyPressed(0),
|
last_keyPressed(0),
|
||||||
|
camera_mode(0),
|
||||||
|
eye_offset_first(v3f(0,0,0)),
|
||||||
|
eye_offset_third(v3f(0,0,0)),
|
||||||
|
last_animation(NO_ANIM),
|
||||||
hotbar_image(""),
|
hotbar_image(""),
|
||||||
hotbar_selected_image(""),
|
hotbar_selected_image(""),
|
||||||
m_sneak_node(32767,32767,32767),
|
m_sneak_node(32767,32767,32767),
|
||||||
|
@ -61,7 +65,7 @@ LocalPlayer::~LocalPlayer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d,
|
void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
||||||
std::list<CollisionInfo> *collision_info)
|
std::list<CollisionInfo> *collision_info)
|
||||||
{
|
{
|
||||||
Map *map = &env->getMap();
|
Map *map = &env->getMap();
|
||||||
|
@ -356,7 +360,7 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d,
|
||||||
m_can_jump = false;
|
m_can_jump = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d)
|
void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d)
|
||||||
{
|
{
|
||||||
move(dtime, env, pos_max_d, NULL);
|
move(dtime, env, pos_max_d, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
class ClientEnvironment;
|
class Environment;
|
||||||
|
|
||||||
class ClientActiveObject;
|
class ClientActiveObject;
|
||||||
|
|
||||||
|
enum LocalPlayerAnimations {NO_ANIM, WALK_ANIM, DIG_ANIM, WD_ANIM}; // no local animation, walking, digging, both
|
||||||
|
|
||||||
class LocalPlayer : public Player
|
class LocalPlayer : public Player
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -44,9 +46,9 @@ public:
|
||||||
|
|
||||||
v3f overridePosition;
|
v3f overridePosition;
|
||||||
|
|
||||||
void move(f32 dtime, ClientEnvironment *env, f32 pos_max_d,
|
void move(f32 dtime, Environment *env, f32 pos_max_d);
|
||||||
|
void move(f32 dtime, Environment *env, f32 pos_max_d,
|
||||||
std::list<CollisionInfo> *collision_info);
|
std::list<CollisionInfo> *collision_info);
|
||||||
void move(f32 dtime, ClientEnvironment *env, f32 pos_max_d);
|
|
||||||
|
|
||||||
void applyControl(float dtime);
|
void applyControl(float dtime);
|
||||||
|
|
||||||
|
@ -60,6 +62,12 @@ public:
|
||||||
unsigned int last_keyPressed;
|
unsigned int last_keyPressed;
|
||||||
|
|
||||||
float camera_impact;
|
float camera_impact;
|
||||||
|
int camera_mode;
|
||||||
|
v3f eye_offset_first;
|
||||||
|
v3f eye_offset_third;
|
||||||
|
|
||||||
|
int last_animation;
|
||||||
|
float last_animation_speed;
|
||||||
|
|
||||||
std::string hotbar_image;
|
std::string hotbar_image;
|
||||||
std::string hotbar_selected_image;
|
std::string hotbar_selected_image;
|
||||||
|
|
49
src/main.cpp
49
src/main.cpp
|
@ -55,7 +55,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "gettime.h"
|
#include "gettime.h"
|
||||||
#include "guiMessageMenu.h"
|
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
@ -85,6 +84,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#ifdef USE_LEVELDB
|
#ifdef USE_LEVELDB
|
||||||
#include "database-leveldb.h"
|
#include "database-leveldb.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if USE_REDIS
|
||||||
|
#include "database-redis.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Settings.
|
Settings.
|
||||||
|
@ -361,7 +363,6 @@ public:
|
||||||
s32 mouse_wheel;
|
s32 mouse_wheel;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IrrlichtDevice *m_device;
|
|
||||||
|
|
||||||
// The current state of keys
|
// The current state of keys
|
||||||
KeyList keyIsDown;
|
KeyList keyIsDown;
|
||||||
|
@ -1024,21 +1025,6 @@ int main(int argc, char *argv[])
|
||||||
if(port == 0)
|
if(port == 0)
|
||||||
port = 30000;
|
port = 30000;
|
||||||
|
|
||||||
// Bind address
|
|
||||||
std::string bind_str = g_settings->get("bind_address");
|
|
||||||
Address bind_addr(0,0,0,0, port);
|
|
||||||
try {
|
|
||||||
bind_addr.Resolve(bind_str.c_str());
|
|
||||||
} catch (ResolveError &e) {
|
|
||||||
infostream << "Resolving bind address \"" << bind_str
|
|
||||||
<< "\" failed: " << e.what()
|
|
||||||
<< " -- Listening on all addresses." << std::endl;
|
|
||||||
|
|
||||||
if (g_settings->getBool("ipv6_server")) {
|
|
||||||
bind_addr.setAddress((IPv6AddressBytes*) NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// World directory
|
// World directory
|
||||||
std::string commanded_world = "";
|
std::string commanded_world = "";
|
||||||
if(cmd_args.exists("world"))
|
if(cmd_args.exists("world"))
|
||||||
|
@ -1224,8 +1210,29 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
verbosestream<<_("Using gameid")<<" ["<<gamespec.id<<"]"<<std::endl;
|
verbosestream<<_("Using gameid")<<" ["<<gamespec.id<<"]"<<std::endl;
|
||||||
|
|
||||||
|
// Bind address
|
||||||
|
std::string bind_str = g_settings->get("bind_address");
|
||||||
|
Address bind_addr(0,0,0,0, port);
|
||||||
|
|
||||||
|
if (g_settings->getBool("ipv6_server")) {
|
||||||
|
bind_addr.setAddress((IPv6AddressBytes*) NULL);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
bind_addr.Resolve(bind_str.c_str());
|
||||||
|
} catch (ResolveError &e) {
|
||||||
|
infostream << "Resolving bind address \"" << bind_str
|
||||||
|
<< "\" failed: " << e.what()
|
||||||
|
<< " -- Listening on all addresses." << std::endl;
|
||||||
|
}
|
||||||
|
if(bind_addr.isIPv6() && !g_settings->getBool("enable_ipv6")) {
|
||||||
|
errorstream << "Unable to listen on "
|
||||||
|
<< bind_addr.serializeString()
|
||||||
|
<< L" because IPv6 is disabled" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Create server
|
// Create server
|
||||||
Server server(world_path, gamespec, false);
|
Server server(world_path, gamespec, false, bind_addr.isIPv6());
|
||||||
|
|
||||||
// Database migration
|
// Database migration
|
||||||
if (cmd_args.exists("migrate")) {
|
if (cmd_args.exists("migrate")) {
|
||||||
|
@ -1238,7 +1245,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
if (!world_mt.exists("backend")) {
|
if (!world_mt.exists("backend")) {
|
||||||
errorstream << "Please specify your current backend in world.mt file:"
|
errorstream << "Please specify your current backend in world.mt file:"
|
||||||
<< std::endl << " backend = {sqlite3|leveldb|dummy}" << std::endl;
|
<< std::endl << " backend = {sqlite3|leveldb|redis|dummy}" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
std::string backend = world_mt.get("backend");
|
std::string backend = world_mt.get("backend");
|
||||||
|
@ -1253,6 +1260,10 @@ int main(int argc, char *argv[])
|
||||||
else if (migrate_to == "leveldb")
|
else if (migrate_to == "leveldb")
|
||||||
new_db = new Database_LevelDB(&(ServerMap&)server.getMap(), world_path);
|
new_db = new Database_LevelDB(&(ServerMap&)server.getMap(), world_path);
|
||||||
#endif
|
#endif
|
||||||
|
#if USE_REDIS
|
||||||
|
else if (migrate_to == "redis")
|
||||||
|
new_db = new Database_Redis(&(ServerMap&)server.getMap(), world_path);
|
||||||
|
#endif
|
||||||
else {
|
else {
|
||||||
errorstream << "Migration to " << migrate_to << " is not supported" << std::endl;
|
errorstream << "Migration to " << migrate_to << " is not supported" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -25,9 +25,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
*/
|
*/
|
||||||
#include "debug.h" // assert
|
#include "debug.h" // assert
|
||||||
#include "modalMenu.h"
|
#include "modalMenu.h"
|
||||||
#include "guiPauseMenu.h" //For IGameCallback
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
class IGameCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void exitToOS() = 0;
|
||||||
|
virtual void disconnect() = 0;
|
||||||
|
virtual void changePassword() = 0;
|
||||||
|
virtual void changeVolume() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
extern gui::IGUIEnvironment* guienv;
|
extern gui::IGUIEnvironment* guienv;
|
||||||
extern gui::IGUIStaticText *guiroot;
|
extern gui::IGUIStaticText *guiroot;
|
||||||
|
|
||||||
|
|
487
src/map.cpp
487
src/map.cpp
|
@ -46,6 +46,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#if USE_LEVELDB
|
#if USE_LEVELDB
|
||||||
#include "database-leveldb.h"
|
#include "database-leveldb.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if USE_REDIS
|
||||||
|
#include "database-redis.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||||
|
|
||||||
|
@ -1097,7 +1100,6 @@ 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
|
||||||
|
@ -1289,7 +1291,6 @@ 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
|
||||||
|
@ -1616,7 +1617,6 @@ struct NodeNeighbor {
|
||||||
NeighborType t;
|
NeighborType t;
|
||||||
v3s16 p;
|
v3s16 p;
|
||||||
bool l; //can liquid
|
bool l; //can liquid
|
||||||
bool i; //infinity
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void Map::transforming_liquid_add(v3s16 p) {
|
void Map::transforming_liquid_add(v3s16 p) {
|
||||||
|
@ -1627,383 +1627,8 @@ s32 Map::transforming_liquid_size() {
|
||||||
return m_transforming_liquid.size();
|
return m_transforming_liquid.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const v3s16 g_7dirs[7] =
|
|
||||||
{
|
|
||||||
// +right, +top, +back
|
|
||||||
v3s16( 0,-1, 0), // bottom
|
|
||||||
v3s16( 0, 0, 0), // self
|
|
||||||
v3s16( 0, 0, 1), // back
|
|
||||||
v3s16( 0, 0,-1), // front
|
|
||||||
v3s16( 1, 0, 0), // right
|
|
||||||
v3s16(-1, 0, 0), // left
|
|
||||||
v3s16( 0, 1, 0) // top
|
|
||||||
};
|
|
||||||
|
|
||||||
#define D_BOTTOM 0
|
|
||||||
#define D_TOP 6
|
|
||||||
#define D_SELF 1
|
|
||||||
|
|
||||||
void Map::transformLiquidsFinite(std::map<v3s16, MapBlock*> & modified_blocks)
|
|
||||||
{
|
|
||||||
INodeDefManager *nodemgr = m_gamedef->ndef();
|
|
||||||
|
|
||||||
DSTACK(__FUNCTION_NAME);
|
|
||||||
//TimeTaker timer("transformLiquids()");
|
|
||||||
|
|
||||||
u32 loopcount = 0;
|
|
||||||
u32 initial_size = m_transforming_liquid.size();
|
|
||||||
|
|
||||||
u8 relax = g_settings->getS16("liquid_relax");
|
|
||||||
bool fast_flood = g_settings->getS16("liquid_fast_flood");
|
|
||||||
int water_level = g_settings->getS16("water_level");
|
|
||||||
|
|
||||||
// list of nodes that due to viscosity have not reached their max level height
|
|
||||||
UniqueQueue<v3s16> must_reflow, must_reflow_second;
|
|
||||||
|
|
||||||
// List of MapBlocks that will require a lighting update (due to lava)
|
|
||||||
std::map<v3s16, MapBlock*> lighting_modified_blocks;
|
|
||||||
|
|
||||||
u16 loop_max = g_settings->getU16("liquid_loop_max");
|
|
||||||
|
|
||||||
//if (m_transforming_liquid.size() > 0) errorstream << "Liquid queue size="<<m_transforming_liquid.size()<<std::endl;
|
|
||||||
|
|
||||||
while (m_transforming_liquid.size() > 0)
|
|
||||||
{
|
|
||||||
// This should be done here so that it is done when continue is used
|
|
||||||
if (loopcount >= initial_size || loopcount >= loop_max)
|
|
||||||
break;
|
|
||||||
loopcount++;
|
|
||||||
/*
|
|
||||||
Get a queued transforming liquid node
|
|
||||||
*/
|
|
||||||
v3s16 p0 = m_transforming_liquid.pop_front();
|
|
||||||
u16 total_level = 0;
|
|
||||||
// surrounding flowing liquid nodes
|
|
||||||
NodeNeighbor neighbors[7];
|
|
||||||
// current level of every block
|
|
||||||
s8 liquid_levels[7] = {-1, -1, -1, -1, -1, -1, -1};
|
|
||||||
// target levels
|
|
||||||
s8 liquid_levels_want[7] = {-1, -1, -1, -1, -1, -1, -1};
|
|
||||||
s8 can_liquid_same_level = 0;
|
|
||||||
content_t liquid_kind = CONTENT_IGNORE;
|
|
||||||
content_t liquid_kind_flowing = CONTENT_IGNORE;
|
|
||||||
/*
|
|
||||||
Collect information about the environment
|
|
||||||
*/
|
|
||||||
const v3s16 *dirs = g_7dirs;
|
|
||||||
for (u16 i = 0; i < 7; i++) {
|
|
||||||
NeighborType nt = NEIGHBOR_SAME_LEVEL;
|
|
||||||
switch (i) {
|
|
||||||
case D_TOP:
|
|
||||||
nt = NEIGHBOR_UPPER;
|
|
||||||
break;
|
|
||||||
case D_BOTTOM:
|
|
||||||
nt = NEIGHBOR_LOWER;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
v3s16 npos = p0 + dirs[i];
|
|
||||||
|
|
||||||
neighbors[i].n = getNodeNoEx(npos);
|
|
||||||
neighbors[i].t = nt;
|
|
||||||
neighbors[i].p = npos;
|
|
||||||
neighbors[i].l = 0;
|
|
||||||
neighbors[i].i = 0;
|
|
||||||
NodeNeighbor & nb = neighbors[i];
|
|
||||||
|
|
||||||
switch (nodemgr->get(nb.n.getContent()).liquid_type) {
|
|
||||||
case LIQUID_NONE:
|
|
||||||
if (nb.n.getContent() == CONTENT_AIR) {
|
|
||||||
liquid_levels[i] = 0;
|
|
||||||
nb.l = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LIQUID_SOURCE:
|
|
||||||
// if this node is not (yet) of a liquid type,
|
|
||||||
// choose the first liquid type we encounter
|
|
||||||
if (liquid_kind_flowing == CONTENT_IGNORE)
|
|
||||||
liquid_kind_flowing = nodemgr->getId(
|
|
||||||
nodemgr->get(nb.n).liquid_alternative_flowing);
|
|
||||||
if (liquid_kind == CONTENT_IGNORE)
|
|
||||||
liquid_kind = nb.n.getContent();
|
|
||||||
if (nb.n.getContent() == liquid_kind) {
|
|
||||||
liquid_levels[i] = nb.n.getLevel(nodemgr); //LIQUID_LEVEL_SOURCE;
|
|
||||||
nb.l = 1;
|
|
||||||
nb.i = (nb.n.param2 & LIQUID_INFINITY_MASK);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LIQUID_FLOWING:
|
|
||||||
// if this node is not (yet) of a liquid type,
|
|
||||||
// choose the first liquid type we encounter
|
|
||||||
if (liquid_kind_flowing == CONTENT_IGNORE)
|
|
||||||
liquid_kind_flowing = nb.n.getContent();
|
|
||||||
if (liquid_kind == CONTENT_IGNORE)
|
|
||||||
liquid_kind = nodemgr->getId(
|
|
||||||
nodemgr->get(nb.n).liquid_alternative_source);
|
|
||||||
if (nb.n.getContent() == liquid_kind_flowing) {
|
|
||||||
liquid_levels[i] = nb.n.getLevel(nodemgr); //(nb.n.param2 & LIQUID_LEVEL_MASK);
|
|
||||||
nb.l = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nb.l && nb.t == NEIGHBOR_SAME_LEVEL)
|
|
||||||
++can_liquid_same_level;
|
|
||||||
if (liquid_levels[i] > 0)
|
|
||||||
total_level += liquid_levels[i];
|
|
||||||
|
|
||||||
/*
|
|
||||||
infostream << "get node i=" <<(int)i<<" " << PP(npos) << " c="
|
|
||||||
<< nb.n.getContent() <<" p0="<< (int)nb.n.param0 <<" p1="
|
|
||||||
<< (int)nb.n.param1 <<" p2="<< (int)nb.n.param2 << " lt="
|
|
||||||
<< nodemgr->get(nb.n.getContent()).liquid_type
|
|
||||||
//<< " lk=" << liquid_kind << " lkf=" << liquid_kind_flowing
|
|
||||||
<< " l="<< nb.l << " inf="<< nb.i << " nlevel=" << (int)liquid_levels[i]
|
|
||||||
<< " tlevel=" << (int)total_level << " cansame="
|
|
||||||
<< (int)can_liquid_same_level << std::endl;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
if (liquid_kind == CONTENT_IGNORE ||
|
|
||||||
!neighbors[D_SELF].l ||
|
|
||||||
total_level <= 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// fill bottom block
|
|
||||||
if (neighbors[D_BOTTOM].l) {
|
|
||||||
liquid_levels_want[D_BOTTOM] = total_level > LIQUID_LEVEL_SOURCE ?
|
|
||||||
LIQUID_LEVEL_SOURCE : total_level;
|
|
||||||
total_level -= liquid_levels_want[D_BOTTOM];
|
|
||||||
}
|
|
||||||
|
|
||||||
//relax up
|
|
||||||
if (relax && ((p0.Y == water_level) || (fast_flood && p0.Y <= water_level)) && liquid_levels[D_TOP] == 0 &&
|
|
||||||
liquid_levels[D_BOTTOM] == LIQUID_LEVEL_SOURCE &&
|
|
||||||
total_level >= LIQUID_LEVEL_SOURCE * can_liquid_same_level-
|
|
||||||
(can_liquid_same_level - relax) &&
|
|
||||||
can_liquid_same_level >= relax + 1) {
|
|
||||||
total_level = LIQUID_LEVEL_SOURCE * can_liquid_same_level;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prevent lakes in air above unloaded blocks
|
|
||||||
if (liquid_levels[D_TOP] == 0 && (p0.Y > water_level) && neighbors[D_BOTTOM].n.getContent() == CONTENT_IGNORE && !(loopcount % 3)) {
|
|
||||||
--total_level;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate self level 5 blocks
|
|
||||||
u8 want_level =
|
|
||||||
total_level >= LIQUID_LEVEL_SOURCE * can_liquid_same_level
|
|
||||||
? LIQUID_LEVEL_SOURCE
|
|
||||||
: total_level / can_liquid_same_level;
|
|
||||||
total_level -= want_level * can_liquid_same_level;
|
|
||||||
|
|
||||||
//relax down
|
|
||||||
if (relax && p0.Y == water_level + 1 && liquid_levels[D_TOP] == 0 &&
|
|
||||||
liquid_levels[D_BOTTOM] == LIQUID_LEVEL_SOURCE && want_level == 0 &&
|
|
||||||
total_level <= (can_liquid_same_level - relax) &&
|
|
||||||
can_liquid_same_level >= relax + 1) {
|
|
||||||
total_level = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u16 ii = D_SELF; ii < D_TOP; ++ii) { // fill only same level
|
|
||||||
if (!neighbors[ii].l)
|
|
||||||
continue;
|
|
||||||
liquid_levels_want[ii] = want_level;
|
|
||||||
if (liquid_levels_want[ii] < LIQUID_LEVEL_SOURCE && total_level > 0) {
|
|
||||||
if (loopcount % 3 || liquid_levels[ii] <= 0){
|
|
||||||
if (liquid_levels[ii] > liquid_levels_want[ii]) {
|
|
||||||
++liquid_levels_want[ii];
|
|
||||||
--total_level;
|
|
||||||
}
|
|
||||||
} else if (neighbors[ii].l > 0){
|
|
||||||
++liquid_levels_want[ii];
|
|
||||||
--total_level;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u16 ii = 0; ii < 7; ++ii) {
|
|
||||||
if (total_level < 1) break;
|
|
||||||
if (liquid_levels_want[ii] >= 0 &&
|
|
||||||
liquid_levels_want[ii] < LIQUID_LEVEL_SOURCE) {
|
|
||||||
++liquid_levels_want[ii];
|
|
||||||
--total_level;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill top block if can
|
|
||||||
if (neighbors[D_TOP].l) {
|
|
||||||
liquid_levels_want[D_TOP] = total_level > LIQUID_LEVEL_SOURCE ?
|
|
||||||
LIQUID_LEVEL_SOURCE : total_level;
|
|
||||||
total_level -= liquid_levels_want[D_TOP];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u16 ii = 0; ii < 7; ii++) // infinity and cave flood optimization
|
|
||||||
if ( neighbors[ii].i ||
|
|
||||||
(liquid_levels_want[ii] >= 0 &&
|
|
||||||
(fast_flood && p0.Y < water_level &&
|
|
||||||
(initial_size >= 1000
|
|
||||||
&& ii != D_TOP
|
|
||||||
&& want_level >= LIQUID_LEVEL_SOURCE/4
|
|
||||||
&& can_liquid_same_level >= 5
|
|
||||||
&& liquid_levels[D_TOP] >= LIQUID_LEVEL_SOURCE))))
|
|
||||||
liquid_levels_want[ii] = LIQUID_LEVEL_SOURCE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (total_level > 0) //|| flowed != volume)
|
|
||||||
infostream <<" AFTER level=" << (int)total_level
|
|
||||||
//<< " flowed="<<flowed<< " volume=" << volume
|
|
||||||
<< " wantsame="<<(int)want_level<< " top="
|
|
||||||
<< (int)liquid_levels_want[D_TOP]<< " topwas="
|
|
||||||
<< (int)liquid_levels[D_TOP]<< " bot="
|
|
||||||
<< (int)liquid_levels_want[D_BOTTOM]<<std::endl;
|
|
||||||
*/
|
|
||||||
|
|
||||||
//u8 changed = 0;
|
|
||||||
for (u16 i = 0; i < 7; i++) {
|
|
||||||
if (liquid_levels_want[i] < 0 || !neighbors[i].l)
|
|
||||||
continue;
|
|
||||||
MapNode & n0 = neighbors[i].n;
|
|
||||||
p0 = neighbors[i].p;
|
|
||||||
/*
|
|
||||||
decide on the type (and possibly level) of the current node
|
|
||||||
*/
|
|
||||||
content_t new_node_content;
|
|
||||||
s8 new_node_level = -1;
|
|
||||||
u8 viscosity = nodemgr->get(liquid_kind).liquid_viscosity;
|
|
||||||
if (viscosity > 1 && liquid_levels_want[i] != liquid_levels[i]) {
|
|
||||||
// amount to gain, limited by viscosity
|
|
||||||
// must be at least 1 in absolute value
|
|
||||||
s8 level_inc = liquid_levels_want[i] - liquid_levels[i];
|
|
||||||
if (level_inc < -viscosity || level_inc > viscosity)
|
|
||||||
new_node_level = liquid_levels[i] + level_inc/viscosity;
|
|
||||||
else if (level_inc < 0)
|
|
||||||
new_node_level = liquid_levels[i] - 1;
|
|
||||||
else if (level_inc > 0)
|
|
||||||
new_node_level = liquid_levels[i] + 1;
|
|
||||||
} else {
|
|
||||||
new_node_level = liquid_levels_want[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new_node_level >= LIQUID_LEVEL_SOURCE)
|
|
||||||
new_node_content = liquid_kind;
|
|
||||||
else if (new_node_level > 0)
|
|
||||||
new_node_content = liquid_kind_flowing;
|
|
||||||
else
|
|
||||||
new_node_content = CONTENT_AIR;
|
|
||||||
|
|
||||||
// last level must flow down on stairs
|
|
||||||
if (liquid_levels_want[i] != liquid_levels[i] &&
|
|
||||||
liquid_levels[D_TOP] <= 0 && !neighbors[D_BOTTOM].l &&
|
|
||||||
new_node_level >= 1 && new_node_level <= 2) {
|
|
||||||
for (u16 ii = D_SELF + 1; ii < D_TOP; ++ii) { // only same level
|
|
||||||
if (neighbors[ii].l)
|
|
||||||
must_reflow_second.push_back(p0 + dirs[ii]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
check if anything has changed.
|
|
||||||
if not, just continue with the next node.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
if (
|
|
||||||
new_node_content == n0.getContent()
|
|
||||||
&& (nodemgr->get(n0.getContent()).liquid_type != LIQUID_FLOWING ||
|
|
||||||
(n0.getLevel(nodemgr) == (u8)new_node_level
|
|
||||||
//&& ((n0.param2 & LIQUID_FLOW_DOWN_MASK) ==
|
|
||||||
//LIQUID_FLOW_DOWN_MASK) == flowing_down
|
|
||||||
))
|
|
||||||
&&
|
|
||||||
(nodemgr->get(n0.getContent()).liquid_type != LIQUID_SOURCE ||
|
|
||||||
(((n0.param2 & LIQUID_INFINITY_MASK) ==
|
|
||||||
LIQUID_INFINITY_MASK) == neighbors[i].i
|
|
||||||
))
|
|
||||||
)*/
|
|
||||||
if (liquid_levels[i] == new_node_level)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//++changed;
|
|
||||||
|
|
||||||
/*
|
|
||||||
update the current node
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
if (nodemgr->get(new_node_content).liquid_type == LIQUID_FLOWING) {
|
|
||||||
// set level to last 3 bits, flowing down bit to 4th bit
|
|
||||||
n0.param2 = (new_node_level & LIQUID_LEVEL_MASK);
|
|
||||||
} else if (nodemgr->get(new_node_content).liquid_type == LIQUID_SOURCE) {
|
|
||||||
//n0.param2 = ~(LIQUID_LEVEL_MASK | LIQUID_FLOW_DOWN_MASK);
|
|
||||||
n0.param2 = (neighbors[i].i ? LIQUID_INFINITY_MASK : 0x00);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
infostream << "set node i=" <<(int)i<<" "<< PP(p0)<< " nc="
|
|
||||||
<<new_node_content<< " p2="<<(int)n0.param2<< " nl="
|
|
||||||
<<(int)new_node_level<<std::endl;
|
|
||||||
*/
|
|
||||||
|
|
||||||
n0.setContent(liquid_kind_flowing);
|
|
||||||
n0.setLevel(nodemgr, new_node_level);
|
|
||||||
// Find out whether there is a suspect for this action
|
|
||||||
std::string suspect;
|
|
||||||
if(m_gamedef->rollback()){
|
|
||||||
suspect = m_gamedef->rollback()->getSuspect(p0, 83, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!suspect.empty()){
|
|
||||||
// Blame suspect
|
|
||||||
RollbackScopeActor rollback_scope(m_gamedef->rollback(), suspect, true);
|
|
||||||
// Get old node for rollback
|
|
||||||
RollbackNode rollback_oldnode(this, p0, m_gamedef);
|
|
||||||
// Set node
|
|
||||||
setNode(p0, n0);
|
|
||||||
// Report
|
|
||||||
RollbackNode rollback_newnode(this, p0, m_gamedef);
|
|
||||||
RollbackAction action;
|
|
||||||
action.setSetNode(p0, rollback_oldnode, rollback_newnode);
|
|
||||||
m_gamedef->rollback()->reportAction(action);
|
|
||||||
} else {
|
|
||||||
// Set node
|
|
||||||
setNode(p0, n0);
|
|
||||||
}
|
|
||||||
|
|
||||||
v3s16 blockpos = getNodeBlockPos(p0);
|
|
||||||
MapBlock *block = getBlockNoCreateNoEx(blockpos);
|
|
||||||
if(block != NULL) {
|
|
||||||
modified_blocks[blockpos] = block;
|
|
||||||
// If node emits light, MapBlock requires lighting update
|
|
||||||
if(nodemgr->get(n0).light_source != 0)
|
|
||||||
lighting_modified_blocks[block->getPos()] = block;
|
|
||||||
}
|
|
||||||
must_reflow.push_back(neighbors[i].p);
|
|
||||||
}
|
|
||||||
/* //for better relax only same level
|
|
||||||
if (changed) for (u16 ii = D_SELF + 1; ii < D_TOP; ++ii) {
|
|
||||||
if (!neighbors[ii].l) continue;
|
|
||||||
must_reflow.push_back(p0 + dirs[ii]);
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
if (loopcount)
|
|
||||||
infostream<<"Map::transformLiquids(): loopcount="<<loopcount
|
|
||||||
<<" reflow="<<must_reflow.size()
|
|
||||||
<<" queue="<< m_transforming_liquid.size()<<std::endl;
|
|
||||||
*/
|
|
||||||
while (must_reflow.size() > 0)
|
|
||||||
m_transforming_liquid.push_back(must_reflow.pop_front());
|
|
||||||
while (must_reflow_second.size() > 0)
|
|
||||||
m_transforming_liquid.push_back(must_reflow_second.pop_front());
|
|
||||||
updateLighting(lighting_modified_blocks, modified_blocks);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
|
void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (g_settings->getBool("liquid_finite"))
|
|
||||||
return Map::transformLiquidsFinite(modified_blocks);
|
|
||||||
|
|
||||||
INodeDefManager *nodemgr = m_gamedef->ndef();
|
INodeDefManager *nodemgr = m_gamedef->ndef();
|
||||||
|
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
@ -2382,26 +2007,6 @@ 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
|
||||||
*/
|
*/
|
||||||
|
@ -2434,6 +2039,10 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emer
|
||||||
else if (backend == "leveldb")
|
else if (backend == "leveldb")
|
||||||
dbase = new Database_LevelDB(this, savedir);
|
dbase = new Database_LevelDB(this, savedir);
|
||||||
#endif
|
#endif
|
||||||
|
#if USE_REDIS
|
||||||
|
else if (backend == "redis")
|
||||||
|
dbase = new Database_Redis(this, savedir);
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
throw BaseException("Unknown map backend");
|
throw BaseException("Unknown map backend");
|
||||||
}
|
}
|
||||||
|
@ -2596,6 +2205,7 @@ bool ServerMap::initBlockMake(BlockMakeData *data, v3s16 blockpos)
|
||||||
// Sector metadata is loaded from disk if not already loaded.
|
// Sector metadata is loaded from disk if not already loaded.
|
||||||
ServerMapSector *sector = createSector(sectorpos);
|
ServerMapSector *sector = createSector(sectorpos);
|
||||||
assert(sector);
|
assert(sector);
|
||||||
|
(void) sector;
|
||||||
|
|
||||||
for(s16 y=blockpos_min.Y-extra_borders.Y;
|
for(s16 y=blockpos_min.Y-extra_borders.Y;
|
||||||
y<=blockpos_max.Y+extra_borders.Y; y++)
|
y<=blockpos_max.Y+extra_borders.Y; y++)
|
||||||
|
@ -2810,29 +2420,6 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data,
|
||||||
<<","<<blockpos_requested.Y<<","
|
<<","<<blockpos_requested.Y<<","
|
||||||
<<blockpos_requested.Z<<")"<<std::endl;*/
|
<<blockpos_requested.Z<<")"<<std::endl;*/
|
||||||
|
|
||||||
/*
|
|
||||||
Update weather data in blocks
|
|
||||||
*/
|
|
||||||
ServerEnvironment *senv = &((Server *)m_gamedef)->getEnv();
|
|
||||||
for(s16 x=blockpos_min.X-extra_borders.X;
|
|
||||||
x<=blockpos_max.X+extra_borders.X; x++)
|
|
||||||
for(s16 z=blockpos_min.Z-extra_borders.Z;
|
|
||||||
z<=blockpos_max.Z+extra_borders.Z; z++)
|
|
||||||
for(s16 y=blockpos_min.Y-extra_borders.Y;
|
|
||||||
y<=blockpos_max.Y+extra_borders.Y; y++)
|
|
||||||
{
|
|
||||||
v3s16 p(x, y, z);
|
|
||||||
MapBlock *block = getBlockNoCreateNoEx(p);
|
|
||||||
block->heat_last_update = 0;
|
|
||||||
block->humidity_last_update = 0;
|
|
||||||
if (senv->m_use_weather) {
|
|
||||||
updateBlockHeat(senv, p * MAP_BLOCKSIZE, block);
|
|
||||||
updateBlockHumidity(senv, p * MAP_BLOCKSIZE, block);
|
|
||||||
} else {
|
|
||||||
block->heat = HEAT_UNDEFINED;
|
|
||||||
block->humidity = HUMIDITY_UNDEFINED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if(enable_mapgen_debug_info)
|
if(enable_mapgen_debug_info)
|
||||||
|
@ -3167,19 +2754,6 @@ MapBlock *ServerMap::getBlockOrEmerge(v3s16 p3d)
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerMap::prepareBlock(MapBlock *block) {
|
void ServerMap::prepareBlock(MapBlock *block) {
|
||||||
ServerEnvironment *senv = &((Server *)m_gamedef)->getEnv();
|
|
||||||
|
|
||||||
// Calculate weather conditions
|
|
||||||
block->heat_last_update = 0;
|
|
||||||
block->humidity_last_update = 0;
|
|
||||||
if (senv->m_use_weather) {
|
|
||||||
v3s16 p = block->getPos() * MAP_BLOCKSIZE;
|
|
||||||
updateBlockHeat(senv, p, block);
|
|
||||||
updateBlockHumidity(senv, p, block);
|
|
||||||
} else {
|
|
||||||
block->heat = HEAT_UNDEFINED;
|
|
||||||
block->humidity = HUMIDITY_UNDEFINED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s16 ServerMap::findGroundLevel(v2s16 p2d)
|
s16 ServerMap::findGroundLevel(v2s16 p2d)
|
||||||
|
@ -3261,12 +2835,13 @@ std::string ServerMap::getSectorDir(v2s16 pos, int layout)
|
||||||
return m_savedir + DIR_DELIM + "sectors2" + DIR_DELIM + cc;
|
return m_savedir + DIR_DELIM + "sectors2" + DIR_DELIM + cc;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v2s16 ServerMap::getSectorPos(std::string dirname)
|
v2s16 ServerMap::getSectorPos(std::string dirname)
|
||||||
{
|
{
|
||||||
unsigned int x, y;
|
unsigned int x = 0, y = 0;
|
||||||
int r;
|
int r;
|
||||||
std::string component;
|
std::string component;
|
||||||
fs::RemoveLastPathComponent(dirname, &component, 1);
|
fs::RemoveLastPathComponent(dirname, &component, 1);
|
||||||
|
@ -3908,48 +3483,6 @@ void ServerMap::PrintInfo(std::ostream &out)
|
||||||
out<<"ServerMap: ";
|
out<<"ServerMap: ";
|
||||||
}
|
}
|
||||||
|
|
||||||
s16 ServerMap::updateBlockHeat(ServerEnvironment *env, v3s16 p, MapBlock *block)
|
|
||||||
{
|
|
||||||
u32 gametime = env->getGameTime();
|
|
||||||
|
|
||||||
if (block) {
|
|
||||||
if (gametime - block->heat_last_update < 10)
|
|
||||||
return block->heat;
|
|
||||||
} else {
|
|
||||||
block = getBlockNoCreateNoEx(getNodeBlockPos(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
f32 heat = m_emerge->biomedef->calcBlockHeat(p, getSeed(),
|
|
||||||
env->getTimeOfDayF(), gametime * env->getTimeOfDaySpeed());
|
|
||||||
|
|
||||||
if(block) {
|
|
||||||
block->heat = heat;
|
|
||||||
block->heat_last_update = gametime;
|
|
||||||
}
|
|
||||||
return heat;
|
|
||||||
}
|
|
||||||
|
|
||||||
s16 ServerMap::updateBlockHumidity(ServerEnvironment *env, v3s16 p, MapBlock *block)
|
|
||||||
{
|
|
||||||
u32 gametime = env->getGameTime();
|
|
||||||
|
|
||||||
if (block) {
|
|
||||||
if (gametime - block->humidity_last_update < 10)
|
|
||||||
return block->humidity;
|
|
||||||
} else {
|
|
||||||
block = getBlockNoCreateNoEx(getNodeBlockPos(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
f32 humidity = m_emerge->biomedef->calcBlockHumidity(p, getSeed(),
|
|
||||||
env->getTimeOfDayF(), gametime * env->getTimeOfDaySpeed());
|
|
||||||
|
|
||||||
if(block) {
|
|
||||||
block->humidity = humidity;
|
|
||||||
block->humidity_last_update = gametime;
|
|
||||||
}
|
|
||||||
return humidity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
MapVoxelManipulator
|
MapVoxelManipulator
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -304,7 +304,6 @@ public:
|
||||||
virtual void PrintInfo(std::ostream &out);
|
virtual void PrintInfo(std::ostream &out);
|
||||||
|
|
||||||
void transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks);
|
void transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks);
|
||||||
void transformLiquidsFinite(std::map<v3s16, MapBlock*> & modified_blocks);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Node metadata
|
Node metadata
|
||||||
|
@ -351,9 +350,6 @@ 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;
|
||||||
|
|
||||||
|
@ -504,9 +500,6 @@ public:
|
||||||
u64 getSeed();
|
u64 getSeed();
|
||||||
s16 getWaterLevel();
|
s16 getWaterLevel();
|
||||||
|
|
||||||
virtual s16 updateBlockHeat(ServerEnvironment *env, v3s16 p, MapBlock *block = NULL);
|
|
||||||
virtual s16 updateBlockHumidity(ServerEnvironment *env, v3s16 p, MapBlock *block = NULL);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Emerge manager
|
// Emerge manager
|
||||||
EmergeManager *m_emerge;
|
EmergeManager *m_emerge;
|
||||||
|
|
|
@ -43,10 +43,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MapBlock::MapBlock(Map *parent, v3s16 pos, IGameDef *gamedef, bool dummy):
|
MapBlock::MapBlock(Map *parent, v3s16 pos, IGameDef *gamedef, bool dummy):
|
||||||
heat(0),
|
|
||||||
humidity(0),
|
|
||||||
heat_last_update(0),
|
|
||||||
humidity_last_update(0),
|
|
||||||
m_parent(parent),
|
m_parent(parent),
|
||||||
m_pos(pos),
|
m_pos(pos),
|
||||||
m_gamedef(gamedef),
|
m_gamedef(gamedef),
|
||||||
|
@ -647,8 +643,8 @@ void MapBlock::serializeNetworkSpecific(std::ostream &os, u16 net_proto_version)
|
||||||
if(net_proto_version >= 21){
|
if(net_proto_version >= 21){
|
||||||
int version = 1;
|
int version = 1;
|
||||||
writeU8(os, version);
|
writeU8(os, version);
|
||||||
writeF1000(os, heat);
|
writeF1000(os, 0); // deprecated heat
|
||||||
writeF1000(os, humidity);
|
writeF1000(os, 0); // deprecated humidity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -764,8 +760,8 @@ void MapBlock::deSerializeNetworkSpecific(std::istream &is)
|
||||||
//if(version != 1)
|
//if(version != 1)
|
||||||
// throw SerializationError("unsupported MapBlock version");
|
// throw SerializationError("unsupported MapBlock version");
|
||||||
if(version >= 1) {
|
if(version >= 1) {
|
||||||
heat = readF1000(is);
|
readF1000(is); // deprecated heat
|
||||||
humidity = readF1000(is);
|
readF1000(is); // deprecated humidity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(SerializationError &e)
|
catch(SerializationError &e)
|
||||||
|
|
|
@ -513,11 +513,6 @@ public:
|
||||||
NodeMetadataList m_node_metadata;
|
NodeMetadataList m_node_metadata;
|
||||||
NodeTimerList m_node_timers;
|
NodeTimerList m_node_timers;
|
||||||
StaticObjectList m_static_objects;
|
StaticObjectList m_static_objects;
|
||||||
|
|
||||||
s16 heat;
|
|
||||||
s16 humidity;
|
|
||||||
u32 heat_last_update;
|
|
||||||
u32 humidity_last_update;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -150,9 +150,8 @@ void MeshMakeData::setSmoothLighting(bool smooth_lighting)
|
||||||
Single light bank.
|
Single light bank.
|
||||||
*/
|
*/
|
||||||
static u8 getInteriorLight(enum LightBank bank, MapNode n, s32 increment,
|
static u8 getInteriorLight(enum LightBank bank, MapNode n, s32 increment,
|
||||||
MeshMakeData *data)
|
INodeDefManager *ndef)
|
||||||
{
|
{
|
||||||
INodeDefManager *ndef = data->m_gamedef->ndef();
|
|
||||||
u8 light = n.getLight(bank, ndef);
|
u8 light = n.getLight(bank, ndef);
|
||||||
|
|
||||||
while(increment > 0)
|
while(increment > 0)
|
||||||
|
@ -173,10 +172,10 @@ static u8 getInteriorLight(enum LightBank bank, MapNode n, s32 increment,
|
||||||
Calculate non-smooth lighting at interior of node.
|
Calculate non-smooth lighting at interior of node.
|
||||||
Both light banks.
|
Both light banks.
|
||||||
*/
|
*/
|
||||||
u16 getInteriorLight(MapNode n, s32 increment, MeshMakeData *data)
|
u16 getInteriorLight(MapNode n, s32 increment, INodeDefManager *ndef)
|
||||||
{
|
{
|
||||||
u16 day = getInteriorLight(LIGHTBANK_DAY, n, increment, data);
|
u16 day = getInteriorLight(LIGHTBANK_DAY, n, increment, ndef);
|
||||||
u16 night = getInteriorLight(LIGHTBANK_NIGHT, n, increment, data);
|
u16 night = getInteriorLight(LIGHTBANK_NIGHT, n, increment, ndef);
|
||||||
return day | (night << 8);
|
return day | (night << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,10 +184,8 @@ u16 getInteriorLight(MapNode n, s32 increment, MeshMakeData *data)
|
||||||
Single light bank.
|
Single light bank.
|
||||||
*/
|
*/
|
||||||
static u8 getFaceLight(enum LightBank bank, MapNode n, MapNode n2,
|
static u8 getFaceLight(enum LightBank bank, MapNode n, MapNode n2,
|
||||||
v3s16 face_dir, MeshMakeData *data)
|
v3s16 face_dir, INodeDefManager *ndef)
|
||||||
{
|
{
|
||||||
INodeDefManager *ndef = data->m_gamedef->ndef();
|
|
||||||
|
|
||||||
u8 light;
|
u8 light;
|
||||||
u8 l1 = n.getLight(bank, ndef);
|
u8 l1 = n.getLight(bank, ndef);
|
||||||
u8 l2 = n2.getLight(bank, ndef);
|
u8 l2 = n2.getLight(bank, ndef);
|
||||||
|
@ -227,10 +224,10 @@ static u8 getFaceLight(enum LightBank bank, MapNode n, MapNode n2,
|
||||||
Calculate non-smooth lighting at face of node.
|
Calculate non-smooth lighting at face of node.
|
||||||
Both light banks.
|
Both light banks.
|
||||||
*/
|
*/
|
||||||
u16 getFaceLight(MapNode n, MapNode n2, v3s16 face_dir, MeshMakeData *data)
|
u16 getFaceLight(MapNode n, MapNode n2, v3s16 face_dir, INodeDefManager *ndef)
|
||||||
{
|
{
|
||||||
u16 day = getFaceLight(LIGHTBANK_DAY, n, n2, face_dir, data);
|
u16 day = getFaceLight(LIGHTBANK_DAY, n, n2, face_dir, ndef);
|
||||||
u16 night = getFaceLight(LIGHTBANK_NIGHT, n, n2, face_dir, data);
|
u16 night = getFaceLight(LIGHTBANK_NIGHT, n, n2, face_dir, ndef);
|
||||||
return day | (night << 8);
|
return day | (night << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -812,7 +809,7 @@ static void getTileInfo(
|
||||||
if(data->m_smooth_lighting == false)
|
if(data->m_smooth_lighting == false)
|
||||||
{
|
{
|
||||||
lights[0] = lights[1] = lights[2] = lights[3] =
|
lights[0] = lights[1] = lights[2] = lights[3] =
|
||||||
getFaceLight(n0, n1, face_dir, data);
|
getFaceLight(n0, n1, face_dir, ndef);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1212,20 +1209,25 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
|
||||||
ITextureSource *tsrc = data->m_gamedef->tsrc();
|
ITextureSource *tsrc = data->m_gamedef->tsrc();
|
||||||
material.setTexture(2, tsrc->getTexture("disable_img.png"));
|
material.setTexture(2, tsrc->getTexture("disable_img.png"));
|
||||||
if (enable_bumpmapping || enable_parallax_occlusion) {
|
if (enable_bumpmapping || enable_parallax_occlusion) {
|
||||||
std::string fname_base = tsrc->getTextureName(p.tile.texture_id);
|
if (tsrc->isKnownSourceImage("override_normal.png")){
|
||||||
std::string normal_ext = "_normal.png";
|
material.setTexture(1, tsrc->getTexture("override_normal.png"));
|
||||||
size_t pos = fname_base.find(".");
|
|
||||||
std::string fname_normal = fname_base.substr(0, pos) + normal_ext;
|
|
||||||
|
|
||||||
if (tsrc->isKnownSourceImage(fname_normal)) {
|
|
||||||
// look for image extension and replace it
|
|
||||||
size_t i = 0;
|
|
||||||
while ((i = fname_base.find(".", i)) != std::string::npos) {
|
|
||||||
fname_base.replace(i, 4, normal_ext);
|
|
||||||
i += normal_ext.length();
|
|
||||||
}
|
|
||||||
material.setTexture(1, tsrc->getTexture(fname_base));
|
|
||||||
material.setTexture(2, tsrc->getTexture("enable_img.png"));
|
material.setTexture(2, tsrc->getTexture("enable_img.png"));
|
||||||
|
} else {
|
||||||
|
std::string fname_base = tsrc->getTextureName(p.tile.texture_id);
|
||||||
|
std::string normal_ext = "_normal.png";
|
||||||
|
size_t pos = fname_base.find(".");
|
||||||
|
std::string fname_normal = fname_base.substr(0, pos) + normal_ext;
|
||||||
|
|
||||||
|
if (tsrc->isKnownSourceImage(fname_normal)) {
|
||||||
|
// look for image extension and replace it
|
||||||
|
size_t i = 0;
|
||||||
|
while ((i = fname_base.find(".", i)) != std::string::npos) {
|
||||||
|
fname_base.replace(i, 4, normal_ext);
|
||||||
|
i += normal_ext.length();
|
||||||
|
}
|
||||||
|
material.setTexture(1, tsrc->getTexture(fname_base));
|
||||||
|
material.setTexture(2, tsrc->getTexture("enable_img.png"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.tile.applyMaterialOptionsWithShaders(material,
|
p.tile.applyMaterialOptionsWithShaders(material,
|
||||||
|
@ -1368,17 +1370,22 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
|
||||||
buf->getMaterial().setTexture(2, tsrc->getTexture("disable_img.png"));
|
buf->getMaterial().setTexture(2, tsrc->getTexture("disable_img.png"));
|
||||||
if (enable_shaders && (enable_bumpmapping || enable_parallax_occlusion))
|
if (enable_shaders && (enable_bumpmapping || enable_parallax_occlusion))
|
||||||
{
|
{
|
||||||
std::string fname_base,fname_normal;
|
if (tsrc->isKnownSourceImage("override_normal.png")){
|
||||||
fname_base = tsrc->getTextureName(tile.texture_id);
|
buf->getMaterial().setTexture(1, tsrc->getTexture("override_normal.png"));
|
||||||
unsigned pos;
|
|
||||||
pos = fname_base.find(".");
|
|
||||||
fname_normal = fname_base.substr (0, pos);
|
|
||||||
fname_normal += "_normal.png";
|
|
||||||
if (tsrc->isKnownSourceImage(fname_normal)){
|
|
||||||
os.str("");
|
|
||||||
os<<fname_normal<<"^[verticalframe:"<<(int)tile.animation_frame_count<<":"<<frame;
|
|
||||||
buf->getMaterial().setTexture(1, tsrc->getTexture(os.str()));
|
|
||||||
buf->getMaterial().setTexture(2, tsrc->getTexture("enable_img.png"));
|
buf->getMaterial().setTexture(2, tsrc->getTexture("enable_img.png"));
|
||||||
|
} else {
|
||||||
|
std::string fname_base,fname_normal;
|
||||||
|
fname_base = tsrc->getTextureName(tile.texture_id);
|
||||||
|
unsigned pos;
|
||||||
|
pos = fname_base.find(".");
|
||||||
|
fname_normal = fname_base.substr (0, pos);
|
||||||
|
fname_normal += "_normal.png";
|
||||||
|
if (tsrc->isKnownSourceImage(fname_normal)){
|
||||||
|
os.str("");
|
||||||
|
os<<fname_normal<<"^[verticalframe:"<<(int)tile.animation_frame_count<<":"<<frame;
|
||||||
|
buf->getMaterial().setTexture(1, tsrc->getTexture(os.str()));
|
||||||
|
buf->getMaterial().setTexture(2, tsrc->getTexture("enable_img.png"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,8 +172,8 @@ inline video::SColor MapBlock_LightColor(u8 alpha, u16 light, u8 light_source=0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute light at node
|
// Compute light at node
|
||||||
u16 getInteriorLight(MapNode n, s32 increment, MeshMakeData *data);
|
u16 getInteriorLight(MapNode n, s32 increment, INodeDefManager *ndef);
|
||||||
u16 getFaceLight(MapNode n, MapNode n2, v3s16 face_dir, MeshMakeData *data);
|
u16 getFaceLight(MapNode n, MapNode n2, v3s16 face_dir, INodeDefManager *ndef);
|
||||||
u16 getSmoothLight(v3s16 p, v3s16 corner, MeshMakeData *data);
|
u16 getSmoothLight(v3s16 p, v3s16 corner, MeshMakeData *data);
|
||||||
|
|
||||||
// Retrieves the TileSpec of a face of a node
|
// Retrieves the TileSpec of a face of a node
|
||||||
|
|
|
@ -977,10 +977,8 @@ void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax) {
|
||||||
|
|
||||||
|
|
||||||
void Mapgen::updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax) {
|
void Mapgen::updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax) {
|
||||||
bool isliquid, wasliquid, rare;
|
bool isliquid, wasliquid;
|
||||||
v3s16 em = vm->m_area.getExtent();
|
v3s16 em = vm->m_area.getExtent();
|
||||||
rare = g_settings->getBool("liquid_finite");
|
|
||||||
int rarecnt = 0;
|
|
||||||
|
|
||||||
for (s16 z = nmin.Z; z <= nmax.Z; z++) {
|
for (s16 z = nmin.Z; z <= nmax.Z; z++) {
|
||||||
for (s16 x = nmin.X; x <= nmax.X; x++) {
|
for (s16 x = nmin.X; x <= nmax.X; x++) {
|
||||||
|
@ -990,8 +988,8 @@ void Mapgen::updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nm
|
||||||
for (s16 y = nmax.Y; y >= nmin.Y; y--) {
|
for (s16 y = nmax.Y; y >= nmin.Y; y--) {
|
||||||
isliquid = ndef->get(vm->m_data[i]).isLiquid();
|
isliquid = ndef->get(vm->m_data[i]).isLiquid();
|
||||||
|
|
||||||
// there was a change between liquid and nonliquid, add to queue. no need to add every with liquid_finite
|
// there was a change between liquid and nonliquid, add to queue.
|
||||||
if (isliquid != wasliquid && (!rare || !(rarecnt++ % 36)))
|
if (isliquid != wasliquid)
|
||||||
trans_liquid->push_back(v3s16(x, y, z));
|
trans_liquid->push_back(v3s16(x, y, z));
|
||||||
|
|
||||||
wasliquid = isliquid;
|
wasliquid = isliquid;
|
||||||
|
|
|
@ -209,7 +209,7 @@ Ore *createOre(OreType type);
|
||||||
|
|
||||||
|
|
||||||
enum DecorationType {
|
enum DecorationType {
|
||||||
DECO_SIMPLE,
|
DECO_SIMPLE = 1,
|
||||||
DECO_SCHEMATIC,
|
DECO_SCHEMATIC,
|
||||||
DECO_LSYSTEM
|
DECO_LSYSTEM
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,9 +26,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void NoiseIndev::init(NoiseIndevParams *np, int seed, int sx, int sy, int sz) {
|
void NoiseIndev::init(NoiseParams *np, int seed, int sx, int sy, int sz) {
|
||||||
Noise::init((NoiseParams*)np, seed, sx, sy, sz);
|
Noise::init(np, seed, sx, sy, sz);
|
||||||
this->npindev = np;
|
this->npindev = (NoiseIndevParams*) np;
|
||||||
}
|
}
|
||||||
|
|
||||||
NoiseIndev::NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy) : Noise(np, seed, sx, sy) {
|
NoiseIndev::NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy) : Noise(np, seed, sx, sy) {
|
||||||
|
|
|
@ -61,7 +61,7 @@ public:
|
||||||
virtual ~NoiseIndev() {};
|
virtual ~NoiseIndev() {};
|
||||||
NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy);
|
NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy);
|
||||||
NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy, int sz);
|
NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy, int sz);
|
||||||
void init(NoiseIndevParams *np, int seed, int sx, int sy, int sz);
|
void init(NoiseParams *np, int seed, int sx, int sy, int sz);
|
||||||
void transformNoiseMapFarScale(float xx = 0, float yy = 0, float zz = 0);
|
void transformNoiseMapFarScale(float xx = 0, float yy = 0, float zz = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ struct ModSpec
|
||||||
bool is_modpack;
|
bool is_modpack;
|
||||||
// if modpack:
|
// if modpack:
|
||||||
std::map<std::string,ModSpec> modpack_content;
|
std::map<std::string,ModSpec> modpack_content;
|
||||||
ModSpec(const std::string name_="", const std::string path_=""):
|
ModSpec(const std::string &name_="", const std::string &path_=""):
|
||||||
name(name_),
|
name(name_),
|
||||||
path(path_),
|
path(path_),
|
||||||
depends(),
|
depends(),
|
||||||
|
|
10
src/player.h
10
src/player.h
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "irrlichttypes_bloated.h"
|
#include "irrlichttypes_bloated.h"
|
||||||
#include "inventory.h"
|
#include "inventory.h"
|
||||||
#include "constants.h" // BS
|
#include "constants.h" // BS
|
||||||
|
#include <list>
|
||||||
|
|
||||||
#define PLAYERNAME_SIZE 20
|
#define PLAYERNAME_SIZE 20
|
||||||
|
|
||||||
|
@ -88,6 +89,7 @@ class IGameDef;
|
||||||
struct CollisionInfo;
|
struct CollisionInfo;
|
||||||
class PlayerSAO;
|
class PlayerSAO;
|
||||||
struct HudElement;
|
struct HudElement;
|
||||||
|
class Environment;
|
||||||
|
|
||||||
class Player
|
class Player
|
||||||
{
|
{
|
||||||
|
@ -96,7 +98,10 @@ public:
|
||||||
Player(IGameDef *gamedef);
|
Player(IGameDef *gamedef);
|
||||||
virtual ~Player() = 0;
|
virtual ~Player() = 0;
|
||||||
|
|
||||||
virtual void move(f32 dtime, Map &map, f32 pos_max_d)
|
virtual void move(f32 dtime, Environment *env, f32 pos_max_d)
|
||||||
|
{}
|
||||||
|
virtual void move(f32 dtime, Environment *env, f32 pos_max_d,
|
||||||
|
std::list<CollisionInfo> *collision_info)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
v3f getSpeed()
|
v3f getSpeed()
|
||||||
|
@ -269,6 +274,9 @@ public:
|
||||||
bool physics_override_sneak;
|
bool physics_override_sneak;
|
||||||
bool physics_override_sneak_glitch;
|
bool physics_override_sneak_glitch;
|
||||||
|
|
||||||
|
v2s32 local_animations[4];
|
||||||
|
float local_animation_speed;
|
||||||
|
|
||||||
u16 hp;
|
u16 hp;
|
||||||
|
|
||||||
float hurt_tilt_timer;
|
float hurt_tilt_timer;
|
||||||
|
|
|
@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
See comments in porting.h
|
See comments in porting.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "porting.h"
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
#include <mach-o/dyld.h>
|
#include <mach-o/dyld.h>
|
||||||
#include "CoreFoundation/CoreFoundation.h"
|
#include "CoreFoundation/CoreFoundation.h"
|
||||||
|
@ -37,7 +39,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "porting.h"
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
|
|
|
@ -24,6 +24,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#ifndef PORTING_HEADER
|
#ifndef PORTING_HEADER
|
||||||
#define PORTING_HEADER
|
#define PORTING_HEADER
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifdef _WIN32_WINNT
|
||||||
|
#undef _WIN32_WINNT
|
||||||
|
#endif
|
||||||
|
#define _WIN32_WINNT 0x0501 // We need to do this before any other headers
|
||||||
|
// because those might include sdkddkver.h which defines _WIN32_WINNT if not already set
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "irrlichttypes.h" // u32
|
#include "irrlichttypes.h" // u32
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
@ -42,9 +50,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
//#define ALIGNOF(type) offsetof (alignment_trick<type>, member)
|
//#define ALIGNOF(type) offsetof (alignment_trick<type>, member)
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifndef _WIN32_WINNT
|
|
||||||
#define _WIN32_WINNT 0x0501
|
|
||||||
#endif
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#define sleep_ms(x) Sleep(x)
|
#define sleep_ms(x) Sleep(x)
|
||||||
|
@ -266,6 +271,26 @@ inline u32 getTime(TimePrecision prec)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (defined(linux) || defined(__linux))
|
||||||
|
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
|
inline void setThreadName(const char* name) {
|
||||||
|
prctl(PR_SET_NAME,name);
|
||||||
|
}
|
||||||
|
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
|
/* BSD doesn't seem to support thread names. If you know about a way
|
||||||
|
* to add this feature please create a pull request.
|
||||||
|
* "setproctitle" doesn't work for threadnames.
|
||||||
|
*/
|
||||||
|
inline void setThreadName(const char* name) {}
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
// threadnames are not supported on windows
|
||||||
|
inline void setThreadName(const char* name) {}
|
||||||
|
#else
|
||||||
|
#warning "Unknown platform for setThreadName support, you wont have threadname support."
|
||||||
|
inline void setThreadName(const char* name) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace porting
|
} // namespace porting
|
||||||
|
|
||||||
|
|
|
@ -654,7 +654,7 @@ ItemStack read_item(lua_State* L, int index,Server* srv)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw LuaError(NULL, "Expecting itemstack, itemstring, table or nil");
|
throw LuaError("Expecting itemstack, itemstring, table or nil");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -840,23 +840,32 @@ void push_hit_params(lua_State *L,const HitParams ¶ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
u32 getflagsfield(lua_State *L, int table, const char *fieldname,
|
|
||||||
FlagDesc *flagdesc, u32 *flagmask)
|
bool getflagsfield(lua_State *L, int table, const char *fieldname,
|
||||||
|
FlagDesc *flagdesc, u32 *flags, u32 *flagmask)
|
||||||
{
|
{
|
||||||
u32 flags = 0;
|
|
||||||
|
|
||||||
lua_getfield(L, table, fieldname);
|
lua_getfield(L, table, fieldname);
|
||||||
|
|
||||||
if (lua_isstring(L, -1)) {
|
bool success = read_flags(L, -1, flagdesc, flags, flagmask);
|
||||||
std::string flagstr = lua_tostring(L, -1);
|
|
||||||
flags = readFlagString(flagstr, flagdesc, flagmask);
|
|
||||||
} else if (lua_istable(L, -1)) {
|
|
||||||
flags = read_flags_table(L, -1, flagdesc, flagmask);
|
|
||||||
}
|
|
||||||
|
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
return flags;
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool read_flags(lua_State *L, int index, FlagDesc *flagdesc,
|
||||||
|
u32 *flags, u32 *flagmask)
|
||||||
|
{
|
||||||
|
if (lua_isstring(L, index)) {
|
||||||
|
std::string flagstr = lua_tostring(L, index);
|
||||||
|
*flags = readFlagString(flagstr, flagdesc, flagmask);
|
||||||
|
} else if (lua_istable(L, index)) {
|
||||||
|
*flags = read_flags_table(L, index, flagdesc, flagmask);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 read_flags_table(lua_State *L, int table, FlagDesc *flagdesc, u32 *flagmask)
|
u32 read_flags_table(lua_State *L, int table, FlagDesc *flagdesc, u32 *flagmask)
|
||||||
|
@ -932,7 +941,7 @@ std::vector<ItemStack> read_items(lua_State *L, int index, Server *srv)
|
||||||
while (lua_next(L, index)) {
|
while (lua_next(L, index)) {
|
||||||
s32 key = luaL_checkinteger(L, -2);
|
s32 key = luaL_checkinteger(L, -2);
|
||||||
if (key < 1) {
|
if (key < 1) {
|
||||||
throw LuaError(NULL, "Invalid inventory list index");
|
throw LuaError("Invalid inventory list index");
|
||||||
}
|
}
|
||||||
if (items.size() < (u32) key) {
|
if (items.size() < (u32) key) {
|
||||||
items.resize(key);
|
items.resize(key);
|
||||||
|
|
|
@ -119,9 +119,14 @@ int getenumfield (lua_State *L,
|
||||||
const EnumString *spec,
|
const EnumString *spec,
|
||||||
int default_);
|
int default_);
|
||||||
|
|
||||||
u32 getflagsfield (lua_State *L, int table,
|
bool getflagsfield (lua_State *L, int table,
|
||||||
const char *fieldname,
|
const char *fieldname,
|
||||||
FlagDesc *flagdesc, u32 *flagmask);
|
FlagDesc *flagdesc,
|
||||||
|
u32 *flags, u32 *flagmask);
|
||||||
|
|
||||||
|
bool read_flags (lua_State *L, int index,
|
||||||
|
FlagDesc *flagdesc,
|
||||||
|
u32 *flags, u32 *flagmask);
|
||||||
|
|
||||||
u32 read_flags_table (lua_State *L, int table,
|
u32 read_flags_table (lua_State *L, int table,
|
||||||
FlagDesc *flagdesc, u32 *flagmask);
|
FlagDesc *flagdesc, u32 *flagmask);
|
||||||
|
|
|
@ -59,6 +59,19 @@ v2s16 read_v2s16(lua_State *L, int index)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v2s32 read_v2s32(lua_State *L, int index)
|
||||||
|
{
|
||||||
|
v2s32 p;
|
||||||
|
luaL_checktype(L, index, LUA_TTABLE);
|
||||||
|
lua_getfield(L, index, "x");
|
||||||
|
p.X = lua_tonumber(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
lua_getfield(L, index, "y");
|
||||||
|
p.Y = lua_tonumber(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
v2f read_v2f(lua_State *L, int index)
|
v2f read_v2f(lua_State *L, int index)
|
||||||
{
|
{
|
||||||
v2f p;
|
v2f p;
|
||||||
|
|
|
@ -75,6 +75,7 @@ v3s16 check_v3s16 (lua_State *L, int index);
|
||||||
v3f read_v3f (lua_State *L, int index);
|
v3f read_v3f (lua_State *L, int index);
|
||||||
v2f read_v2f (lua_State *L, int index);
|
v2f read_v2f (lua_State *L, int index);
|
||||||
v2s16 read_v2s16 (lua_State *L, int index);
|
v2s16 read_v2s16 (lua_State *L, int index);
|
||||||
|
v2s32 read_v2s32 (lua_State *L, int index);
|
||||||
video::SColor readARGB8 (lua_State *L, int index);
|
video::SColor readARGB8 (lua_State *L, int index);
|
||||||
aabb3f read_aabb3f (lua_State *L, int index, f32 scale);
|
aabb3f read_aabb3f (lua_State *L, int index, f32 scale);
|
||||||
v3s16 read_v3s16 (lua_State *L, int index);
|
v3s16 read_v3s16 (lua_State *L, int index);
|
||||||
|
|
|
@ -71,7 +71,7 @@ void script_error(lua_State *L)
|
||||||
{
|
{
|
||||||
const char *s = lua_tostring(L, -1);
|
const char *s = lua_tostring(L, -1);
|
||||||
std::string str(s ? s : "");
|
std::string str(s ? s : "");
|
||||||
throw LuaError(NULL, str);
|
throw LuaError(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push the list of callbacks (a lua table).
|
// Push the list of callbacks (a lua table).
|
||||||
|
|
|
@ -23,13 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "common/c_internal.h"
|
#include "common/c_internal.h"
|
||||||
#include "itemdef.h"
|
#include "itemdef.h"
|
||||||
|
|
||||||
LuaError::LuaError(lua_State *L, const std::string &s) :
|
|
||||||
ServerError(s)
|
|
||||||
{
|
|
||||||
if (L) {
|
|
||||||
m_s += '\n' + script_get_backtrace(L);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct EnumString es_ItemType[] =
|
struct EnumString es_ItemType[] =
|
||||||
{
|
{
|
||||||
|
|
|
@ -55,14 +55,7 @@ public:
|
||||||
class LuaError : public ServerError
|
class LuaError : public ServerError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LuaError(lua_State *L, const std::string &s);
|
LuaError(const std::string &s) : ServerError(s) {}
|
||||||
|
|
||||||
virtual ~LuaError() throw()
|
|
||||||
{}
|
|
||||||
virtual const char * what() const throw()
|
|
||||||
{
|
|
||||||
return m_s.c_str();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ class ModNameStorer
|
||||||
private:
|
private:
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
public:
|
public:
|
||||||
ModNameStorer(lua_State *L_, const std::string modname):
|
ModNameStorer(lua_State *L_, const std::string &modname):
|
||||||
L(L_)
|
L(L_)
|
||||||
{
|
{
|
||||||
// Store current modname in registry
|
// Store current modname in registry
|
||||||
|
@ -151,13 +151,14 @@ void ScriptApiBase::realityCheck()
|
||||||
if(top >= 30){
|
if(top >= 30){
|
||||||
dstream<<"Stack is over 30:"<<std::endl;
|
dstream<<"Stack is over 30:"<<std::endl;
|
||||||
stackDump(dstream);
|
stackDump(dstream);
|
||||||
throw LuaError(m_luastack, "Stack is over 30 (reality check)");
|
std::string traceback = script_get_backtrace(m_luastack);
|
||||||
|
throw LuaError("Stack is over 30 (reality check)\n" + traceback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptApiBase::scriptError()
|
void ScriptApiBase::scriptError()
|
||||||
{
|
{
|
||||||
throw LuaError(NULL, lua_tostring(m_luastack, -1));
|
throw LuaError(lua_tostring(m_luastack, -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptApiBase::stackDump(std::ostream &o)
|
void ScriptApiBase::stackDump(std::ostream &o)
|
||||||
|
|
|
@ -54,7 +54,7 @@ int ScriptApiDetached::detached_inventory_AllowMove(
|
||||||
if(lua_pcall(L, 7, 1, errorhandler))
|
if(lua_pcall(L, 7, 1, errorhandler))
|
||||||
scriptError();
|
scriptError();
|
||||||
if(!lua_isnumber(L, -1))
|
if(!lua_isnumber(L, -1))
|
||||||
throw LuaError(NULL, "allow_move should return a number");
|
throw LuaError("allow_move should return a number. name=" + name);
|
||||||
int ret = luaL_checkinteger(L, -1);
|
int ret = luaL_checkinteger(L, -1);
|
||||||
lua_pop(L, 2); // Pop integer and error handler
|
lua_pop(L, 2); // Pop integer and error handler
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -86,7 +86,7 @@ int ScriptApiDetached::detached_inventory_AllowPut(
|
||||||
if(lua_pcall(L, 5, 1, errorhandler))
|
if(lua_pcall(L, 5, 1, errorhandler))
|
||||||
scriptError();
|
scriptError();
|
||||||
if(!lua_isnumber(L, -1))
|
if(!lua_isnumber(L, -1))
|
||||||
throw LuaError(NULL, "allow_put should return a number");
|
throw LuaError("allow_put should return a number. name=" + name);
|
||||||
int ret = luaL_checkinteger(L, -1);
|
int ret = luaL_checkinteger(L, -1);
|
||||||
lua_pop(L, 2); // Pop integer and error handler
|
lua_pop(L, 2); // Pop integer and error handler
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -118,7 +118,7 @@ int ScriptApiDetached::detached_inventory_AllowTake(
|
||||||
if(lua_pcall(L, 5, 1, errorhandler))
|
if(lua_pcall(L, 5, 1, errorhandler))
|
||||||
scriptError();
|
scriptError();
|
||||||
if(!lua_isnumber(L, -1))
|
if(!lua_isnumber(L, -1))
|
||||||
throw LuaError(NULL, "allow_take should return a number");
|
throw LuaError("allow_take should return a number. name=" + name);
|
||||||
int ret = luaL_checkinteger(L, -1);
|
int ret = luaL_checkinteger(L, -1);
|
||||||
lua_pop(L, 2); // Pop integer and error handler
|
lua_pop(L, 2); // Pop integer and error handler
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -232,7 +232,7 @@ bool ScriptApiDetached::getDetachedInventoryCallback(
|
||||||
// Should be a table
|
// Should be a table
|
||||||
if(lua_type(L, -1) != LUA_TTABLE)
|
if(lua_type(L, -1) != LUA_TTABLE)
|
||||||
{
|
{
|
||||||
errorstream<<"Item \""<<name<<"\" not defined"<<std::endl;
|
errorstream<<"Detached inventory \""<<name<<"\" not defined"<<std::endl;
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,8 +47,13 @@ bool ScriptApiItem::item_OnDrop(ItemStack &item,
|
||||||
pushFloatPos(L, pos);
|
pushFloatPos(L, pos);
|
||||||
if(lua_pcall(L, 3, 1, errorhandler))
|
if(lua_pcall(L, 3, 1, errorhandler))
|
||||||
scriptError();
|
scriptError();
|
||||||
if(!lua_isnil(L, -1))
|
if(!lua_isnil(L, -1)) {
|
||||||
item = read_item(L,-1, getServer());
|
try {
|
||||||
|
item = read_item(L,-1, getServer());
|
||||||
|
} catch (LuaError &e) {
|
||||||
|
throw LuaError(std::string(e.what()) + ". item=" + item.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
lua_pop(L, 2); // Pop item and error handler
|
lua_pop(L, 2); // Pop item and error handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -71,8 +76,13 @@ bool ScriptApiItem::item_OnPlace(ItemStack &item,
|
||||||
pushPointedThing(pointed);
|
pushPointedThing(pointed);
|
||||||
if(lua_pcall(L, 3, 1, errorhandler))
|
if(lua_pcall(L, 3, 1, errorhandler))
|
||||||
scriptError();
|
scriptError();
|
||||||
if(!lua_isnil(L, -1))
|
if(!lua_isnil(L, -1)) {
|
||||||
item = read_item(L,-1, getServer());
|
try {
|
||||||
|
item = read_item(L,-1, getServer());
|
||||||
|
} catch (LuaError &e) {
|
||||||
|
throw LuaError(std::string(e.what()) + ". item=" + item.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
lua_pop(L, 2); // Pop item and error handler
|
lua_pop(L, 2); // Pop item and error handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -95,8 +105,13 @@ bool ScriptApiItem::item_OnUse(ItemStack &item,
|
||||||
pushPointedThing(pointed);
|
pushPointedThing(pointed);
|
||||||
if(lua_pcall(L, 3, 1, errorhandler))
|
if(lua_pcall(L, 3, 1, errorhandler))
|
||||||
scriptError();
|
scriptError();
|
||||||
if(!lua_isnil(L, -1))
|
if(!lua_isnil(L, -1)) {
|
||||||
item = read_item(L,-1, getServer());
|
try {
|
||||||
|
item = read_item(L,-1, getServer());
|
||||||
|
} catch (LuaError &e) {
|
||||||
|
throw LuaError(std::string(e.what()) + ". item=" + item.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
lua_pop(L, 2); // Pop item and error handler
|
lua_pop(L, 2); // Pop item and error handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -123,8 +138,13 @@ bool ScriptApiItem::item_OnCraft(ItemStack &item, ServerActiveObject *user,
|
||||||
InvRef::create(L, craft_inv);
|
InvRef::create(L, craft_inv);
|
||||||
if(lua_pcall(L, 4, 1, errorhandler))
|
if(lua_pcall(L, 4, 1, errorhandler))
|
||||||
scriptError();
|
scriptError();
|
||||||
if(!lua_isnil(L, -1))
|
if(!lua_isnil(L, -1)) {
|
||||||
item = read_item(L,-1, getServer());
|
try {
|
||||||
|
item = read_item(L,-1, getServer());
|
||||||
|
} catch (LuaError &e) {
|
||||||
|
throw LuaError(std::string(e.what()) + ". item=" + item.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
lua_pop(L, 2); // Pop item and error handler
|
lua_pop(L, 2); // Pop item and error handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -151,8 +171,13 @@ bool ScriptApiItem::item_CraftPredict(ItemStack &item, ServerActiveObject *user,
|
||||||
InvRef::create(L, craft_inv);
|
InvRef::create(L, craft_inv);
|
||||||
if(lua_pcall(L, 4, 1, errorhandler))
|
if(lua_pcall(L, 4, 1, errorhandler))
|
||||||
scriptError();
|
scriptError();
|
||||||
if(!lua_isnil(L, -1))
|
if(!lua_isnil(L, -1)) {
|
||||||
item = read_item(L,-1, getServer());
|
try {
|
||||||
|
item = read_item(L,-1, getServer());
|
||||||
|
} catch (LuaError &e) {
|
||||||
|
throw LuaError(std::string(e.what()) + ". item=" + item.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
lua_pop(L, 2); // Pop item and error handler
|
lua_pop(L, 2); // Pop item and error handler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ struct ItemDefinition;
|
||||||
class LuaItemStack;
|
class LuaItemStack;
|
||||||
class ModApiItemMod;
|
class ModApiItemMod;
|
||||||
class InventoryList;
|
class InventoryList;
|
||||||
class InventoryLocation;
|
struct InventoryLocation;
|
||||||
|
|
||||||
class ScriptApiItem
|
class ScriptApiItem
|
||||||
: virtual public ScriptApiBase
|
: virtual public ScriptApiBase
|
||||||
|
|
|
@ -61,7 +61,7 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowMove(v3s16 p,
|
||||||
scriptError();
|
scriptError();
|
||||||
lua_remove(L, errorhandler); // Remove error handler
|
lua_remove(L, errorhandler); // Remove error handler
|
||||||
if(!lua_isnumber(L, -1))
|
if(!lua_isnumber(L, -1))
|
||||||
throw LuaError(NULL, "allow_metadata_inventory_move should"
|
throw LuaError("allow_metadata_inventory_move should"
|
||||||
" return a number, guilty node: " + nodename);
|
" return a number, guilty node: " + nodename);
|
||||||
int num = luaL_checkinteger(L, -1);
|
int num = luaL_checkinteger(L, -1);
|
||||||
lua_pop(L, 1); // Pop integer
|
lua_pop(L, 1); // Pop integer
|
||||||
|
@ -100,7 +100,7 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowPut(v3s16 p,
|
||||||
scriptError();
|
scriptError();
|
||||||
lua_remove(L, errorhandler); // Remove error handler
|
lua_remove(L, errorhandler); // Remove error handler
|
||||||
if(!lua_isnumber(L, -1))
|
if(!lua_isnumber(L, -1))
|
||||||
throw LuaError(NULL, "allow_metadata_inventory_put should"
|
throw LuaError("allow_metadata_inventory_put should"
|
||||||
" return a number, guilty node: " + nodename);
|
" return a number, guilty node: " + nodename);
|
||||||
int num = luaL_checkinteger(L, -1);
|
int num = luaL_checkinteger(L, -1);
|
||||||
lua_pop(L, 1); // Pop integer
|
lua_pop(L, 1); // Pop integer
|
||||||
|
@ -139,7 +139,7 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowTake(v3s16 p,
|
||||||
scriptError();
|
scriptError();
|
||||||
lua_remove(L, errorhandler); // Remove error handler
|
lua_remove(L, errorhandler); // Remove error handler
|
||||||
if(!lua_isnumber(L, -1))
|
if(!lua_isnumber(L, -1))
|
||||||
throw LuaError(NULL, "allow_metadata_inventory_take should"
|
throw LuaError("allow_metadata_inventory_take should"
|
||||||
" return a number, guilty node: " + nodename);
|
" return a number, guilty node: " + nodename);
|
||||||
int num = luaL_checkinteger(L, -1);
|
int num = luaL_checkinteger(L, -1);
|
||||||
lua_pop(L, 1); // Pop integer
|
lua_pop(L, 1); // Pop integer
|
||||||
|
|
|
@ -33,7 +33,7 @@ bool ScriptApiServer::getAuth(const std::string &playername,
|
||||||
getAuthHandler();
|
getAuthHandler();
|
||||||
lua_getfield(L, -1, "get_auth");
|
lua_getfield(L, -1, "get_auth");
|
||||||
if(lua_type(L, -1) != LUA_TFUNCTION)
|
if(lua_type(L, -1) != LUA_TFUNCTION)
|
||||||
throw LuaError(NULL, "Authentication handler missing get_auth");
|
throw LuaError("Authentication handler missing get_auth");
|
||||||
lua_pushstring(L, playername.c_str());
|
lua_pushstring(L, playername.c_str());
|
||||||
if(lua_pcall(L, 1, 1, errorhandler))
|
if(lua_pcall(L, 1, 1, errorhandler))
|
||||||
scriptError();
|
scriptError();
|
||||||
|
@ -48,13 +48,13 @@ bool ScriptApiServer::getAuth(const std::string &playername,
|
||||||
std::string password;
|
std::string password;
|
||||||
bool found = getstringfield(L, -1, "password", password);
|
bool found = getstringfield(L, -1, "password", password);
|
||||||
if(!found)
|
if(!found)
|
||||||
throw LuaError(NULL, "Authentication handler didn't return password");
|
throw LuaError("Authentication handler didn't return password");
|
||||||
if(dst_password)
|
if(dst_password)
|
||||||
*dst_password = password;
|
*dst_password = password;
|
||||||
|
|
||||||
lua_getfield(L, -1, "privileges");
|
lua_getfield(L, -1, "privileges");
|
||||||
if(!lua_istable(L, -1))
|
if(!lua_istable(L, -1))
|
||||||
throw LuaError(NULL, "Authentication handler didn't return privilege table");
|
throw LuaError("Authentication handler didn't return privilege table");
|
||||||
if(dst_privs)
|
if(dst_privs)
|
||||||
readPrivileges(-1, *dst_privs);
|
readPrivileges(-1, *dst_privs);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
@ -74,7 +74,7 @@ void ScriptApiServer::getAuthHandler()
|
||||||
}
|
}
|
||||||
lua_remove(L, -2); // Remove minetest
|
lua_remove(L, -2); // Remove minetest
|
||||||
if(lua_type(L, -1) != LUA_TTABLE)
|
if(lua_type(L, -1) != LUA_TTABLE)
|
||||||
throw LuaError(NULL, "Authentication handler table not valid");
|
throw LuaError("Authentication handler table not valid");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptApiServer::readPrivileges(int index, std::set<std::string> &result)
|
void ScriptApiServer::readPrivileges(int index, std::set<std::string> &result)
|
||||||
|
@ -108,7 +108,7 @@ void ScriptApiServer::createAuth(const std::string &playername,
|
||||||
lua_getfield(L, -1, "create_auth");
|
lua_getfield(L, -1, "create_auth");
|
||||||
lua_remove(L, -2); // Remove auth handler
|
lua_remove(L, -2); // Remove auth handler
|
||||||
if(lua_type(L, -1) != LUA_TFUNCTION)
|
if(lua_type(L, -1) != LUA_TFUNCTION)
|
||||||
throw LuaError(NULL, "Authentication handler missing create_auth");
|
throw LuaError("Authentication handler missing create_auth");
|
||||||
lua_pushstring(L, playername.c_str());
|
lua_pushstring(L, playername.c_str());
|
||||||
lua_pushstring(L, password.c_str());
|
lua_pushstring(L, password.c_str());
|
||||||
if(lua_pcall(L, 2, 0, errorhandler))
|
if(lua_pcall(L, 2, 0, errorhandler))
|
||||||
|
@ -128,7 +128,7 @@ bool ScriptApiServer::setPassword(const std::string &playername,
|
||||||
lua_getfield(L, -1, "set_password");
|
lua_getfield(L, -1, "set_password");
|
||||||
lua_remove(L, -2); // Remove auth handler
|
lua_remove(L, -2); // Remove auth handler
|
||||||
if(lua_type(L, -1) != LUA_TFUNCTION)
|
if(lua_type(L, -1) != LUA_TFUNCTION)
|
||||||
throw LuaError(NULL, "Authentication handler missing set_password");
|
throw LuaError("Authentication handler missing set_password");
|
||||||
lua_pushstring(L, playername.c_str());
|
lua_pushstring(L, playername.c_str());
|
||||||
lua_pushstring(L, password.c_str());
|
lua_pushstring(L, password.c_str());
|
||||||
if(lua_pcall(L, 2, 1, errorhandler))
|
if(lua_pcall(L, 2, 1, errorhandler))
|
||||||
|
|
|
@ -262,6 +262,9 @@ void* AsyncWorkerThread::worker_thread_main() {
|
||||||
snprintf(number,sizeof(number),"%d",m_threadnum);
|
snprintf(number,sizeof(number),"%d",m_threadnum);
|
||||||
log_register_thread(std::string("AsyncWorkerThread_") + number);
|
log_register_thread(std::string("AsyncWorkerThread_") + number);
|
||||||
|
|
||||||
|
porting::setThreadName(
|
||||||
|
std::string(std::string("AsyncWorkTh_") + number).c_str());
|
||||||
|
|
||||||
/** prepare job lua environment **/
|
/** prepare job lua environment **/
|
||||||
lua_newtable(m_LuaStack);
|
lua_newtable(m_LuaStack);
|
||||||
lua_setglobal(m_LuaStack, "engine");
|
lua_setglobal(m_LuaStack, "engine");
|
||||||
|
|
|
@ -48,7 +48,7 @@ protected:
|
||||||
ScriptApiBase *scriptIface = getScriptApiBase(L);
|
ScriptApiBase *scriptIface = getScriptApiBase(L);
|
||||||
T *scriptIfaceDowncast = dynamic_cast<T*>(scriptIface);
|
T *scriptIfaceDowncast = dynamic_cast<T*>(scriptIface);
|
||||||
if (!scriptIfaceDowncast) {
|
if (!scriptIfaceDowncast) {
|
||||||
throw LuaError(NULL, "Requested unavailable ScriptApi - core engine bug!");
|
throw LuaError("Requested unavailable ScriptApi - core engine bug!");
|
||||||
}
|
}
|
||||||
return scriptIfaceDowncast;
|
return scriptIfaceDowncast;
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,16 +150,16 @@ int ModApiCraft::l_register_craft(lua_State *L)
|
||||||
if(type == "shaped"){
|
if(type == "shaped"){
|
||||||
std::string output = getstringfield_default(L, table, "output", "");
|
std::string output = getstringfield_default(L, table, "output", "");
|
||||||
if(output == "")
|
if(output == "")
|
||||||
throw LuaError(NULL, "Crafting definition is missing an output");
|
throw LuaError("Crafting definition is missing an output");
|
||||||
|
|
||||||
int width = 0;
|
int width = 0;
|
||||||
std::vector<std::string> recipe;
|
std::vector<std::string> recipe;
|
||||||
lua_getfield(L, table, "recipe");
|
lua_getfield(L, table, "recipe");
|
||||||
if(lua_isnil(L, -1))
|
if(lua_isnil(L, -1))
|
||||||
throw LuaError(NULL, "Crafting definition is missing a recipe"
|
throw LuaError("Crafting definition is missing a recipe"
|
||||||
" (output=\"" + output + "\")");
|
" (output=\"" + output + "\")");
|
||||||
if(!readCraftRecipeShaped(L, -1, width, recipe))
|
if(!readCraftRecipeShaped(L, -1, width, recipe))
|
||||||
throw LuaError(NULL, "Invalid crafting recipe"
|
throw LuaError("Invalid crafting recipe"
|
||||||
" (output=\"" + output + "\")");
|
" (output=\"" + output + "\")");
|
||||||
|
|
||||||
CraftReplacements replacements;
|
CraftReplacements replacements;
|
||||||
|
@ -167,7 +167,7 @@ int ModApiCraft::l_register_craft(lua_State *L)
|
||||||
if(!lua_isnil(L, -1))
|
if(!lua_isnil(L, -1))
|
||||||
{
|
{
|
||||||
if(!readCraftReplacements(L, -1, replacements))
|
if(!readCraftReplacements(L, -1, replacements))
|
||||||
throw LuaError(NULL, "Invalid replacements"
|
throw LuaError("Invalid replacements"
|
||||||
" (output=\"" + output + "\")");
|
" (output=\"" + output + "\")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,17 +181,17 @@ int ModApiCraft::l_register_craft(lua_State *L)
|
||||||
else if(type == "shapeless"){
|
else if(type == "shapeless"){
|
||||||
std::string output = getstringfield_default(L, table, "output", "");
|
std::string output = getstringfield_default(L, table, "output", "");
|
||||||
if(output == "")
|
if(output == "")
|
||||||
throw LuaError(NULL, "Crafting definition (shapeless)"
|
throw LuaError("Crafting definition (shapeless)"
|
||||||
" is missing an output");
|
" is missing an output");
|
||||||
|
|
||||||
std::vector<std::string> recipe;
|
std::vector<std::string> recipe;
|
||||||
lua_getfield(L, table, "recipe");
|
lua_getfield(L, table, "recipe");
|
||||||
if(lua_isnil(L, -1))
|
if(lua_isnil(L, -1))
|
||||||
throw LuaError(NULL, "Crafting definition (shapeless)"
|
throw LuaError("Crafting definition (shapeless)"
|
||||||
" is missing a recipe"
|
" is missing a recipe"
|
||||||
" (output=\"" + output + "\")");
|
" (output=\"" + output + "\")");
|
||||||
if(!readCraftRecipeShapeless(L, -1, recipe))
|
if(!readCraftRecipeShapeless(L, -1, recipe))
|
||||||
throw LuaError(NULL, "Invalid crafting recipe"
|
throw LuaError("Invalid crafting recipe"
|
||||||
" (output=\"" + output + "\")");
|
" (output=\"" + output + "\")");
|
||||||
|
|
||||||
CraftReplacements replacements;
|
CraftReplacements replacements;
|
||||||
|
@ -199,7 +199,7 @@ int ModApiCraft::l_register_craft(lua_State *L)
|
||||||
if(!lua_isnil(L, -1))
|
if(!lua_isnil(L, -1))
|
||||||
{
|
{
|
||||||
if(!readCraftReplacements(L, -1, replacements))
|
if(!readCraftReplacements(L, -1, replacements))
|
||||||
throw LuaError(NULL, "Invalid replacements"
|
throw LuaError("Invalid replacements"
|
||||||
" (output=\"" + output + "\")");
|
" (output=\"" + output + "\")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,12 +224,12 @@ int ModApiCraft::l_register_craft(lua_State *L)
|
||||||
else if(type == "cooking"){
|
else if(type == "cooking"){
|
||||||
std::string output = getstringfield_default(L, table, "output", "");
|
std::string output = getstringfield_default(L, table, "output", "");
|
||||||
if(output == "")
|
if(output == "")
|
||||||
throw LuaError(NULL, "Crafting definition (cooking)"
|
throw LuaError("Crafting definition (cooking)"
|
||||||
" is missing an output");
|
" is missing an output");
|
||||||
|
|
||||||
std::string recipe = getstringfield_default(L, table, "recipe", "");
|
std::string recipe = getstringfield_default(L, table, "recipe", "");
|
||||||
if(recipe == "")
|
if(recipe == "")
|
||||||
throw LuaError(NULL, "Crafting definition (cooking)"
|
throw LuaError("Crafting definition (cooking)"
|
||||||
" is missing a recipe"
|
" is missing a recipe"
|
||||||
" (output=\"" + output + "\")");
|
" (output=\"" + output + "\")");
|
||||||
|
|
||||||
|
@ -240,7 +240,7 @@ int ModApiCraft::l_register_craft(lua_State *L)
|
||||||
if(!lua_isnil(L, -1))
|
if(!lua_isnil(L, -1))
|
||||||
{
|
{
|
||||||
if(!readCraftReplacements(L, -1, replacements))
|
if(!readCraftReplacements(L, -1, replacements))
|
||||||
throw LuaError(NULL, "Invalid replacements"
|
throw LuaError("Invalid replacements"
|
||||||
" (cooking output=\"" + output + "\")");
|
" (cooking output=\"" + output + "\")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,7 +254,7 @@ int ModApiCraft::l_register_craft(lua_State *L)
|
||||||
else if(type == "fuel"){
|
else if(type == "fuel"){
|
||||||
std::string recipe = getstringfield_default(L, table, "recipe", "");
|
std::string recipe = getstringfield_default(L, table, "recipe", "");
|
||||||
if(recipe == "")
|
if(recipe == "")
|
||||||
throw LuaError(NULL, "Crafting definition (fuel)"
|
throw LuaError("Crafting definition (fuel)"
|
||||||
" is missing a recipe");
|
" is missing a recipe");
|
||||||
|
|
||||||
float burntime = getfloatfield_default(L, table, "burntime", 1.0);
|
float burntime = getfloatfield_default(L, table, "burntime", 1.0);
|
||||||
|
@ -264,7 +264,7 @@ int ModApiCraft::l_register_craft(lua_State *L)
|
||||||
if(!lua_isnil(L, -1))
|
if(!lua_isnil(L, -1))
|
||||||
{
|
{
|
||||||
if(!readCraftReplacements(L, -1, replacements))
|
if(!readCraftReplacements(L, -1, replacements))
|
||||||
throw LuaError(NULL, "Invalid replacements"
|
throw LuaError("Invalid replacements"
|
||||||
" (fuel recipe=\"" + recipe + "\")");
|
" (fuel recipe=\"" + recipe + "\")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ int ModApiCraft::l_register_craft(lua_State *L)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw LuaError(NULL, "Unknown crafting definition type: \"" + type + "\"");
|
throw LuaError("Unknown crafting definition type: \"" + type + "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
|
@ -765,7 +765,6 @@ int ModApiEnvMod::l_spawn_tree(lua_State *L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// minetest.transforming_liquid_add(pos)
|
// minetest.transforming_liquid_add(pos)
|
||||||
int ModApiEnvMod::l_transforming_liquid_add(lua_State *L)
|
int ModApiEnvMod::l_transforming_liquid_add(lua_State *L)
|
||||||
{
|
{
|
||||||
|
@ -776,28 +775,6 @@ int ModApiEnvMod::l_transforming_liquid_add(lua_State *L)
|
||||||
return 1;
|
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().updateBlockHeat(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().updateBlockHumidity(env, pos));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// minetest.forceload_block(blockpos)
|
// minetest.forceload_block(blockpos)
|
||||||
// blockpos = {x=num, y=num, z=num}
|
// blockpos = {x=num, y=num, z=num}
|
||||||
int ModApiEnvMod::l_forceload_block(lua_State *L)
|
int ModApiEnvMod::l_forceload_block(lua_State *L)
|
||||||
|
@ -855,8 +832,6 @@ void ModApiEnvMod::Initialize(lua_State *L, int top)
|
||||||
API_FCT(find_path);
|
API_FCT(find_path);
|
||||||
API_FCT(line_of_sight);
|
API_FCT(line_of_sight);
|
||||||
API_FCT(transforming_liquid_add);
|
API_FCT(transforming_liquid_add);
|
||||||
API_FCT(get_heat);
|
|
||||||
API_FCT(get_humidity);
|
|
||||||
API_FCT(forceload_block);
|
API_FCT(forceload_block);
|
||||||
API_FCT(forceload_free_block);
|
API_FCT(forceload_free_block);
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue