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
local p = {x = pos.x+d.x, y = pos.y+d.y, z = pos.z+d.z}
local n = minetest.get_node(p)
if not minetest.registered_nodes[n.name].walkable then
return p, true
local n = minetest.get_node_or_nil(p)
if n and n.name then
local def = minetest.registered_nodes[n.name]
if def and not def.walkable then
return p, true
end
end
end
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
local pos_copy = vector.new(pos)
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)
end
end

View File

@ -116,6 +116,7 @@ minetest.register_entity("__builtin:item", {
return
end
end
self.itemstring = ''
self.object:remove()
end,
})

View File

@ -176,7 +176,7 @@ function update_menu()
-- handle errors
if gamedata.errormessage ~= nil then
formspec = "size[12,5.2]" ..
formspec = "size[12,5.2,true]" ..
"textarea[1,2;10,2;;ERROR: " ..
engine.formspec_escape(gamedata.errormessage) ..
";]"..
@ -365,7 +365,7 @@ end
function tabbuilder.gettab()
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
retval = retval .. tabbuilder.tab_header()
@ -714,15 +714,15 @@ function tabbuilder.handle_settings_buttons(fields)
if fields["cb_particles"] then
engine.setting_set("enable_particles", fields["cb_particles"])
end
if fields["cb_finite_liquid"] then
engine.setting_set("liquid_finite", fields["cb_finite_liquid"])
end
if fields["cb_bumpmapping"] then
engine.setting_set("enable_bumpmapping", fields["cb_bumpmapping"])
end
if fields["cb_parallax"] then
engine.setting_set("enable_parallax_occlusion", fields["cb_parallax"])
end
if fields["cb_generate_normalmaps"] then
engine.setting_set("generate_normalmaps", fields["cb_generate_normalmaps"])
end
if fields["cb_waving_water"] then
engine.setting_set("enable_waving_water", fields["cb_waving_water"])
end
@ -994,9 +994,6 @@ function tabbuilder.tab_settings()
.. dump(engine.setting_getbool("preload_item_visuals")) .. "]"..
"checkbox[1,2.5;cb_particles;".. fgettext("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") .. ";"
.. dump(engine.setting_getbool("mip_map")) .. "]"..
"checkbox[4.5,0.5;cb_anisotrophic;".. fgettext("Anisotropic Filtering") .. ";"
@ -1010,27 +1007,30 @@ function tabbuilder.tab_settings()
.. dump(engine.setting_getbool("enable_shaders")) .. "]"..
"button[1,4.5;2.25,0.5;btn_change_keys;".. fgettext("Change keys") .. "]"
if engine.setting_getbool("enable_shaders") then
tab_string = tab_string ..
if engine.setting_getbool("enable_shaders") then
tab_string = tab_string ..
"checkbox[8,0.5;cb_bumpmapping;".. fgettext("Bumpmapping") .. ";"
.. dump(engine.setting_getbool("enable_bumpmapping")) .. "]"..
"checkbox[8,1.0;cb_parallax;".. fgettext("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")) .. "]"..
"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")) .. "]"..
"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")) .. "]"
else
tab_string = tab_string ..
else
tab_string = tab_string ..
"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.7;4,1;;#888888" .. fgettext("Waving Water") .. ";0;true]" ..
"textlist[8.33,2.2;4,1;;#888888" .. fgettext("Waving Leaves") .. ";0;true]" ..
"textlist[8.33,2.7;4,1;;#888888" .. fgettext("Waving Plants") .. ";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 Water") .. ";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
return tab_string
return tab_string
end
--------------------------------------------------------------------------------

View File

@ -21,6 +21,8 @@ minetest.register_globalstep(function(dtime)
end)
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={...}})
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 retval =
"size[11,6.5]" ..
"size[11,6.5,true]" ..
"label[0.5,-0.25;" .. fgettext("World:") .. "]" ..
"label[1.75,-0.25;" .. worldspec.name .. "]"

View File

@ -98,7 +98,7 @@ end
-- @function [parent=#modstore] getsuccessfuldialog
function modstore.getsuccessfuldialog()
local retval = ""
retval = retval .. "size[6,2]"
retval = retval .. "size[6,2,true]"
if modstore.lastmodentry ~= nil then
retval = retval .. "label[0,0.25;" .. fgettext("Successfully installed:") .. "]"
retval = retval .. "label[3,0.25;" .. modstore.lastmodentry.moddetails.title .. "]"
@ -152,7 +152,7 @@ end
--------------------------------------------------------------------------------
-- @function [parent=#modstore] tabheader
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;" ..
"Unsorted,Search;" ..
modstore.nametoindex(tabname) .. ";true;false]" ..

View File

@ -1,71 +1,110 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
#ifdef ENABLE_PARALLAX_OCCLUSION
varying vec3 tsEyeVec;
#endif
const float e = 2.718281828459;
void main (void)
{
vec3 color;
vec2 uv = gl_TexCoord[0].st;
#ifdef USE_NORMALMAPS
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
#endif
#ifdef ENABLE_PARALLAX_OCCLUSION
float height;
vec2 tsEye = vec2(tsEyeVec.x,-tsEyeVec.y);
if (use_normalmap > 0.0) {
float map_height = texture2D(normalTexture, uv).a;
if (map_height < 1.0){
float height = PARALLAX_OCCLUSION_SCALE * map_height - PARALLAX_OCCLUSION_BIAS;
uv = uv + height * tsEye;
}
}
#endif
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap > 0.0) {
vec3 base = texture2D(baseTexture, uv).rgb;
vec3 vVec = normalize(eyeVec);
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
vec3 R = reflect(-vVec, bump);
vec3 lVec = normalize(vVec);
float diffuse = max(dot(lVec, bump), 0.0);
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
} else {
color = texture2D(baseTexture, uv).rgb;
}
#else
color = texture2D(baseTexture, uv).rgb;
#endif
float alpha = texture2D(baseTexture, uv).a;
vec4 col = vec4(color.r, color.g, color.b, alpha);
col *= gl_Color;
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
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.r, col.g, col.b, alpha);
}
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 tsEyeVec;
varying vec3 lightVec;
varying vec3 tsLightVec;
bool normalTexturePresent = false;
const float e = 2.718281828459;
float intensity (vec3 color){
return (color.r + color.g + color.b) / 3.0;
}
float get_rgb_height (vec2 uv){
return intensity(texture2D(baseTexture,uv).rgb);
}
vec4 get_normal_map(vec2 uv){
vec4 bump = texture2D(normalTexture, uv).rgba;
bump.xyz = normalize(bump.xyz * 2.0 -1.0);
bump.y = -bump.y;
return bump;
}
void main (void)
{
vec3 color;
vec4 bump;
vec2 uv = gl_TexCoord[0].st;
bool use_normalmap = false;
#ifdef USE_NORMALMAPS
if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0){
normalTexturePresent = true;
}
#endif
#ifdef ENABLE_PARALLAX_OCCLUSION
if (normalTexturePresent){
vec3 tsEye = normalize(tsEyeVec);
float height = PARALLAX_OCCLUSION_SCALE * texture2D(normalTexture, uv).a - PARALLAX_OCCLUSION_BIAS;
uv = uv + texture2D(normalTexture, uv).z * height * vec2(tsEye.x,-tsEye.y);
}
#endif
#ifdef USE_NORMALMAPS
if (normalTexturePresent){
bump = get_normal_map(uv);
use_normalmap = true;
}
#endif
#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,27 +1,33 @@
uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform mat4 mWorld;
uniform float dayNightRatio;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
#ifdef ENABLE_PARALLAX_OCCLUSION
varying vec3 tsEyeVec;
#endif
varying vec3 tsLightVec;
const float BS = 10.0;
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = mWorldViewProj * gl_Vertex;
vPosition = (mWorldViewProj * gl_Vertex).xyz;
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
vPosition = gl_Position.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);
if (gl_Normal.x > 0.5) {
// 1.0, 0.0, 0.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));
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);
tsEyeVec = normalize(eyeVec * tbnMatrix);
#endif
lightVec = sunPosition - worldPosition;
tsLightVec = lightVec * tbnMatrix;
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
tsEyeVec = eyeVec * tbnMatrix;
vec4 color;
//color = vec4(1.0, 1.0, 1.0, 1.0);
float day = gl_Color.r;
float night = gl_Color.g;
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);
rg += light_source * 2.5; // Make light sources brighter
float b = rg;
@ -90,13 +91,8 @@ void main(void)
color = color * color; // SRGB -> Linear
if(gl_Normal.y <= 0.5)
color *= 0.6;
//color *= 0.7;
color = sqrt(color); // Linear -> SRGB
color.a = gl_Color.a;
gl_FrontColor = gl_BackColor = color;
gl_TexCoord[0] = gl_MultiTexCoord0;
}

View File

@ -1,54 +1,100 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
const float e = 2.718281828459;
void main (void)
{
vec3 color;
vec2 uv = gl_TexCoord[0].st;
#ifdef USE_NORMALMAPS
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
#endif
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap > 0.0) {
vec3 base = texture2D(baseTexture, uv).rgb;
vec3 vVec = normalize(eyeVec);
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
vec3 R = reflect(-vVec, bump);
vec3 lVec = normalize(vVec);
float diffuse = max(dot(lVec, bump), 0.0);
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
} else {
color = texture2D(baseTexture, uv).rgb;
}
#else
color = texture2D(baseTexture, uv).rgb;
#endif
float alpha = texture2D(baseTexture, uv).a;
vec4 col = vec4(color.r, color.g, color.b, alpha);
col *= gl_Color;
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
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.r, col.g, col.b, alpha);
}
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
bool normalTexturePresent = false;
const float e = 2.718281828459;
float intensity (vec3 color){
return (color.r + color.g + color.b) / 3.0;
}
float get_rgb_height (vec2 uv){
return intensity(texture2D(baseTexture,uv).rgb);
}
vec4 get_normal_map(vec2 uv){
vec4 bump = texture2D(normalTexture, uv).rgba;
bump.xyz = normalize(bump.xyz * 2.0 -1.0);
bump.y = -bump.y;
return bump;
}
void main (void)
{
vec3 color;
vec4 bump;
vec2 uv = gl_TexCoord[0].st;
bool use_normalmap = false;
#ifdef USE_NORMALMAPS
if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0){
normalTexturePresent = true;
}
#endif
#ifdef USE_NORMALMAPS
if (normalTexturePresent){
bump = get_normal_map(uv);
use_normalmap = true;
}
#endif
#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 mInvWorld;
uniform mat4 mTransWorld;
uniform mat4 mWorld;
uniform float dayNightRatio;
uniform float animationTimer;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
const float BS = 10.0;
#ifdef ENABLE_WAVING_LEAVES
float smoothCurve( float x ) {
@ -27,7 +34,7 @@ void main(void)
#ifdef ENABLE_WAVING_LEAVES
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.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;
@ -36,10 +43,13 @@ void main(void)
gl_Position = mWorldViewProj * gl_Vertex;
#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;
vec4 color;
//color = vec4(1.0, 1.0, 1.0, 1.0);
@ -75,13 +85,8 @@ void main(void)
color = color * color; // SRGB -> Linear
if(gl_Normal.y <= 0.5)
color *= 0.6;
//color *= 0.7;
color = sqrt(color); // Linear -> SRGB
color.a = gl_Color.a;
gl_FrontColor = gl_BackColor = color;
gl_TexCoord[0] = gl_MultiTexCoord0;
}

View File

