Damien Moore 2014-04-18 22:29:01 -04:00
commit 4be38f6a0d
120 changed files with 2900 additions and 2541 deletions

View File

@ -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

View File

@ -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

View File

@ -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,
}) })

View File

@ -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
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

View File

@ -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

View File

@ -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 .. "]"

View File

@ -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]" ..

View File

@ -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);
}

View File

@ -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;
} }

View File

@ -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);
}

View File

@ -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;
} }

View File

@ -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);
}

View File

@ -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;
} }

View File

@ -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);
}

View File

@ -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;
} }

View File

@ -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);
}

View File

@ -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;
} }

View File

@ -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:

View File

@ -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 =

View File

@ -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

View File

@ -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;
}

View File

@ -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");

View File

@ -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;

View File

@ -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;
} }

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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()

View File

@ -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);
} }

View File

@ -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;}

View File

@ -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

View File

@ -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;

View File

@ -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@

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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));
}
}
} }

View File

@ -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)
{ {

View File

@ -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);

View File

@ -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);
} }

View File

@ -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; }

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

224
src/database-redis.cpp Normal file
View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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() {};

View File

@ -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");

View File

@ -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)) {

View File

@ -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);
} }

View File

@ -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

View File

@ -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)
{} {}
}; };

View File

@ -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,&current_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(),&current_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();

View File

@ -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] == '#') {

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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)
{ {
} }

View File

@ -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

View File

@ -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();

View File

@ -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) {

View File

@ -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);
} }

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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
*/ */

View File

@ -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;

View File

@ -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)

View File

@ -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:
/* /*

View File

@ -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"));
}
} }
} }
} }

View File

@ -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

View File

@ -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;

View File

@ -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
}; };

View File

@ -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) {

View File

@ -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);
}; };

View File

@ -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(),

View File

@ -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;

View File

@ -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"

View File

@ -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

View File

@ -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 &params)
} }
/******************************************************************************/ /******************************************************************************/
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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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).

View File

@ -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[] =
{ {

View File

@ -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();
}
}; };

View File

@ -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)

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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

View File

@ -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

View File

@ -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))

View File

@ -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");

View File

@ -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;
} }

View File

@ -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);

View File

@ -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