@ -1,54 +1,95 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
const float e = 2.718281828459;
void main (void)
{
vec3 color;
vec2 uv = gl_TexCoord[0].st;
#ifdef USE_NORMALMAPS
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
#endif
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap > 0.0) {
vec3 base = texture2D(baseTexture, uv).rgb;
vec3 vVec = normalize(eyeVec);
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
vec3 R = reflect(-vVec, bump);
vec3 lVec = normalize(vVec);
float diffuse = max(dot(vec3(-1.0, -0.4, 0.5), bump), 0.0);
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
} else {
color = texture2D(baseTexture, uv).rgb;
}
#else
color = texture2D(baseTexture, uv).rgb;
#endif
float alpha = gl_Color.a;
vec4 col = vec4(color.r, color.g, color.b, alpha);
col *= gl_Color;
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
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.r, col.g, col.b, alpha);
}
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 tsEyeVec;
varying vec3 lightVec;
varying vec3 tsLightVec;
const float e = 2.718281828459;
float intensity (vec3 color){
return (color.r + color.g + color.b) / 3.0;
}
float get_rgb_height (vec2 uv){
return intensity(texture2D(baseTexture,uv).rgb);
}
vec4 get_normal_map(vec2 uv){
vec4 bump = texture2D(normalTexture, uv).rgba;
bump.xyz = normalize(bump.xyz * 2.0 -1.0);
bump.y = -bump.y;
return bump;
}
void main (void)
{
vec3 color;
vec4 bump;
vec2 uv = gl_TexCoord[0].st;
bool use_normalmap = false;
#ifdef USE_NORMALMAPS
if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0){
bump = get_normal_map(uv);
use_normalmap = true;
}
#endif
#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
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 mInvWorld;
uniform mat4 mTransWorld;
uniform mat4 mWorld;
uniform float dayNightRatio;
uniform float animationTimer;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
varying vec3 tsEyeVec;
varying vec3 tsLightVec;
const float BS = 10.0;
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
#ifdef ENABLE_WAVING_WATER
vec4 pos2 = gl_Vertex;
pos2.y -= 2.0;
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;
gl_Position = mWorldViewProj * pos2;
vPosition = gl_Position.xyz;
#else
gl_Position = mWorldViewProj * gl_Vertex;
vPosition = gl_Position.xyz;
#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;
vPosition = (mWorldViewProj * gl_Vertex).xyz;
tsEyeVec = eyeVec * tbnMatrix;
vec4 color;
//color = vec4(1.0, 1.0, 1.0, 1.0);
float day = gl_Color.r;
float night = gl_Color.g;
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);
rg += light_source * 2.5; // Make light sources brighter
float b = rg;
@ -54,10 +98,13 @@ void main(void)
color.r = clamp(rg,0.0,1.0);
color.g = clamp(rg,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;
gl_FrontColor = gl_BackColor = color;
gl_TexCoord[0] = gl_MultiTexCoord0;
}

View File

@ -1,54 +1,94 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
const float e = 2.718281828459;
void main (void)
{
vec3 color;
vec2 uv = gl_TexCoord[0].st;
#ifdef USE_NORMALMAPS
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
#endif
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap > 0.0) {
vec3 base = texture2D(baseTexture, uv).rgb;
vec3 vVec = normalize(eyeVec);
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
vec3 R = reflect(-vVec, bump);
vec3 lVec = normalize(vVec);
float diffuse = max(dot(lVec, bump), 0.0);
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
} else {
color = texture2D(baseTexture, uv).rgb;
}
#else
color = texture2D(baseTexture, uv).rgb;
#endif
float alpha = texture2D(baseTexture, uv).a;
vec4 col = vec4(color.r, color.g, color.b, alpha);
col *= gl_Color;
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
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.r, col.g, col.b, alpha);
}
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
bool normalTexturePresent = false;
const float e = 2.718281828459;
float intensity (vec3 color){
return (color.r + color.g + color.b) / 3.0;
}
float get_rgb_height (vec2 uv){
return intensity(texture2D(baseTexture,uv).rgb);
}
vec4 get_normal_map(vec2 uv){
vec4 bump = texture2D(normalTexture, uv).rgba;
bump.xyz = normalize(bump.xyz * 2.0 -1.0);
bump.y = -bump.y;
return bump;
}
void main (void)
{
vec3 color;
vec4 bump;
vec2 uv = gl_TexCoord[0].st;
bool use_normalmap = false;
#ifdef USE_NORMALMAPS
if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0){
bump = get_normal_map(uv);
use_normalmap = true;
}
#endif
#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 mInvWorld;
uniform mat4 mTransWorld;
uniform mat4 mWorld;
uniform float dayNightRatio;
uniform float animationTimer;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
const float BS = 10.0;
#ifdef ENABLE_WAVING_PLANTS
float smoothCurve( float x ) {
@ -23,12 +30,11 @@ float smoothTriangleWave( float x ) {
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
#ifdef ENABLE_WAVING_PLANTS
vec4 pos = gl_Vertex;
vec4 pos2 = mTransWorld * gl_Vertex;
vec4 pos2 = mWorld * gl_Vertex;
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.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;
#endif
vPosition = (mWorldViewProj * gl_Vertex).xyz;
eyeVec = (gl_ModelViewMatrix * 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;
vec4 color;
//color = vec4(1.0, 1.0, 1.0, 1.0);
@ -76,11 +86,8 @@ void main(void)
color = color * color; // SRGB -> Linear
if(gl_Normal.y <= 0.5)
color *= 0.6;
//color *= 0.7;
color = sqrt(color); // Linear -> SRGB
color.a = gl_Color.a;
gl_FrontColor = gl_BackColor = color;
}

View File

@ -1,90 +1,110 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
#ifdef ENABLE_PARALLAX_OCCLUSION
varying vec3 tsEyeVec;
#endif
const float e = 2.718281828459;
void main (void)
{
vec3 color;
vec2 uv = gl_TexCoord[0].st;
#ifdef USE_NORMALMAPS
float use_normalmap = texture2D(useNormalmap,vec2(1.0,1.0)).r;
#endif
#ifdef ENABLE_PARALLAX_OCCLUSION
float height;
vec2 tsEye = vec2(tsEyeVec.x,-tsEyeVec.y);
if (use_normalmap > 0.0) {
float map_height = texture2D(normalTexture, uv).a;
if (map_height < 1.0){
float height = PARALLAX_OCCLUSION_SCALE * map_height - PARALLAX_OCCLUSION_BIAS;
uv = uv + height * tsEye;
}
}
#endif
/* Steep parallax code, for future use
if ((parallaxMappingMode == 2.0) && (use_normalmap > 0.0)) {
const float numSteps = 40.0;
float height = 1.0;
float step = 1.0 / numSteps;
vec4 NB = texture2D(normalTexture, uv);
vec2 delta = tsEye * parallaxMappingScale / numSteps;
for (float i = 0.0; i < numSteps; i++) {
if (NB.a < height) {
height -= step;
uv += delta;
NB = texture2D(normalTexture, uv);
} else {
break;
}
}
}
*/
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap > 0.0) {
vec3 base = texture2D(baseTexture, uv).rgb;
vec3 vVec = normalize(eyeVec);
vec3 bump = normalize(texture2D(normalTexture, uv).xyz * 2.0 - 1.0);
vec3 R = reflect(-vVec, bump);
vec3 lVec = normalize(vVec);
float diffuse = max(dot(lVec, bump), 0.0);
float specular = pow(clamp(dot(R, lVec), 0.0, 1.0),1.0);
color = mix (base,diffuse*base,1.0) + 0.1 * specular * diffuse;
} else {
color = texture2D(baseTexture, uv).rgb;
}
#else
color = texture2D(baseTexture, uv).rgb;
#endif
float alpha = texture2D(baseTexture, uv).a;
vec4 col = vec4(color.r, color.g, color.b, alpha);
col *= gl_Color;
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
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.r, col.g, col.b, alpha);
}
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 tsEyeVec;
varying vec3 lightVec;
varying vec3 tsLightVec;
bool normalTexturePresent = false;
const float e = 2.718281828459;
float intensity (vec3 color){
return (color.r + color.g + color.b) / 3.0;
}
float get_rgb_height (vec2 uv){
return intensity(texture2D(baseTexture,uv).rgb);
}
vec4 get_normal_map(vec2 uv){
vec4 bump = texture2D(normalTexture, uv).rgba;
bump.xyz = normalize(bump.xyz * 2.0 -1.0);
bump.y = -bump.y;
return bump;
}
void main (void)
{
vec3 color;
vec4 bump;
vec2 uv = gl_TexCoord[0].st;
bool use_normalmap = false;
#ifdef USE_NORMALMAPS
if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0){
normalTexturePresent = true;
}
#endif
#ifdef ENABLE_PARALLAX_OCCLUSION
if (normalTexturePresent){
vec3 tsEye = normalize(tsEyeVec);
float height = PARALLAX_OCCLUSION_SCALE * texture2D(normalTexture, uv).a - PARALLAX_OCCLUSION_BIAS;
uv = uv + texture2D(normalTexture, uv).z * height * vec2(tsEye.x,-tsEye.y);
}
#endif
#ifdef USE_NORMALMAPS
if (normalTexturePresent){
bump = get_normal_map(uv);
use_normalmap = true;
}
#endif
#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,27 +1,33 @@
uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform mat4 mWorld;
uniform float dayNightRatio;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 eyeVec;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
#ifdef ENABLE_PARALLAX_OCCLUSION
varying vec3 tsEyeVec;
#endif
varying vec3 tsLightVec;
const float BS = 10.0;
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = mWorldViewProj * gl_Vertex;
vPosition = (mWorldViewProj * gl_Vertex).xyz;
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
vPosition = gl_Position.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);
if (gl_Normal.x > 0.5) {
// 1.0, 0.0, 0.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));
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);
tsEyeVec = normalize(eyeVec * tbnMatrix);
#endif
lightVec = sunPosition - worldPosition;
tsLightVec = lightVec * tbnMatrix;
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
tsEyeVec = eyeVec * tbnMatrix;
vec4 color;
//color = vec4(1.0, 1.0, 1.0, 1.0);
float day = gl_Color.r;
float night = gl_Color.g;
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);
rg += light_source * 2.5; // Make light sources brighter
float b = rg;
@ -90,13 +91,8 @@ void main(void)
color = color * color; // SRGB -> Linear
if(gl_Normal.y <= 0.5)
color *= 0.6;
//color *= 0.7;
color = sqrt(color); // Linear -> SRGB
color.a = gl_Color.a;
gl_FrontColor = gl_BackColor = color;
gl_TexCoord[0] = gl_MultiTexCoord0;
}

View File

@ -849,7 +849,7 @@ Example stuff:
local meta = minetest.get_meta(pos)
meta:set_string("formspec",
"invsize[8,9;]"..
"size[8,9]"..
"list[context;main;0,0;8,4;]"..
"list[current_player;main;0,5;8,4;]")
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] = ""}
},
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"
}
})
@ -876,17 +876,17 @@ examples.
Examples:
- Chest:
invsize[8,9;]
size[8,9]
list[context;main;0,0;8,4;]
list[current_player;main;0,5;8,4;]
- Furnace:
invsize[8,9;]
size[8,9]
list[context;fuel;2,3;1,1;]
list[context;src;2,1;1,1;]
list[context;dst;5,1;2,2;]
list[current_player;main;0,5;8,4;]
- Minecraft-like player inventory
invsize[8,7.5;]
size[8,7.5]
image[1,0.6;1,2;player.png]
list[current_player;main;0,3.5;8,4;]
list[current_player;craft;3,0;3,3;]
@ -894,8 +894,9 @@ Examples:
Elements:
size[<W>,<H>]
size[<W>,<H>,<fixed_size>]
^ Define the size of the menu in inventory slots
^ fixed_size true/false (optional)
^ deprecated: invsize[<W>,<H>;]
list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;]
@ -1199,6 +1200,29 @@ minetest.features
minetest.has_feature(arg) -> bool, missing_features
^ arg: string or table in format {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:
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).
minetest.add_node_level(pos, level)
^ increase level of leveled node by level, default level = 1, if totallevel > maxlevel returns rest (total-max). can be negative for decreasing
minetest.get_heat(pos)
^ heat at pos
minetest.get_humidity(pos)
^ humidity at pos
Inventory:
minetest.get_inventory(location) -> InvRef
@ -1850,6 +1870,15 @@ Player-only: (no-op for other objects)
- override_day_night_ratio(ratio or nil)
^ 0...1: Overrides day-night ratio, controlling sunlight to a specific amount
^ 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
methods:

View File

@ -93,24 +93,10 @@
#enable_fog = true
# Enable a bit lower water surface; disable for speed (not quite optimized)
#new_style_water = false
# Constant volume liquids
#liquid_finite = false
# Max liquids processed per step
#liquid_loop_max = 10000
# Update liquids every .. recommend for finite: 0.2
#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
#new_style_leaves = true
# Enable smooth lighting with simple ambient occlusion;
@ -173,6 +159,14 @@
# Set to true to enable textures bumpmapping. Requires shaders enabled.
#enable_bumpmapping = false
# 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
# Scale of parallax occlusion effect
#parallax_occlusion_scale = 0.08
@ -353,6 +347,7 @@
# try reducing it, but don't reduce it to a number below double of targeted
# client number
#max_packets_per_iteration = 1024
#
# Physics stuff
#
@ -430,6 +425,7 @@
#enable_ipv6 = true
# Enable/disable running an IPv6 server. An IPv6 server may be restricted
# to IPv6 clients, depending on system configuration.
# Ignored if bind_address is set.
#ipv6_server = false
#main_menu_script =

View File

@ -291,6 +291,25 @@ if(ENABLE_LEVELDB)
endif(LEVELDB_LIBRARY AND LEVELDB_INCLUDE_DIR)
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(
"${PROJECT_SOURCE_DIR}/cmake_config.h.in"
"${PROJECT_BINARY_DIR}/cmake_config.h"
@ -368,6 +387,7 @@ set(common_SRCS
database-dummy.cpp
database-leveldb.cpp
database-sqlite3.cpp
database-redis.cpp
player.cpp
test.cpp
sha1.cpp
@ -393,7 +413,7 @@ if(WIN32)
set(CMAKE_RC_COMPILER "windres.exe")
endif()
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}
-o ${CMAKE_CURRENT_BINARY_DIR}/winresource_rc.o
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
@ -424,11 +444,9 @@ set(minetest_SRCS
chat.cpp
hud.cpp
guiKeyChangeMenu.cpp
guiMessageMenu.cpp
guiTextInputMenu.cpp
guiFormSpecMenu.cpp
guiTable.cpp
guiPauseMenu.cpp
guiPasswordChange.cpp
guiVolumeChange.cpp
guiDeathScreen.cpp
@ -535,6 +553,9 @@ if(BUILD_CLIENT)
if (USE_LEVELDB)
target_link_libraries(${PROJECT_NAME} ${LEVELDB_LIBRARY})
endif(USE_LEVELDB)
if (USE_REDIS)
target_link_libraries(${PROJECT_NAME} ${REDIS_LIBRARY})
endif(USE_REDIS)
endif(BUILD_CLIENT)
if(BUILD_SERVER)
@ -552,6 +573,9 @@ if(BUILD_SERVER)
if (USE_LEVELDB)
target_link_libraries(${PROJECT_NAME}server ${LEVELDB_LIBRARY})
endif(USE_LEVELDB)
if (USE_REDIS)
target_link_libraries(${PROJECT_NAME}server ${REDIS_LIBRARY})
endif(USE_REDIS)
if(USE_CURL)
target_link_libraries(
${PROJECT_NAME}server

View File

@ -203,54 +203,3 @@ u8 BiomeDefManager::getBiomeIdByName(const char *name) {
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
#include "nodedef.h"
Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control,
IGameDef *gamedef):
m_smgr(smgr),
m_playernode(NULL),
m_headnode(NULL),
m_cameranode(NULL),
@ -248,7 +249,8 @@ void Camera::step(f32 dtime)
}
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
// Smooth the movement when walking up stairs
@ -276,7 +278,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
// Fall bobbing animation
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
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");
}
// 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
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->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_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 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;
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
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*
(((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*
(((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
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);
// *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
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 <ICameraSceneNode.h>
#include "client.h"
class LocalPlayer;
struct MapDrawControl;
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
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.
// busytime is used to adjust the viewing range.
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
void updateViewingRange(f32 frametime_in, f32 busytime_in);
@ -131,8 +136,7 @@ public:
void drawWieldedTool();
private:
// Scene manager and nodes
scene::ISceneManager* m_smgr;
// Nodes
scene::ISceneNode* m_playernode;
scene::ISceneNode* m_headnode;
scene::ICameraSceneNode* m_cameranode;

View File

@ -3395,7 +3395,7 @@ inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const short ri
template <typename TAlloc>
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;
return ret;
}
@ -3415,7 +3415,7 @@ inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const unsigned
template <typename TAlloc>
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;
return ret;
}
@ -3435,7 +3435,7 @@ inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const int righ
template <typename TAlloc>
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;
return ret;
}
@ -3455,7 +3455,7 @@ inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const unsigned
template <typename TAlloc>
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;
return ret;
}
@ -3475,7 +3475,7 @@ inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const long rig
template <typename TAlloc>
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;
return ret;
}
@ -3495,7 +3495,7 @@ inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const unsigned
template <typename TAlloc>
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;
return ret;
}
@ -3515,7 +3515,7 @@ inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const float ri
template <typename TAlloc>
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;
return ret;
}
@ -3535,7 +3535,7 @@ inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const double r
template <typename TAlloc>
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;
return ret;
}

View File

@ -47,6 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serialization.h"
#include "util/serialize.h"
#include "config.h"
#include "cmake_config_githash.h"
#include "util/directiontables.h"
#include "util/pointedthing.h"
#include "version.h"
@ -168,6 +169,8 @@ void * MeshUpdateThread::Thread()
BEGIN_DEBUG_EXCEPTION_HANDLER
porting::setThreadName("MeshUpdateThread");
while(!StopRequested())
{
QueuedMeshUpdate *q = m_queue_in.pop();
@ -252,7 +255,8 @@ Client::Client(
m_last_time_of_day_f(-1),
m_time_of_day_update_timer(0),
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_delete_unused_sectors_timer = 0.0;
@ -325,17 +329,6 @@ void Client::connect(Address 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)
{
DSTACK(__FUNCTION_NAME);
@ -372,9 +365,6 @@ void Client::step(float dtime)
m_packetcounter.clear();
}
}
// Get connection status
bool connected = connectedAndInitialized();
#if 0
{
@ -467,7 +457,7 @@ void Client::step(float dtime)
}
#endif
if(connected == false)
if(m_state == LC_Created)
{
float &counter = m_connection_reinit_timer;
counter -= dtime;
@ -632,7 +622,7 @@ void Client::step(float dtime)
{
counter = 0.0;
// 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;
}
}
@ -643,7 +633,7 @@ void Client::step(float dtime)
{
float &counter = m_playerpos_send_timer;
counter += dtime;
if(counter >= m_recommended_send_interval)
if((m_state == LC_Ready) && (counter >= m_recommended_send_interval))
{
counter = 0.0;
sendPlayerPos();
@ -1051,6 +1041,8 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
// Send as reliable
m_con.Send(PEER_ID_SERVER, 1, reply, true);
m_state = LC_Init;
return;
}
@ -1222,7 +1214,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
m_time_of_day_set = true;
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
<<" 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;
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
{
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)
{
if(connectedAndInitialized() == false){
if(m_state != LC_Ready){
infostream<<"Client::interact() "
"cancelled (not connected)"
<<std::endl;
@ -2072,8 +2089,8 @@ void Client::sendChatMessage(const std::wstring &message)
Send(0, data, true);
}
void Client::sendChangePassword(const std::wstring oldpassword,
const std::wstring newpassword)
void Client::sendChangePassword(const std::wstring &oldpassword,
const std::wstring &newpassword)
{
Player *player = m_env.getLocalPlayer();
if(player == NULL)
@ -2152,6 +2169,27 @@ void Client::sendRespawn()
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()
{
LocalPlayer *myplayer = m_env.getLocalPlayer();
@ -2650,16 +2688,14 @@ void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font)
infostream<<"- Starting mesh update thread"<<std::endl;
m_mesh_update_thread.Start();
m_state = LC_Ready;
sendReady();
infostream<<"Client::afterContentReceived() done"<<std::endl;
}
float Client::getRTT(void)
{
try{
return m_con.GetPeerAvgRTT(PEER_ID_SERVER);
} catch(con::PeerNotFoundException &e){
return 1337;
}
return m_con.getPeerStat(PEER_ID_SERVER,con::AVG_RTT);
}
// IGameDef interface

View File

@ -57,6 +57,12 @@ struct QueuedMeshUpdate
~QueuedMeshUpdate();
};
enum LocalClientState {
LC_Created,
LC_Init,
LC_Ready
};
/*
A thread-safe queue of mesh update tasks
*/
@ -319,14 +325,7 @@ public:
calling this, as it is sent in the initialization.
*/
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
long as this is not called. (eg. Players)
@ -349,11 +348,12 @@ public:
const std::map<std::string, std::string> &fields);
void sendInventoryAction(InventoryAction *a);
void sendChatMessage(const std::wstring &message);
void sendChangePassword(const std::wstring oldpassword,
const std::wstring newpassword);
void sendChangePassword(const std::wstring &oldpassword,
const std::wstring &newpassword);
void sendDamage(u8 damage);
void sendBreath(u16 breath);
void sendRespawn();
void sendReady();
ClientEnvironment& getEnv()
{ return m_env; }
@ -454,6 +454,8 @@ public:
// Send a notification that no conventional media transfer is needed
void received_media();
LocalClientState getState() { return m_state; }
private:
// Virtual methods from con::PeerHandler
@ -537,6 +539,9 @@ private:
// Storage for mesh data for creating multiple instances of the same mesh
std::map<std::string, std::string> m_mesh_data;
// own state
LocalClientState m_state;
};
#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.
*/
#include <sstream>
#include "clientiface.h"
#include "player.h"
#include "settings.h"
@ -140,7 +142,8 @@ void RemoteClient::GetNextBlocks(
*/
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");
// Don't loop very much at a time
@ -214,7 +217,7 @@ void RemoteClient::GetNextBlocks(
generate = false;*/
// 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;
}
@ -396,10 +399,11 @@ void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
void RemoteClient::notifyEvent(ClientStateEvent event)
{
std::ostringstream myerror;
switch (m_state)
{
case Invalid:
assert("State update for client in invalid state" != 0);
//intentionally do nothing
break;
case Created:
@ -419,7 +423,8 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
/* GotInit2 SetDefinitionsSent SetMediaSent */
default:
assert("Invalid client state transition!" == 0);
myerror << "Created: Invalid client state transition! " << event;
throw ClientStateError(myerror.str());
}
break;
@ -445,7 +450,8 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
/* Init SetDefinitionsSent SetMediaSent */
default:
assert("Invalid client state transition!" == 0);
myerror << "InitSent: Invalid client state transition! " << event;
throw ClientStateError(myerror.str());
}
break;
@ -466,14 +472,15 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
/* Init GotInit2 SetMediaSent */
default:
assert("Invalid client state transition!" == 0);
myerror << "InitDone: Invalid client state transition! " << event;
throw ClientStateError(myerror.str());
}
break;
case DefinitionsSent:
switch(event)
{
case SetMediaSent:
case SetClientReady:
m_state = Active;
break;
@ -487,7 +494,8 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
/* Init GotInit2 SetDefinitionsSent */
default:
assert("Invalid client state transition!" == 0);
myerror << "DefinitionsSent: Invalid client state transition! " << event;
throw ClientStateError(myerror.str());
}
break;
@ -504,7 +512,8 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
/* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
default:
assert("Invalid client state transition!" == 0);
myerror << "Active: Invalid client state transition! " << event;
throw ClientStateError(myerror.str());
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)
:
m_con(con),
@ -748,7 +762,7 @@ void ClientInterface::event(u16 peer_id, ClientStateEvent event)
n->second->notifyEvent(event);
}
if ((event == SetMediaSent) || (event == Disconnect) || (event == SetDenied))
if ((event == SetClientReady) || (event == Disconnect) || (event == SetDenied))
{
UpdatePlayerList();
}
@ -762,9 +776,24 @@ u16 ClientInterface::getProtocolVersion(u16 peer_id)
std::map<u16, RemoteClient*>::iterator n;
n = m_clients.find(peer_id);
// No client to deliver event
// No client to get version
if (n == m_clients.end())
return 0;
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 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 {
class Connection;
}
#define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
enum ClientState
{
Invalid,
@ -50,13 +155,24 @@ enum ClientState
Active
};
static const char* statenames[] = {
"Invalid",
"Disconnecting",
"Denied",
"Created",
"InitSent",
"InitDone",
"DefinitionsSent",
"Active"
};
enum ClientStateEvent
{
Init,
GotInit2,
SetDenied,
SetDefinitionsSent,
SetMediaSent,
SetClientReady,
Disconnect
};
@ -105,9 +221,13 @@ public:
m_nearest_unsent_d(0),
m_nearest_unsent_reset_timer(0.0),
m_excess_gotblocks(0),
m_nothing_to_send_counter(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()
@ -178,6 +298,23 @@ public:
void confirmSerializationVersion()
{ 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:
// Version is stored in here after INIT before INIT2
u8 m_pending_serialization_version;
@ -219,9 +356,26 @@ private:
u32 m_excess_gotblocks;
// CPU usage optimization
u32 m_nothing_to_send_counter;
float m_nothing_to_send_pause_timer;
/*
name of player using this client
*/
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 {
@ -268,6 +422,9 @@ public:
/* get protocol version of client */
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 */
void event(u16 peer_id, ClientStateEvent event);
@ -275,6 +432,11 @@ public:
void setEnv(ServerEnvironment* env)
{ assert(m_env == 0); m_env = env; }
static std::string state2Name(ClientState state) {
assert((int) state < ARRAYSIZE(statenames));
return statenames[state];
}
protected:
//TODO find way to avoid this functions
void Lock()

View File

@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapblock.h"
#include "profiler.h"
#include "settings.h"
#include "camera.h" // CameraModes
#include "util/mathconstants.h"
#include <algorithm>
@ -866,13 +867,16 @@ void ClientMap::renderPostFx()
v3f camera_position = m_camera_position;
m_camera_mutex.Unlock();
LocalPlayer *player = m_client->getEnv().getLocalPlayer();
MapNode n = getNodeNoEx(floatToInt(camera_position, BS));
// - If the player is in a solid node, make everything black.
// - 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);
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);
}

View File

@ -55,7 +55,7 @@ public:
virtual void updateLight(u8 light_at_pos){}
virtual v3s16 getLightPosition(){return v3s16(0,0,0);}
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 v3f getPosition(){return v3f(0,0,0);}
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
automatic_face_movement_dir and automatic_face_movement_dir_offset
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
#define SERVER_PROTOCOL_VERSION_MIN 13
@ -129,7 +133,7 @@ enum ToClientCommand
[0] u16 TOSERVER_INIT
[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)
[20] f1000 recommended send interval (in seconds) (new as of 14)
@ -526,6 +530,23 @@ enum ToClientCommand
u8 do_override (boolean)
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
@ -755,6 +776,16 @@ enum ToServerCommand
u16 command
u16 breath
*/
TOSERVER_CLIENT_READY = 0x43,
/*
u8 major
u8 minor
u8 patch
u8 reserved
u16 len
u8[len] full_version_string
*/
};
#endif

View File

@ -76,7 +76,6 @@ private:
video::SMaterial m_material;
core::aabbox3d<f32> m_box;
float m_cloud_y;
float m_brightness;
video::SColorf m_color;
u32 m_seed;
v2f m_camera_pos;

View File

@ -14,6 +14,7 @@
#define CMAKE_STATIC_SHAREDIR "@SHAREDIR@"
#define CMAKE_USE_LEVELDB @USE_LEVELDB@
#define CMAKE_USE_LUAJIT @USE_LUAJIT@
#define CMAKE_USE_REDIS @USE_REDIS@
#define CMAKE_VERSION_MAJOR @VERSION_MAJOR@
#define CMAKE_VERSION_MINOR @VERSION_MINOR@
#define CMAKE_VERSION_PATCH @VERSION_PATCH@

View File

@ -9,12 +9,28 @@
#define PROJECT_NAME "Minetest"
#define RUN_IN_PLACE 0
#define USE_GETTEXT 0
#define USE_SOUND 0
#define USE_CURL 0
#ifndef USE_SOUND
#define USE_SOUND 0
#endif
#ifndef USE_CURL
#define USE_CURL 0
#endif
#define USE_FREETYPE 0
#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
#include "cmake_config.h"
@ -36,6 +52,8 @@
#define USE_LEVELDB CMAKE_USE_LEVELDB
#undef USE_LUAJIT
#define USE_LUAJIT CMAKE_USE_LUAJIT
#undef USE_REDIS
#define USE_REDIS CMAKE_USE_REDIS
#undef VERSION_MAJOR
#define VERSION_MAJOR CMAKE_VERSION_MAJOR
#undef VERSION_MINOR

View File

@ -212,7 +212,7 @@ SharedBuffer<u8> makeReliablePacket(
ReliablePacketBuffer
*/
ReliablePacketBuffer::ReliablePacketBuffer(): m_list_size(0),writeptr(0) {}
ReliablePacketBuffer::ReliablePacketBuffer(): m_list_size(0) {}
void ReliablePacketBuffer::print()
{
@ -1170,7 +1170,7 @@ void UDPPeer::RunCommandQueues(
channels[i].queued_commands.push_front(c);
}
}
catch (ItemNotFoundException e) {
catch (ItemNotFoundException &e) {
// intentionally empty
}
}
@ -1227,6 +1227,8 @@ void * ConnectionSendThread::Thread()
PROFILE(std::stringstream ThreadIdentifier);
PROFILE(ThreadIdentifier << "ConnectionSend: [" << m_connection->getDesc() << "]");
porting::setThreadName("ConnectionSend");
/* if stop is requested don't stop immediately but try to send all */
/* packets first */
while(!StopRequested() || packetsQueued()) {
@ -1939,8 +1941,7 @@ void ConnectionSendThread::sendAsPacket(u16 peer_id, u8 channelnum,
ConnectionReceiveThread::ConnectionReceiveThread(Connection* parent,
unsigned int max_packet_size) :
m_connection(parent),
m_max_packet_size(max_packet_size)
m_connection(parent)
{
}
@ -1955,6 +1956,8 @@ void * ConnectionReceiveThread::Thread()
PROFILE(std::stringstream ThreadIdentifier);
PROFILE(ThreadIdentifier << "ConnectionReceive: [" << m_connection->getDesc() << "]");
porting::setThreadName("ConnectionReceive");
#ifdef DEBUG_CONNECTION_KBPS
u32 curtime = porting::getTimeMs();
u32 lasttime = curtime;
@ -2067,7 +2070,7 @@ void ConnectionReceiveThread::receive()
m_connection->putEvent(e);
}
}
catch(ProcessedSilentlyException e) {
catch(ProcessedSilentlyException &e) {
/* try reading again */
}
}
@ -2875,11 +2878,11 @@ Address Connection::GetPeerAddress(u16 peer_id)
return peer_address;
}
float Connection::GetPeerAvgRTT(u16 peer_id)
float Connection::getPeerStat(u16 peer_id, rtt_stat_type type)
{
PeerHelper peer = getPeerNoEx(peer_id);
if (!peer) return -1;
return peer->getStat(AVG_RTT);
return peer->getStat(type);
}
u16 Connection::createPeer(Address& sender, MTProtocols protocol, int fd)

View File

@ -339,13 +339,11 @@ private:
RPBSearchResult findPacket(u16 seqnum);
std::list<BufferedPacket> m_list;
u16 m_list_size;
u32 m_list_size;
u16 m_oldest_non_answered_ack;
JMutex m_list_mutex;
unsigned int writeptr;
};
/*
@ -975,7 +973,6 @@ private:
Connection* m_connection;
unsigned int m_max_packet_size;
};
class Connection
@ -1004,7 +1001,7 @@ public:
void Send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
u16 GetPeerID(){ return m_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 std::string getDesc();
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
#define PLAYER_MAX_HP 20
/*
Environmental condition constants
*/
#define HEAT_UNDEFINED (-0x7fff-1)
#define HUMIDITY_UNDEFINED (-0x7fff-1)
#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<<")"
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) {
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 "map.h"
#include "main.h" // g_settings
#include "camera.h" // CameraModes
#include <IMeshManipulator.h>
#include <IAnimatedMeshSceneNode.h>
#include <IBoneSceneNode.h>
@ -165,7 +166,7 @@ public:
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr);
void removeFromScene();
void removeFromScene(bool permanent);
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
@ -235,7 +236,7 @@ void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
updateNodePos();
}
void TestCAO::removeFromScene()
void TestCAO::removeFromScene(bool permanent)
{
if(m_node == NULL)
return;
@ -309,7 +310,7 @@ public:
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr);
void removeFromScene();
void removeFromScene(bool permanent);
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
@ -411,7 +412,7 @@ void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
updateTexture();
}
void ItemCAO::removeFromScene()
void ItemCAO::removeFromScene(bool permanent)
{
if(m_node == NULL)
return;
@ -580,7 +581,7 @@ private:
v2s16 m_tx_basepos;
bool m_initial_tx_basepos_set;
bool m_tx_select_horiz_by_yawpitch;
v2f m_animation_range;
v2s32 m_animation_range;
int m_animation_speed;
int m_animation_blend;
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_initial_tx_basepos_set(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_blend(0),
m_bone_position(std::map<std::string, core::vector2d<v3f> >()),
@ -647,7 +648,6 @@ public:
bool getCollisionBox(aabb3f *toset) {
if (m_prop.physical) {
aabb3f retval;
//update collision box
toset->MinEdge = m_prop.collisionbox.MinEdge * BS;
toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS;
@ -858,7 +858,7 @@ public:
m_visuals_expired = false;
if(!m_prop.is_visible || m_is_local_player)
if(!m_prop.is_visible)
return;
//video::IVideoDriver* driver = smgr->getVideoDriver();
@ -1078,6 +1078,76 @@ public:
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){
m_visuals_expired = false;
@ -1440,8 +1510,7 @@ public:
{
if(m_animated_meshnode == NULL)
return;
m_animated_meshnode->setFrameLoop((int)m_animation_range.X, (int)m_animation_range.Y);
m_animated_meshnode->setFrameLoop(m_animation_range.X, m_animation_range.Y);
m_animated_meshnode->setAnimationSpeed(m_animation_speed);
m_animated_meshnode->setTransitionTime(m_animation_blend);
}
@ -1701,6 +1770,7 @@ public:
bool sneak = !readU8(is);
bool sneak_glitch = !readU8(is);
if(m_is_local_player)
{
LocalPlayer *player = m_env->getLocalPlayer();
@ -1713,11 +1783,31 @@ public:
}
else if(cmd == GENERIC_CMD_SET_ANIMATION)
{
m_animation_range = readV2F1000(is);
m_animation_speed = readF1000(is);
m_animation_blend = readF1000(is);
updateAnimation();
// TODO: change frames send as v2s32 value
v2f range = readV2F1000(is);
if (!m_is_local_player) {
m_animation_range = v2s32((s32)range.X, (s32)range.Y);
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)
{

View File

@ -219,7 +219,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
if(ntop.getContent() == c_flowing || ntop.getContent() == c_source)
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));
/*
@ -389,10 +389,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
}
// Use the light of the node on top if possible
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)
else
l = getInteriorLight(n, 0, data);
l = getInteriorLight(n, 0, nodedef);
video::SColor c = MapBlock_LightColor(f.alpha, l, decode_light(f.light_source));
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);
u16 l = getInteriorLight(n, 1, data);
u16 l = getInteriorLight(n, 1, nodedef);
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
for(u32 j=0; j<6; j++)
@ -758,7 +758,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
TileSpec tiles[2];
tiles[0] = getNodeTile(n, p, dirs[0], 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));
v3f pos = intToFloat(p, BS);
static const float a=BS/2;
@ -876,7 +876,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
TileSpec tile_leaves = 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));
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_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));
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_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));
float d = (float)BS/16;
@ -993,7 +993,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
TileSpec tile = getNodeTileN(n, p, 0, data);
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));
float s = BS/2*f.visual_scale;
@ -1045,7 +1045,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
texturestring_rot,
&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));
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_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));
float d = (float)BS/64;
@ -1333,7 +1333,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
};
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));
v3f pos = intToFloat(p, BS);

View File

@ -191,7 +191,7 @@ public:
}
ItemSAO(ServerEnvironment *env, v3f pos,
const std::string itemstring):
const std::string &itemstring):
ServerActiveObject(env, pos),
m_itemstring(itemstring),
m_itemstring_changed(false),
@ -350,7 +350,7 @@ private:
ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), "");
ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
const std::string itemstring)
const std::string &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"
ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
const std::string itemstring);
const std::string &itemstring);
/*
LuaEntitySAO needs some internals exposed.
@ -37,7 +37,7 @@ class LuaEntitySAO : public ServerActiveObject
{
public:
LuaEntitySAO(ServerEnvironment *env, v3f pos,
const std::string &name, const std::string &state);
const std::string &name, const std::string &state);
~LuaEntitySAO();
u8 getType() const
{ 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 "porting.h"
Json::Value fetchJsonValue(const std::string url,
struct curl_slist *chunk) {
Json::Value fetchJsonValue(const std::string &url,
struct curl_slist *chunk) {
#if USE_CURL
HTTPFetchRequest fetchrequest;

View File

@ -28,7 +28,7 @@ struct ModStoreModDetails;
std::vector<ModStoreMod> readModStoreList(Json::Value& modlist);
ModStoreModDetails readModStoreModDetails(Json::Value& details);
Json::Value fetchJsonValue(const std::string url,
struct curl_slist *chunk);
Json::Value fetchJsonValue(const std::string &url,
struct curl_slist *chunk);
#endif

View File

@ -151,7 +151,7 @@ MapBlock* Database_Dummy::loadBlock(v3s16 blockpos)
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);
//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
#define DATABASE_DUMMY_HEADER
#include "database.h"
#include <map>
#include <string>
#include "database.h"
#include "irrlichttypes.h"
class ServerMap;
@ -39,6 +40,6 @@ public:
~Database_Dummy();
private:
ServerMap *srvmap;
std::map<unsigned long long, std::string> m_database;
std::map<u64, std::string> m_database;
};
#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
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
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.
*/
#ifndef GUIMESSAGEMENU_HEADER
#define GUIMESSAGEMENU_HEADER
#ifndef DATABASE_REDIS_HEADER
#define DATABASE_REDIS_HEADER
#include "irrlichttypes_extrabloated.h"
#include "modalMenu.h"
#include "config.h"
#if USE_REDIS
#include "database.h"
#include <hiredis.h>
#include <string>
class GUIMessageMenu : public GUIModalMenu
class ServerMap;
class Database_Redis : public Database
{
public:
GUIMessageMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr,
std::wstring message_text);
~GUIMessageMenu();
void removeChildren();
/*
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;
}
Database_Redis(ServerMap *map, std::string savedir);
virtual void beginSave();
virtual void endSave();
virtual void saveBlock(MapBlock *block);
virtual MapBlock* loadBlock(v3s16 blockpos);
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
virtual int Initialized(void);
~Database_Redis();
private:
std::wstring m_message_text;
bool m_status;
ServerMap *srvmap;
redisContext *ctx;
std::string hash;
};
#endif
#endif

View File

@ -20,33 +20,29 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "database.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;
else
return i - 2*max_positive;
} else {
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 i % mod;
return mod - ((-i) % mod);
return (((u64) pos.Z) << 24) +
(((u64) pos.Y) << 12) +
((u64) pos.X);
}
long long Database::getBlockAsInteger(const v3s16 pos) {
return (unsigned long long)pos.Z*16777216 +
(unsigned long long)pos.Y*4096 +
(unsigned long long)pos.X;
v3s16 Database::getIntegerAsBlock(const s64 i) const
{
v3s16 pos;
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 "irr_v3d.h"
#include "irrlichttypes.h"
class MapBlock;
@ -33,8 +34,8 @@ public:
virtual void saveBlock(MapBlock *block)=0;
virtual MapBlock* loadBlock(v3s16 blockpos)=0;
long long getBlockAsInteger(const v3s16 pos);
v3s16 getIntegerAsBlock(long long i);
s64 getBlockAsInteger(const v3s16 pos) const;
v3s16 getIntegerAsBlock(const s64 i) const;
virtual void listAllLoadableBlocks(std::list<v3s16> &dst)=0;
virtual int Initialized(void)=0;
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_debug", "KEY_F5");
settings->setDefault("keymap_toggle_profiler", "KEY_F6");
settings->setDefault("keymap_camera_mode", "KEY_F7");
settings->setDefault("keymap_increase_viewing_range_min", "+");
settings->setDefault("keymap_decrease_viewing_range_min", "-");
settings->setDefault("anaglyph", "false");
@ -130,8 +131,11 @@ void set_default_settings(Settings *settings)
settings->setDefault("preload_item_visuals", "true");
settings->setDefault("enable_bumpmapping", "false");
settings->setDefault("enable_parallax_occlusion", "false");
settings->setDefault("parallax_occlusion_scale", "0.08");
settings->setDefault("parallax_occlusion_bias", "0.04");
settings->setDefault("generate_normalmaps", "false");
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("water_wave_height", "1.0");
settings->setDefault("water_wave_length", "20.0");
@ -240,13 +244,8 @@ void set_default_settings(Settings *settings)
settings->setDefault("movement_gravity", "9.81");
//liquid stuff
settings->setDefault("liquid_finite", "false");
settings->setDefault("liquid_loop_max", "10000");
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
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 p;
u8 flags;
u8 flags = 0;
map = (ServerMap *)&(m_server->m_env->getMap());
emerge = m_server->m_emerge;
mapgen = emerge->mapgen[id];
enable_mapgen_debug_info = emerge->mapgen_debug_info;
porting::setThreadName("EmergeThread");
while (!StopRequested())
try {
if (!popBlockEmerge(&p, &flags)) {

View File

@ -85,19 +85,17 @@ void Environment::addPlayer(Player *player)
void Environment::removePlayer(u16 peer_id)
{
DSTACK(__FUNCTION_NAME);
re_search:
for(std::list<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i)
i != m_players.end();)
{
Player *player = *i;
if(player->peer_id != peer_id)
continue;
delete player;
m_players.erase(i);
// See if there is an another one
// (shouldn't be, but just to be sure)
goto re_search;
if(player->peer_id == peer_id) {
delete player;
i = m_players.erase(i);
} else {
++i;
}
}
}
@ -316,7 +314,6 @@ ServerEnvironment::ServerEnvironment(ServerMap *map,
m_map(map),
m_script(scriptIface),
m_gamedef(gamedef),
m_random_spawn_timer(3),
m_send_recommended_timer(0),
m_active_block_interval_overload_skip(0),
m_game_time(0),
@ -324,7 +321,6 @@ ServerEnvironment::ServerEnvironment(ServerMap *map,
m_recommended_send_interval(0.1),
m_max_lag_estimate(0.1)
{
m_use_weather = g_settings->getBool("weather");
}
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)
{
if(m_aabms.empty())
@ -719,6 +743,10 @@ public:
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;
for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
for(p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++)
@ -762,33 +790,16 @@ public:
}
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
i->abm->trigger(m_env, p, n);
i->abm->trigger(m_env, p, n,
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;
// 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)
{
assert(object);
m_added_objects++;
u16 id = addActiveObjectRaw(object, true, 0);
return id;
}
@ -2381,7 +2393,7 @@ void ClientEnvironment::step(float dtime)
if(player->isLocal() == false)
{
// 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;
}
// counter used internally when triggering ABMs
u32 m_added_objects;
protected:
// peer_ids in here should be unique, except that there may be many 0s
std::list<Player*> m_players;
@ -118,6 +121,7 @@ protected:
// Overriding the day-night ratio is useful for custom sky visuals
bool m_enable_day_night_ratio_override;
u32 m_day_night_ratio_override;
};
/*
@ -310,9 +314,6 @@ public:
void reportMaxLagEstimate(float f) { m_max_lag_estimate = f; }
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; };
private:
@ -370,7 +371,6 @@ private:
// Outgoing network message buffer for active objects
std::list<ActiveObjectMessage> m_active_object_messages;
// Some timers
float m_random_spawn_timer; // used for experimental code
float m_send_recommended_timer;
IntervalLimiter m_object_management_interval;
// 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
{
public:
BaseException(const std::string s) throw()
BaseException(const std::string &s) throw()
{
m_s = s;
}
@ -42,78 +42,83 @@ protected:
class AsyncQueuedException : public BaseException {
public:
AsyncQueuedException(std::string s): BaseException(s) {}
AsyncQueuedException(const std::string &s): BaseException(s) {}
};
class NotImplementedException : public BaseException {
public:
NotImplementedException(std::string s): BaseException(s) {}
NotImplementedException(const std::string &s): BaseException(s) {}
};
class AlreadyExistsException : public BaseException {
public:
AlreadyExistsException(std::string s): BaseException(s) {}
AlreadyExistsException(const std::string &s): BaseException(s) {}
};
class VersionMismatchException : public BaseException {
public:
VersionMismatchException(std::string s): BaseException(s) {}
VersionMismatchException(const std::string &s): BaseException(s) {}
};
class FileNotGoodException : public BaseException {
public:
FileNotGoodException(std::string s): BaseException(s) {}
FileNotGoodException(const std::string &s): BaseException(s) {}
};
class SerializationError : public BaseException {
public:
SerializationError(std::string s): BaseException(s) {}
SerializationError(const std::string &s): BaseException(s) {}
};
class LoadError : public BaseException {
public:
LoadError(std::string s): BaseException(s) {}
LoadError(const std::string &s): BaseException(s) {}
};
class ContainerFullException : public BaseException {
public:
ContainerFullException(std::string s): BaseException(s) {}
ContainerFullException(const std::string &s): BaseException(s) {}
};
class SettingNotFoundException : public BaseException {
public:
SettingNotFoundException(std::string s): BaseException(s) {}
SettingNotFoundException(const std::string &s): BaseException(s) {}
};
class InvalidFilenameException : public BaseException {
public:
InvalidFilenameException(std::string s): BaseException(s) {}
InvalidFilenameException(const std::string &s): BaseException(s) {}
};
class ProcessingLimitException : public BaseException {
public:
ProcessingLimitException(std::string s): BaseException(s) {}
ProcessingLimitException(const std::string &s): BaseException(s) {}
};
class CommandLineError : public BaseException {
public:
CommandLineError(std::string s): BaseException(s) {}
CommandLineError(const std::string &s): BaseException(s) {}
};
class ItemNotFoundException : public BaseException {
public:
ItemNotFoundException(std::string s): BaseException(s) {}
ItemNotFoundException(const std::string &s): BaseException(s) {}
};
class ServerError : public BaseException {
public:
ServerError(std::string s): BaseException(s) {}
ServerError(const std::string &s): BaseException(s) {}
};
// Only used on Windows (SEH)
class FatalSystemException : public BaseException {
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():
BaseException("Somebody tried to get/set something in a nonexistent position.")
{}
InvalidPositionException(std::string s):
InvalidPositionException(const std::string &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 "client.h"
#include "server.h"
#include "guiPauseMenu.h"
#include "guiPasswordChange.h"
#include "guiVolumeChange.h"
#include "guiFormSpecMenu.h"
@ -75,24 +74,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
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
{
TextDestNodeMetadata(v3s16 p, Client *client)
@ -136,12 +117,81 @@ struct TextDestPlayerInventory : public TextDest
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;
}
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;
std::string m_formname;
};
/* Respawn menu callback */
@ -224,13 +274,9 @@ inline bool isPointableNode(const MapNode& n,
Find what the player is pointing at
*/
PointedThing getPointedThing(Client *client, v3f player_position,
v3f camera_direction, v3f camera_position,
core::line3d<f32> shootline, f32 d,
bool liquids_pointable,
bool look_for_object,
v3s16 camera_offset,
std::vector<aabb3f> &hilightboxes,
ClientActiveObject *&selected_object)
v3f camera_direction, v3f camera_position, core::line3d<f32> shootline,
f32 d, bool liquids_pointable, bool look_for_object, v3s16 camera_offset,
std::vector<aabb3f> &hilightboxes, ClientActiveObject *&selected_object)
{
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.
*/
/*gui::IGUIStaticText **/
void draw_load_screen(const std::wstring &text,
IrrlichtDevice* device, gui::IGUIFont* font,
float dtime=0 ,int percent=0, bool clouds=true)
void draw_load_screen(const std::wstring &text, IrrlichtDevice* device,
gui::IGUIFont* font, float dtime=0 ,int percent=0, bool clouds=true)
{
video::IVideoDriver* driver = device->getVideoDriver();
v2u32 screensize = driver->getScreenSize();
@ -430,8 +475,8 @@ void draw_load_screen(const std::wstring &text,
/* Profiler display */
void update_profiler_gui(gui::IGUIStaticText *guitext_profiler,
gui::IGUIFont *font, u32 text_height,
u32 show_profiler, u32 show_profiler_max)
gui::IGUIFont *font, u32 text_height, u32 show_profiler,
u32 show_profiler_max)
{
if(show_profiler == 0)
{
@ -818,14 +863,17 @@ public:
services->setPixelShaderConstant("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 layer2 = 2;
// before 1.8 there isn't a "integer interface", only float
#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("useNormalmap" , (irr::f32*)&layer2, 1);
#else
services->setPixelShaderConstant("baseTexture" , (irr::s32*)&layer0, 1);
services->setPixelShaderConstant("normalTexture" , (irr::s32*)&layer1, 1);
services->setPixelShaderConstant("useNormalmap" , (irr::s32*)&layer2, 1);
#endif
@ -833,8 +881,7 @@ public:
};
bool nodePlacementPrediction(Client &client,
const ItemDefinition &playeritem_def,
v3s16 nodepos, v3s16 neighbourpos)
const ItemDefinition &playeritem_def, v3s16 nodepos, v3s16 neighbourpos)
{
std::string prediction = playeritem_def.node_placement_prediction;
INodeDefManager *nodedef = client.ndef();
@ -930,26 +977,98 @@ bool nodePlacementPrediction(Client &client,
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(
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
)
/* Create menu */
/* Note: FormspecFormSource and LocalFormspecHandler
* are deleted by guiFormSpecMenu */
current_formspec = new FormspecFormSource(formspec,&current_formspec);
current_textdest = new LocalFormspecHandler("MT_CHAT_MENU",client);
GUIFormSpecMenu *menu =
new GUIFormSpecMenu(device, guiroot, -1,
&g_menumgr,
NULL, NULL, tsrc);
menu->doPause = false;
menu->setFormSource(current_formspec);
menu->setTextDest(current_textdest);
menu->drop();
}
/******************************************************************************/
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;
TextDestPlayerInventory* current_textdest = 0;
TextDest* current_textdest = 0;
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
@ -1028,27 +1147,34 @@ void the_game(
draw_load_screen(text, device, font,0,25);
delete[] text;
infostream<<"Creating server"<<std::endl;
server = new Server(map_dir, gamespec,
simple_singleplayer_mode);
std::string bind_str = g_settings->get("bind_address");
Address bind_addr(0,0,0,0, port);
if (bind_str != "")
{
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);
}
}
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);
}
@ -1074,31 +1200,33 @@ void the_game(
delete[] text;
}
Address connect_address(0,0,0,0, port);
try{
if(address == "")
{
try {
connect_address.Resolve(address.c_str());
if (connect_address.isZero()) { // i.e. INADDR_ANY, IN6ADDR_ANY
//connect_address.Resolve("localhost");
if(g_settings->getBool("enable_ipv6") && g_settings->getBool("ipv6_server"))
{
if (connect_address.isIPv6()) {
IPv6AddressBytes addr_bytes;
addr_bytes.bytes[15] = 1;
connect_address.setAddress(&addr_bytes);
}
else
{
} else {
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());
errorstream<<wide_to_narrow(error_message)<<std::endl;
// Break out of client scope
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
@ -1147,7 +1275,7 @@ void the_game(
server->step(dtime);
// End condition
if(client.connectedAndInitialized()){
if(client.getState() == LC_Init){
could_connect = true;
break;
}
@ -1254,7 +1382,7 @@ void the_game(
errorstream<<wide_to_narrow(error_message)<<std::endl;
break;
}
if(!client.connectedAndInitialized()){
if(client.getState() < LC_Init){
error_message = L"Client disconnected";
errorstream<<wide_to_narrow(error_message)<<std::endl;
break;
@ -1342,6 +1470,8 @@ void the_game(
f32 camera_yaw = 0; // "right/left"
f32 camera_pitch = 0; // "up/down"
int current_camera_mode = CAMERA_MODE_FIRST; // start in first-person view
/*
Clouds
*/
@ -1512,8 +1642,6 @@ void the_game(
Hud hud(driver, smgr, guienv, font, text_height,
gamedef, player, &local_inventory);
bool use_weather = g_settings->getBool("weather");
core::stringw str = L"Minetest [";
str += driver->getName();
str += "]";
@ -1781,6 +1909,7 @@ void the_game(
PlayerInventoryFormSource *src = new PlayerInventoryFormSource(&client);
assert(src);
menu->doPause = false;
menu->setFormSpec(src->getForm(), inventoryloc);
menu->setFormSource(src);
menu->setTextDest(new TextDestPlayerInventory(&client));
@ -1788,33 +1917,16 @@ void the_game(
}
else if(input->wasKeyDown(EscapeKey))
{
infostream<<"the_game: "
<<"Launching pause menu"<<std::endl;
// 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);
show_pause_menu(current_formspec, current_textdest, tsrc, device,
simple_singleplayer_mode);
}
else if(input->wasKeyDown(getKeySetting("keymap_chat")))
{
TextDest *dest = new TextDestChat(&client);
(new GUITextInputMenu(guienv, guiroot, -1,
&g_menumgr, dest,
L""))->drop();
show_chat_menu(current_formspec, current_textdest, tsrc, device, &client,"");
}
else if(input->wasKeyDown(getKeySetting("keymap_cmd")))
{
TextDest *dest = new TextDestChat(&client);
(new GUITextInputMenu(guienv, guiroot, -1,
&g_menumgr, dest,
L"/"))->drop();
show_chat_menu(current_formspec, current_textdest, tsrc, device, &client,"/");
}
else if(input->wasKeyDown(getKeySetting("keymap_console")))
{
@ -2139,7 +2251,7 @@ void the_game(
else{
s32 dx = input->getMousePos().X - displaycenter.X;
s32 dy = input->getMousePos().Y - displaycenter.Y;
if(invert_mouse)
if(invert_mouse || player->camera_mode == CAMERA_MODE_THIRD_FRONT)
dy = -dy;
//infostream<<"window active, pos difference "<<dx<<","<<dy<<std::endl;
@ -2204,18 +2316,17 @@ void the_game(
camera_yaw
);
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();
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,
&g_menumgr,
&client, gamedef, tsrc);
menu->doPause = false;
menu->setFormSource(current_formspec);
menu->setTextDest(current_textdest);
menu->drop();
@ -2547,13 +2659,24 @@ void the_game(
LocalPlayer* player = client.getEnv().getLocalPlayer();
float full_punch_interval = playeritem_toolcap.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);
camera.update(player, dtime, busytime, screensize,
tool_reload_ratio);
camera.update(player, dtime, busytime, screensize, tool_reload_ratio,
current_camera_mode, client.getEnv());
camera.step(dtime);
v3f player_position = player->getPosition();
v3s16 pos_i = floatToInt(player_position, BS);
v3f camera_position = camera.getPosition();
v3f camera_direction = camera.getDirection();
f32 camera_fov = camera.getFovMax();
@ -2573,7 +2696,7 @@ void the_game(
}
// Update sound listener
sound->updateListener(camera.getCameraNode()->getPosition(),
sound->updateListener(camera.getCameraNode()->getPosition()+intToFloat(camera_offset, BS),
v3f(0,0,0), // velocity
camera.getDirection(),
camera.getCameraNode()->getUpVector());
@ -2605,6 +2728,10 @@ void the_game(
core::line3d<f32> shootline(camera_position,
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;
PointedThing pointed = getPointedThing(
@ -2871,6 +2998,7 @@ void the_game(
new GUIFormSpecMenu(device, guiroot, -1,
&g_menumgr,
&client, gamedef, tsrc);
menu->doPause = false;
menu->setFormSpec(meta->getString("formspec"),
inventoryloc);
menu->setFormSource(new NodeMetadataFormSource(
@ -2980,8 +3108,6 @@ void the_game(
fog_range = 100000*BS;
else {
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 *= 0.9;
}
@ -3131,9 +3257,7 @@ void the_game(
<<", "<<(player_position.Y/BS)
<<", "<<(player_position.Z/BS)
<<") (yaw="<<(wrapDegrees_0_360(camera_yaw))
<<") (t="<<client.getEnv().getClientMap().getHeat(pos_i)
<<"C, h="<<client.getEnv().getClientMap().getHumidity(pos_i)
<<"%) (seed = "<<((unsigned long long)client.getMapSeed())
<<") (seed = "<<((u64)client.getMapSeed())
<<")";
guitext2->setText(narrow_to_wide(os.str()).c_str());
guitext2->setVisible(true);
@ -3394,7 +3518,9 @@ void the_game(
/*
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.
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,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr,
InventoryManager *invmgr,
IGameDef *gamedef,
ISimpleTextureSource *tsrc
):
gui::IGUIElement* parent, s32 id, IMenuManager *menumgr,
InventoryManager *invmgr, IGameDef *gamedef,
ISimpleTextureSource *tsrc) :
GUIModalMenu(dev->getGUIEnvironment(), parent, id, menumgr),
m_device(dev),
m_invmgr(invmgr),
@ -248,10 +245,11 @@ std::vector<std::string> split(const std::string &s, char delim) {
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,',');
if (parts.size() == 2) {
if ((parts.size() == 2) || parts.size() == 3) {
v2f invsize;
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.Y = stof(parts[1]);
lockSize(false);
if (parts.size() == 3) {
if (parts[2] == "true") {
lockSize(true,v2u32(800,600));
}
}
if (m_lock) {
v2u32 current_screensize = m_device->getVideoDriver()->getScreenSize();
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;
}
void GUIFormSpecMenu::parseList(parserData* data,std::string element) {
void GUIFormSpecMenu::parseList(parserData* data,std::string element)
{
if (m_gamedef == 0) {
errorstream<<"WARNING: invalid use of 'list' with m_gamedef==0"<<std::endl;
return;
@ -358,7 +363,8 @@ void GUIFormSpecMenu::parseList(parserData* data,std::string element) {
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,';');
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;
}
void GUIFormSpecMenu::parseImage(parserData* data,std::string element) {
void GUIFormSpecMenu::parseImage(parserData* data,std::string element)
{
std::vector<std::string> parts = split(element,';');
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;
}
void GUIFormSpecMenu::parseItemImage(parserData* data,std::string element) {
void GUIFormSpecMenu::parseItemImage(parserData* data,std::string element)
{
std::vector<std::string> parts = split(element,';');
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;
}
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,';');
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;
}
void GUIFormSpecMenu::parseBackground(parserData* data,std::string element) {
void GUIFormSpecMenu::parseBackground(parserData* data,std::string element)
{
std::vector<std::string> parts = split(element,';');
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;
}
void GUIFormSpecMenu::parseTableOptions(parserData* data,std::string element) {
void GUIFormSpecMenu::parseTableOptions(parserData* data,std::string element)
{
std::vector<std::string> parts = split(element,';');
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,';');
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,';');
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;
}
void GUIFormSpecMenu::parseTextList(parserData* data,std::string element) {
void GUIFormSpecMenu::parseTextList(parserData* data,std::string element)
{
std::vector<std::string> parts = split(element,';');
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,';');
if (parts.size() == 5) {
@ -790,7 +806,8 @@ void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element) {
<< 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,';');
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;
}
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 label = parts[1];
std::string default_val = parts[2];
@ -935,7 +954,9 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data,std::vector<std::string>
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_geom = split(parts[1],',');
@ -1026,7 +1047,9 @@ void GUIFormSpecMenu::parseTextArea(parserData* data,std::vector<std::string>& p
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,';');
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;
}
void GUIFormSpecMenu::parseLabel(parserData* data,std::string element) {
void GUIFormSpecMenu::parseLabel(parserData* data,std::string element)
{
std::vector<std::string> parts = split(element,';');
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;
}
void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element) {
void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element)
{
std::vector<std::string> parts = split(element,';');
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;
}
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,';');
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;
}
void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element) {
void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element)
{
std::vector<std::string> parts = split(element,';');
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;
}
void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element) {
void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
{
if (m_gamedef == 0) {
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;
}
void GUIFormSpecMenu::parseBox(parserData* data,std::string element) {
void GUIFormSpecMenu::parseBox(parserData* data,std::string element)
{
std::vector<std::string> parts = split(element,';');
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;
}
void GUIFormSpecMenu::parseBackgroundColor(parserData* data,std::string element) {
void GUIFormSpecMenu::parseBackgroundColor(parserData* data,std::string element)
{
std::vector<std::string> parts = split(element,';');
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;
}
void GUIFormSpecMenu::parseListColors(parserData* data,std::string element) {
void GUIFormSpecMenu::parseListColors(parserData* data,std::string element)
{
std::vector<std::string> parts = split(element,';');
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;
}
void GUIFormSpecMenu::parseElement(parserData* data,std::string element) {
void GUIFormSpecMenu::parseElement(parserData* data,std::string element)
{
//some prechecks
if (element == "")
return;
@ -2132,16 +2164,22 @@ ItemStack GUIFormSpecMenu::verifySelectedItem()
return ItemStack();
}
void GUIFormSpecMenu::acceptInput(bool quit=false)
void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode=quit_mode_no)
{
if(m_text_dst)
{
std::map<std::string, std::string> fields;
if (quit) {
if (quitmode == quit_mode_accept) {
fields["quit"] = "true";
}
if (quitmode == quit_mode_cancel) {
fields["quit"] = "true";
m_text_dst->gotText(fields);
return;
}
if (current_keys_pending.key_down) {
fields["key_down"] = "true";
current_keys_pending.key_down = false;
@ -2281,10 +2319,11 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
if (event.KeyInput.PressedDown && (kp == EscapeKey ||
kp == getKeySetting("keymap_inventory")))
{
if (m_allowclose) {
acceptInput(true);
if (m_allowclose){
doPause = false;
acceptInput(quit_mode_cancel);
quitMenu();
} else {
} else {
m_text_dst->gotText(narrow_to_wide("MenuQuit"));
}
return true;
@ -2313,7 +2352,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
break;
}
if (current_keys_pending.key_enter && m_allowclose) {
acceptInput(true);
acceptInput(quit_mode_accept);
quitMenu();
}
else {
@ -2643,7 +2682,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
if (btn_id == 257) {
if (m_allowclose) {
acceptInput(true);
acceptInput(quit_mode_accept);
quitMenu();
} else {
acceptInput();
@ -2663,16 +2702,16 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
(s.fid == event.GUIEvent.Caller->getID()))
{
s.send = true;
acceptInput();
if(s.is_exit){
if (m_allowclose) {
acceptInput(true);
acceptInput(quit_mode_accept);
quitMenu();
} else {
m_text_dst->gotText(narrow_to_wide("ExitButton"));
}
return true;
}else{
acceptInput();
s.send = false;
return true;
}
@ -2685,7 +2724,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
{
if (m_allowclose) {
acceptInput(true);
acceptInput(quit_mode_accept);
quitMenu();
}
else {
@ -2723,7 +2762,8 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
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;
if (value[0] == '#') {

View File

@ -42,12 +42,22 @@ typedef enum {
f_Unknown
} FormspecFieldType;
typedef enum {
quit_mode_no,
quit_mode_accept,
quit_mode_cancel
} FormspecQuitMode;
struct TextDest
{
virtual ~TextDest() {};
// This is deprecated I guess? -celeron55
virtual void gotText(std::wstring text){}
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
@ -139,7 +149,8 @@ class GUIFormSpecMenu : public GUIModalMenu
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),
flabel(label),
fdefault(fdeflt),
@ -228,9 +239,11 @@ public:
void updateSelectedItem();
ItemStack verifySelectedItem();
void acceptInput(bool quit);
void acceptInput(FormspecQuitMode quitmode);
bool preprocessEvent(const SEvent& event);
bool OnEvent(const SEvent& event);
bool doPause;
bool pausesGame() { return doPause; }
GUITable* getTable(std::wstring tablename);
@ -332,7 +345,8 @@ private:
void parsePwdField(parserData* data,std::string element);
void parseField(parserData* data,std::string element,std::string type);
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 parseVertLabel(parserData* data,std::string element);
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,
Client* client
):
GUIModalMenu(env, parent, id, menumgr),
m_client(client)
GUIModalMenu(env, parent, id, menumgr)
{
}

View File

@ -44,11 +44,7 @@ public:
bool OnEvent(const SEvent& event);
bool pausesGame(){ return true; }
private:
Client* m_client;
bool pausesGame() { return true; }
};
#endif

View File

@ -566,6 +566,8 @@ protected:
log_register_thread("CurlFetchThread");
DSTACK(__FUNCTION_NAME);
porting::setThreadName("CurlFetchThread");
CurlHandlePool pool;
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));
break;
default:
steppos = v2s32(padding + i * fullimglen, padding);
steppos = v2s32(padding + i * fullimglen, padding);
}
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);
break;
default:
steppos = v2s32(1, 0);
steppos = v2s32(1, 0);
}
steppos.X *= srcd.Width;
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) {
InventoryList *mainlist = inventory->getList("main");
if (mainlist == NULL) {
errorstream << "draw_hotbar(): mainlist == NULL" << std::endl;
//silently ignore this we may not be initialized completely
return;
}
@ -384,7 +384,8 @@ void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem, s
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;
if (use_crosshair_image) {

View File

@ -43,6 +43,10 @@ LocalPlayer::LocalPlayer(IGameDef *gamedef):
last_pitch(0),
last_yaw(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_selected_image(""),
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)
{
Map *map = &env->getMap();
@ -356,7 +360,7 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d,
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);
}

View File

@ -23,10 +23,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "player.h"
#include <list>
class ClientEnvironment;
class Environment;
class ClientActiveObject;
enum LocalPlayerAnimations {NO_ANIM, WALK_ANIM, DIG_ANIM, WD_ANIM}; // no local animation, walking, digging, both
class LocalPlayer : public Player
{
public:
@ -44,9 +46,9 @@ public:
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);
void move(f32 dtime, ClientEnvironment *env, f32 pos_max_d);
void applyControl(float dtime);
@ -60,6 +62,12 @@ public:
unsigned int last_keyPressed;
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_selected_image;

View File

@ -55,7 +55,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "constants.h"
#include "porting.h"
#include "gettime.h"
#include "guiMessageMenu.h"
#include "filesys.h"
#include "config.h"
#include "version.h"
@ -85,6 +84,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifdef USE_LEVELDB
#include "database-leveldb.h"
#endif
#if USE_REDIS
#include "database-redis.h"
#endif
/*
Settings.
@ -361,7 +363,6 @@ public:
s32 mouse_wheel;
private:
IrrlichtDevice *m_device;
// The current state of keys
KeyList keyIsDown;
@ -1024,21 +1025,6 @@ int main(int argc, char *argv[])
if(port == 0)
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
std::string commanded_world = "";
if(cmd_args.exists("world"))
@ -1224,8 +1210,29 @@ int main(int argc, char *argv[])
}
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
Server server(world_path, gamespec, false);
Server server(world_path, gamespec, false, bind_addr.isIPv6());
// Database migration
if (cmd_args.exists("migrate")) {
@ -1238,7 +1245,7 @@ int main(int argc, char *argv[])
}
if (!world_mt.exists("backend")) {
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;
}
std::string backend = world_mt.get("backend");
@ -1253,6 +1260,10 @@ int main(int argc, char *argv[])
else if (migrate_to == "leveldb")
new_db = new Database_LevelDB(&(ServerMap&)server.getMap(), world_path);
#endif
#if USE_REDIS
else if (migrate_to == "redis")
new_db = new Database_Redis(&(ServerMap&)server.getMap(), world_path);
#endif
else {
errorstream << "Migration to " << migrate_to << " is not supported" << std::endl;
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 "modalMenu.h"
#include "guiPauseMenu.h" //For IGameCallback
#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::IGUIStaticText *guiroot;

View File

@ -46,6 +46,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#if USE_LEVELDB
#include "database-leveldb.h"
#endif
#if USE_REDIS
#include "database-redis.h"
#endif
#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
liquid (=water node was added) to transform queue.
note: todo: for liquid_finite enough to add only self node
*/
v3s16 dirs[7] = {
v3s16(0,0,0), // self
@ -1289,7 +1291,6 @@ void Map::removeNodeAndUpdate(v3s16 p,
/*
Add neighboring liquid nodes and this node to transform queue.
(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(0,0,1), // back
@ -1616,7 +1617,6 @@ struct NodeNeighbor {
NeighborType t;
v3s16 p;
bool l; //can liquid
bool i; //infinity
};
void Map::transforming_liquid_add(v3s16 p) {
@ -1627,383 +1627,8 @@ s32 Map::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)
{
if (g_settings->getBool("liquid_finite"))
return Map::transformLiquidsFinite(modified_blocks);
INodeDefManager *nodemgr = m_gamedef->ndef();
DSTACK(__FUNCTION_NAME);
@ -2382,26 +2007,6 @@ void Map::removeNodeTimer(v3s16 p)
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
*/
@ -2434,6 +2039,10 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emer
else if (backend == "leveldb")
dbase = new Database_LevelDB(this, savedir);
#endif
#if USE_REDIS
else if (backend == "redis")
dbase = new Database_Redis(this, savedir);
#endif
else
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.
ServerMapSector *sector = createSector(sectorpos);
assert(sector);
(void) sector;
for(s16 y=blockpos_min.Y-extra_borders.Y;
y<=blockpos_max.Y+extra_borders.Y; y++)
@ -2810,29 +2420,6 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data,
<<","<<blockpos_requested.Y<<","
<<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(enable_mapgen_debug_info)
@ -3167,19 +2754,6 @@ MapBlock *ServerMap::getBlockOrEmerge(v3s16 p3d)
}
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)
@ -3261,12 +2835,13 @@ std::string ServerMap::getSectorDir(v2s16 pos, int layout)
return m_savedir + DIR_DELIM + "sectors2" + DIR_DELIM + cc;
default:
assert(false);
return "";
}
}
v2s16 ServerMap::getSectorPos(std::string dirname)
{
unsigned int x, y;
unsigned int x = 0, y = 0;
int r;
std::string component;
fs::RemoveLastPathComponent(dirname, &component, 1);
@ -3908,48 +3483,6 @@ void ServerMap::PrintInfo(std::ostream &out)
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
*/

View File

@ -304,7 +304,6 @@ public:
virtual void PrintInfo(std::ostream &out);
void transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks);
void transformLiquidsFinite(std::map<v3s16, MapBlock*> & modified_blocks);
/*
Node metadata
@ -351,9 +350,6 @@ public:
void transforming_liquid_add(v3s16 p);
s32 transforming_liquid_size();
virtual s16 getHeat(v3s16 p);
virtual s16 getHumidity(v3s16 p);
protected:
friend class LuaVoxelManip;
@ -504,9 +500,6 @@ public:
u64 getSeed();
s16 getWaterLevel();
virtual s16 updateBlockHeat(ServerEnvironment *env, v3s16 p, MapBlock *block = NULL);
virtual s16 updateBlockHumidity(ServerEnvironment *env, v3s16 p, MapBlock *block = NULL);
private:
// Emerge manager
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):
heat(0),
humidity(0),
heat_last_update(0),
humidity_last_update(0),
m_parent(parent),
m_pos(pos),
m_gamedef(gamedef),
@ -647,8 +643,8 @@ void MapBlock::serializeNetworkSpecific(std::ostream &os, u16 net_proto_version)
if(net_proto_version >= 21){
int version = 1;
writeU8(os, version);
writeF1000(os, heat);
writeF1000(os, humidity);
writeF1000(os, 0); // deprecated heat
writeF1000(os, 0); // deprecated humidity
}
}
@ -764,8 +760,8 @@ void MapBlock::deSerializeNetworkSpecific(std::istream &is)
//if(version != 1)
// throw SerializationError("unsupported MapBlock version");
if(version >= 1) {
heat = readF1000(is);
humidity = readF1000(is);
readF1000(is); // deprecated heat
readF1000(is); // deprecated humidity
}
}
catch(SerializationError &e)

View File

@ -513,11 +513,6 @@ public:
NodeMetadataList m_node_metadata;
NodeTimerList m_node_timers;
StaticObjectList m_static_objects;
s16 heat;
s16 humidity;
u32 heat_last_update;
u32 humidity_last_update;
private:
/*

View File

@ -150,9 +150,8 @@ void MeshMakeData::setSmoothLighting(bool smooth_lighting)
Single light bank.
*/
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);
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.
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 night = getInteriorLight(LIGHTBANK_NIGHT, n, increment, data);
u16 day = getInteriorLight(LIGHTBANK_DAY, n, increment, ndef);
u16 night = getInteriorLight(LIGHTBANK_NIGHT, n, increment, ndef);
return day | (night << 8);
}
@ -185,10 +184,8 @@ u16 getInteriorLight(MapNode n, s32 increment, MeshMakeData *data)
Single light bank.
*/
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 l1 = n.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.
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 night = getFaceLight(LIGHTBANK_NIGHT, n, n2, face_dir, data);
u16 day = getFaceLight(LIGHTBANK_DAY, n, n2, face_dir, ndef);
u16 night = getFaceLight(LIGHTBANK_NIGHT, n, n2, face_dir, ndef);
return day | (night << 8);
}
@ -812,7 +809,7 @@ static void getTileInfo(
if(data->m_smooth_lighting == false)
{
lights[0] = lights[1] = lights[2] = lights[3] =
getFaceLight(n0, n1, face_dir, data);
getFaceLight(n0, n1, face_dir, ndef);
}
else
{
@ -1212,20 +1209,25 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
ITextureSource *tsrc = data->m_gamedef->tsrc();
material.setTexture(2, tsrc->getTexture("disable_img.png"));
if (enable_bumpmapping || enable_parallax_occlusion) {
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));
if (tsrc->isKnownSourceImage("override_normal.png")){
material.setTexture(1, tsrc->getTexture("override_normal.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,
@ -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"));
if (enable_shaders && (enable_bumpmapping || enable_parallax_occlusion))
{
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()));
if (tsrc->isKnownSourceImage("override_normal.png")){
buf->getMaterial().setTexture(1, tsrc->getTexture("override_normal.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
u16 getInteriorLight(MapNode n, s32 increment, MeshMakeData *data);
u16 getFaceLight(MapNode n, MapNode n2, v3s16 face_dir, MeshMakeData *data);
u16 getInteriorLight(MapNode n, s32 increment, INodeDefManager *ndef);
u16 getFaceLight(MapNode n, MapNode n2, v3s16 face_dir, INodeDefManager *ndef);
u16 getSmoothLight(v3s16 p, v3s16 corner, MeshMakeData *data);
// 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) {
bool isliquid, wasliquid, rare;
bool isliquid, wasliquid;
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 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--) {
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
if (isliquid != wasliquid && (!rare || !(rarecnt++ % 36)))
// there was a change between liquid and nonliquid, add to queue.
if (isliquid != wasliquid)
trans_liquid->push_back(v3s16(x, y, z));
wasliquid = isliquid;

View File

@ -209,7 +209,7 @@ Ore *createOre(OreType type);
enum DecorationType {
DECO_SIMPLE,
DECO_SIMPLE = 1,
DECO_SCHEMATIC,
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) {
Noise::init((NoiseParams*)np, seed, sx, sy, sz);
this->npindev = np;
void NoiseIndev::init(NoiseParams *np, int seed, int sx, int sy, int sz) {
Noise::init(np, seed, sx, sy, sz);
this->npindev = (NoiseIndevParams*) np;
}
NoiseIndev::NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy) : Noise(np, seed, sx, sy) {

View File

@ -61,7 +61,7 @@ public:
virtual ~NoiseIndev() {};
NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy);
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);
};

View File

@ -66,7 +66,7 @@ struct ModSpec
bool is_modpack;
// if modpack:
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_),
path(path_),
depends(),

View File

@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes_bloated.h"
#include "inventory.h"
#include "constants.h" // BS
#include <list>
#define PLAYERNAME_SIZE 20
@ -88,6 +89,7 @@ class IGameDef;
struct CollisionInfo;
class PlayerSAO;
struct HudElement;
class Environment;
class Player
{
@ -96,7 +98,10 @@ public:
Player(IGameDef *gamedef);
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()
@ -269,6 +274,9 @@ public:
bool physics_override_sneak;
bool physics_override_sneak_glitch;
v2s32 local_animations[4];
float local_animation_speed;
u16 hp;
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
*/
#include "porting.h"
#if defined(__APPLE__)
#include <mach-o/dyld.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>
#endif
#include "porting.h"
#include "config.h"
#include "debug.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
#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 "irrlichttypes.h" // u32
#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)
#ifdef _WIN32
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#include <windows.h>
#define sleep_ms(x) Sleep(x)
@ -266,6 +271,26 @@ inline u32 getTime(TimePrecision prec)
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

View File

@ -654,7 +654,7 @@ ItemStack read_item(lua_State* L, int index,Server* srv)
}
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);
if (lua_isstring(L, -1)) {
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);
}
bool success = read_flags(L, -1, flagdesc, flags, flagmask);
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)
@ -932,7 +941,7 @@ std::vector<ItemStack> read_items(lua_State *L, int index, Server *srv)
while (lua_next(L, index)) {
s32 key = luaL_checkinteger(L, -2);
if (key < 1) {
throw LuaError(NULL, "Invalid inventory list index");
throw LuaError("Invalid inventory list index");
}
if (items.size() < (u32) key) {
items.resize(key);

View File

@ -119,9 +119,14 @@ int getenumfield (lua_State *L,
const EnumString *spec,
int default_);
u32 getflagsfield (lua_State *L, int table,
bool getflagsfield (lua_State *L, int table,
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,
FlagDesc *flagdesc, u32 *flagmask);

View File

@ -59,6 +59,19 @@ v2s16 read_v2s16(lua_State *L, int index)
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 p;

View File

@ -75,6 +75,7 @@ v3s16 check_v3s16 (lua_State *L, int index);
v3f read_v3f (lua_State *L, int index);
v2f read_v2f (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);
aabb3f read_aabb3f (lua_State *L, int index, f32 scale);
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);
std::string str(s ? s : "");
throw LuaError(NULL, str);
throw LuaError(str);
}
// 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 "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[] =
{

View File

@ -55,14 +55,7 @@ public:
class LuaError : public ServerError
{
public:
LuaError(lua_State *L, const std::string &s);
virtual ~LuaError() throw()
{}
virtual const char * what() const throw()
{
return m_s.c_str();
}
LuaError(const std::string &s) : ServerError(s) {}
};

View File

@ -43,7 +43,7 @@ class ModNameStorer
private:
lua_State *L;
public:
ModNameStorer(lua_State *L_, const std::string modname):
ModNameStorer(lua_State *L_, const std::string &modname):
L(L_)
{
// Store current modname in registry
@ -151,13 +151,14 @@ void ScriptApiBase::realityCheck()
if(top >= 30){
dstream<<"Stack is over 30:"<<std::endl;
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()
{
throw LuaError(NULL, lua_tostring(m_luastack, -1));
throw LuaError(lua_tostring(m_luastack, -1));
}
void ScriptApiBase::stackDump(std::ostream &o)

View File

@ -54,7 +54,7 @@ int ScriptApiDetached::detached_inventory_AllowMove(
if(lua_pcall(L, 7, 1, errorhandler))
scriptError();
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);
lua_pop(L, 2); // Pop integer and error handler
return ret;
@ -86,7 +86,7 @@ int ScriptApiDetached::detached_inventory_AllowPut(
if(lua_pcall(L, 5, 1, errorhandler))
scriptError();
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);
lua_pop(L, 2); // Pop integer and error handler
return ret;
@ -118,7 +118,7 @@ int ScriptApiDetached::detached_inventory_AllowTake(
if(lua_pcall(L, 5, 1, errorhandler))
scriptError();
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);
lua_pop(L, 2); // Pop integer and error handler
return ret;
@ -232,7 +232,7 @@ bool ScriptApiDetached::getDetachedInventoryCallback(
// Should be a table
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);
return false;
}

View File

@ -47,8 +47,13 @@ bool ScriptApiItem::item_OnDrop(ItemStack &item,
pushFloatPos(L, pos);
if(lua_pcall(L, 3, 1, errorhandler))
scriptError();
if(!lua_isnil(L, -1))
item = read_item(L,-1, getServer());
if(!lua_isnil(L, -1)) {
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
return true;
}
@ -71,8 +76,13 @@ bool ScriptApiItem::item_OnPlace(ItemStack &item,
pushPointedThing(pointed);
if(lua_pcall(L, 3, 1, errorhandler))
scriptError();
if(!lua_isnil(L, -1))
item = read_item(L,-1, getServer());
if(!lua_isnil(L, -1)) {
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
return true;
}
@ -95,8 +105,13 @@ bool ScriptApiItem::item_OnUse(ItemStack &item,
pushPointedThing(pointed);
if(lua_pcall(L, 3, 1, errorhandler))
scriptError();
if(!lua_isnil(L, -1))
item = read_item(L,-1, getServer());
if(!lua_isnil(L, -1)) {
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
return true;
}
@ -123,8 +138,13 @@ bool ScriptApiItem::item_OnCraft(ItemStack &item, ServerActiveObject *user,
InvRef::create(L, craft_inv);
if(lua_pcall(L, 4, 1, errorhandler))
scriptError();
if(!lua_isnil(L, -1))
item = read_item(L,-1, getServer());
if(!lua_isnil(L, -1)) {
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
return true;
}
@ -151,8 +171,13 @@ bool ScriptApiItem::item_CraftPredict(ItemStack &item, ServerActiveObject *user,
InvRef::create(L, craft_inv);
if(lua_pcall(L, 4, 1, errorhandler))
scriptError();
if(!lua_isnil(L, -1))
item = read_item(L,-1, getServer());
if(!lua_isnil(L, -1)) {
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
return true;
}

View File

@ -30,7 +30,7 @@ struct ItemDefinition;
class LuaItemStack;
class ModApiItemMod;
class InventoryList;
class InventoryLocation;
struct InventoryLocation;
class ScriptApiItem
: virtual public ScriptApiBase

View File

@ -61,7 +61,7 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowMove(v3s16 p,
scriptError();
lua_remove(L, errorhandler); // Remove error handler
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);
int num = luaL_checkinteger(L, -1);
lua_pop(L, 1); // Pop integer
@ -100,7 +100,7 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowPut(v3s16 p,
scriptError();
lua_remove(L, errorhandler); // Remove error handler
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);
int num = luaL_checkinteger(L, -1);
lua_pop(L, 1); // Pop integer
@ -139,7 +139,7 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowTake(v3s16 p,
scriptError();
lua_remove(L, errorhandler); // Remove error handler
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);
int num = luaL_checkinteger(L, -1);
lua_pop(L, 1); // Pop integer

View File

@ -33,7 +33,7 @@ bool ScriptApiServer::getAuth(const std::string &playername,
getAuthHandler();
lua_getfield(L, -1, "get_auth");
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());
if(lua_pcall(L, 1, 1, errorhandler))
scriptError();
@ -48,13 +48,13 @@ bool ScriptApiServer::getAuth(const std::string &playername,
std::string password;
bool found = getstringfield(L, -1, "password", password);
if(!found)
throw LuaError(NULL, "Authentication handler didn't return password");
throw LuaError("Authentication handler didn't return password");
if(dst_password)
*dst_password = password;
lua_getfield(L, -1, "privileges");
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)
readPrivileges(-1, *dst_privs);
lua_pop(L, 1);
@ -74,7 +74,7 @@ void ScriptApiServer::getAuthHandler()
}
lua_remove(L, -2); // Remove minetest
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)
@ -108,7 +108,7 @@ void ScriptApiServer::createAuth(const std::string &playername,
lua_getfield(L, -1, "create_auth");
lua_remove(L, -2); // Remove auth handler
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, password.c_str());
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_remove(L, -2); // Remove auth handler
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, password.c_str());
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);
log_register_thread(std::string("AsyncWorkerThread_") + number);
porting::setThreadName(
std::string(std::string("AsyncWorkTh_") + number).c_str());
/** prepare job lua environment **/
lua_newtable(m_LuaStack);
lua_setglobal(m_LuaStack, "engine");

View File

@ -48,7 +48,7 @@ protected:
ScriptApiBase *scriptIface = getScriptApiBase(L);
T *scriptIfaceDowncast = dynamic_cast<T*>(scriptIface);
if (!scriptIfaceDowncast) {
throw LuaError(NULL, "Requested unavailable ScriptApi - core engine bug!");
throw LuaError("Requested unavailable ScriptApi - core engine bug!");
}
return scriptIfaceDowncast;
}

View File

@ -150,16 +150,16 @@ int ModApiCraft::l_register_craft(lua_State *L)
if(type == "shaped"){
std::string output = getstringfield_default(L, table, "output", "");
if(output == "")
throw LuaError(NULL, "Crafting definition is missing an output");
throw LuaError("Crafting definition is missing an output");
int width = 0;
std::vector<std::string> recipe;
lua_getfield(L, table, "recipe");
if(lua_isnil(L, -1))
throw LuaError(NULL, "Crafting definition is missing a recipe"
throw LuaError("Crafting definition is missing a recipe"
" (output=\"" + output + "\")");
if(!readCraftRecipeShaped(L, -1, width, recipe))
throw LuaError(NULL, "Invalid crafting recipe"
throw LuaError("Invalid crafting recipe"
" (output=\"" + output + "\")");
CraftReplacements replacements;
@ -167,7 +167,7 @@ int ModApiCraft::l_register_craft(lua_State *L)
if(!lua_isnil(L, -1))
{
if(!readCraftReplacements(L, -1, replacements))
throw LuaError(NULL, "Invalid replacements"
throw LuaError("Invalid replacements"
" (output=\"" + output + "\")");
}
@ -181,17 +181,17 @@ int ModApiCraft::l_register_craft(lua_State *L)
else if(type == "shapeless"){
std::string output = getstringfield_default(L, table, "output", "");
if(output == "")
throw LuaError(NULL, "Crafting definition (shapeless)"
throw LuaError("Crafting definition (shapeless)"
" is missing an output");
std::vector<std::string> recipe;
lua_getfield(L, table, "recipe");
if(lua_isnil(L, -1))
throw LuaError(NULL, "Crafting definition (shapeless)"
throw LuaError("Crafting definition (shapeless)"
" is missing a recipe"
" (output=\"" + output + "\")");
if(!readCraftRecipeShapeless(L, -1, recipe))
throw LuaError(NULL, "Invalid crafting recipe"
throw LuaError("Invalid crafting recipe"
" (output=\"" + output + "\")");
CraftReplacements replacements;
@ -199,7 +199,7 @@ int ModApiCraft::l_register_craft(lua_State *L)
if(!lua_isnil(L, -1))
{
if(!readCraftReplacements(L, -1, replacements))
throw LuaError(NULL, "Invalid replacements"
throw LuaError("Invalid replacements"
" (output=\"" + output + "\")");
}
@ -224,12 +224,12 @@ int ModApiCraft::l_register_craft(lua_State *L)
else if(type == "cooking"){
std::string output = getstringfield_default(L, table, "output", "");
if(output == "")
throw LuaError(NULL, "Crafting definition (cooking)"
throw LuaError("Crafting definition (cooking)"
" is missing an output");
std::string recipe = getstringfield_default(L, table, "recipe", "");
if(recipe == "")
throw LuaError(NULL, "Crafting definition (cooking)"
throw LuaError("Crafting definition (cooking)"
" is missing a recipe"
" (output=\"" + output + "\")");
@ -240,7 +240,7 @@ int ModApiCraft::l_register_craft(lua_State *L)
if(!lua_isnil(L, -1))
{
if(!readCraftReplacements(L, -1, replacements))
throw LuaError(NULL, "Invalid replacements"
throw LuaError("Invalid replacements"
" (cooking output=\"" + output + "\")");
}
@ -254,7 +254,7 @@ int ModApiCraft::l_register_craft(lua_State *L)
else if(type == "fuel"){
std::string recipe = getstringfield_default(L, table, "recipe", "");
if(recipe == "")
throw LuaError(NULL, "Crafting definition (fuel)"
throw LuaError("Crafting definition (fuel)"
" is missing a recipe");
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(!readCraftReplacements(L, -1, replacements))
throw LuaError(NULL, "Invalid replacements"
throw LuaError("Invalid replacements"
" (fuel recipe=\"" + recipe + "\")");
}
@ -274,7 +274,7 @@ int ModApiCraft::l_register_craft(lua_State *L)
}
else
{
throw LuaError(NULL, "Unknown crafting definition type: \"" + type + "\"");
throw LuaError("Unknown crafting definition type: \"" + type + "\"");
}
lua_pop(L, 1);

View File

@ -765,7 +765,6 @@ int ModApiEnvMod::l_spawn_tree(lua_State *L)
return 1;
}
// minetest.transforming_liquid_add(pos)
int ModApiEnvMod::l_transforming_liquid_add(lua_State *L)
{
@ -776,28 +775,6 @@ int ModApiEnvMod::l_transforming_liquid_add(lua_State *L)
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)
// blockpos = {x=num, y=num, z=num}
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(line_of_sight);
API_FCT(transforming_liquid_add);
API_FCT(get_heat);
API_FCT(get_humidity);
API_FCT(forceload_block);
API_FCT(forceload_free_block);
}

Some files were not shown because too many files have changed in this diff Show More