master
commit
4be38f6a0d
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -116,6 +116,7 @@ minetest.register_entity("__builtin:item", {
|
|||
return
|
||||
end
|
||||
end
|
||||
self.itemstring = ''
|
||||
self.object:remove()
|
||||
end,
|
||||
})
|
||||
|
|
|
@ -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
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 .. "]"
|
||||
|
||||
|
|
|
@ -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]" ..
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
10
src/camera.h
10
src/camera.h
|
@ -27,10 +27,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "util/numeric.h"
|
||||
#include <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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
25
src/client.h
25
src/client.h
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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@
|
||||
|
|
26
src/config.h
26
src/config.h
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2014 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if USE_REDIS
|
||||
/*
|
||||
Redis databases
|
||||
*/
|
||||
|
||||
|
||||
#include "database-redis.h"
|
||||
#include <hiredis.h>
|
||||
|
||||
#include "map.h"
|
||||
#include "mapsector.h"
|
||||
#include "mapblock.h"
|
||||
#include "serialization.h"
|
||||
#include "main.h"
|
||||
#include "settings.h"
|
||||
#include "log.h"
|
||||
|
||||
Database_Redis::Database_Redis(ServerMap *map, std::string savedir)
|
||||
{
|
||||
Settings conf;
|
||||
conf.readConfigFile((std::string(savedir) + DIR_DELIM + "world.mt").c_str());
|
||||
std::string tmp;
|
||||
try {
|
||||
tmp = conf.get("redis_address");
|
||||
hash = conf.get("redis_hash");
|
||||
} catch(SettingNotFoundException e) {
|
||||
throw SettingNotFoundException("Set redis_address and redis_hash in world.mt to use the redis backend");
|
||||
}
|
||||
const char *addr = tmp.c_str();
|
||||
int port = conf.exists("redis_port") ? conf.getU16("redis_port") : 6379;
|
||||
ctx = redisConnect(addr, port);
|
||||
if(!ctx)
|
||||
throw FileNotGoodException("Cannot allocate redis context");
|
||||
else if(ctx->err) {
|
||||
std::string err = std::string("Connection error: ") + ctx->errstr;
|
||||
redisFree(ctx);
|
||||
throw FileNotGoodException(err);
|
||||
}
|
||||
srvmap = map;
|
||||
}
|
||||
|
||||
int Database_Redis::Initialized(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Database_Redis::beginSave() {
|
||||
redisReply *reply;
|
||||
reply = (redisReply*) redisCommand(ctx, "MULTI");
|
||||
if(!reply)
|
||||
throw FileNotGoodException(std::string("redis command 'MULTI' failed: ") + ctx->errstr);
|
||||
freeReplyObject(reply);
|
||||
}
|
||||
|
||||
void Database_Redis::endSave() {
|
||||
redisReply *reply;
|
||||
reply = (redisReply*) redisCommand(ctx, "EXEC");
|
||||
if(!reply)
|
||||
throw FileNotGoodException(std::string("redis command 'EXEC' failed: ") + ctx->errstr);
|
||||
freeReplyObject(reply);
|
||||
}
|
||||
|
||||
void Database_Redis::saveBlock(MapBlock *block)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
/*
|
||||
Dummy blocks are not written
|
||||
*/
|
||||
if(block->isDummy())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Format used for writing
|
||||
u8 version = SER_FMT_VER_HIGHEST_WRITE;
|
||||
// Get destination
|
||||
v3s16 p3d = block->getPos();
|
||||
|
||||
/*
|
||||
[0] u8 serialization version
|
||||
[1] data
|
||||
*/
|
||||
|
||||
std::ostringstream o(std::ios_base::binary);
|
||||
o.write((char*)&version, 1);
|
||||
// Write basic data
|
||||
block->serialize(o, version, true);
|
||||
// Write block to database
|
||||
std::string tmp1 = o.str();
|
||||
std::string tmp2 = i64tos(getBlockAsInteger(p3d));
|
||||
|
||||
redisReply *reply;
|
||||
reply = (redisReply*) redisCommand(ctx, "HSET %s %s %b", hash.c_str(), tmp2.c_str(), tmp1.c_str(), tmp1.size());
|
||||
if(!reply)
|
||||
throw FileNotGoodException(std::string("redis command 'HSET %s %s %b' failed: ") + ctx->errstr);
|
||||
if(reply->type == REDIS_REPLY_ERROR)
|
||||
throw FileNotGoodException("Failed to store block in Database");
|
||||
|
||||
// We just wrote it to the disk so clear modified flag
|
||||
block->resetModified();
|
||||
}
|
||||
|
||||
MapBlock* Database_Redis::loadBlock(v3s16 blockpos)
|
||||
{
|
||||
v2s16 p2d(blockpos.X, blockpos.Z);
|
||||
|
||||
std::string tmp = i64tos(getBlockAsInteger(blockpos));
|
||||
redisReply *reply;
|
||||
reply = (redisReply*) redisCommand(ctx, "HGET %s %s", hash.c_str(), tmp.c_str());
|
||||
if(!reply)
|
||||
throw FileNotGoodException(std::string("redis command 'HGET %s %s' failed: ") + ctx->errstr);
|
||||
|
||||
if (reply->type == REDIS_REPLY_STRING && reply->len == 0) {
|
||||
freeReplyObject(reply);
|
||||
errorstream << "Blank block data in database (reply->len == 0) ("
|
||||
<< blockpos.X << "," << blockpos.Y << "," << blockpos.Z << ")" << std::endl;
|
||||
|
||||
if (g_settings->getBool("ignore_world_load_errors")) {
|
||||
errorstream << "Ignoring block load error. Duck and cover! "
|
||||
<< "(ignore_world_load_errors)" << std::endl;
|
||||
} else {
|
||||
throw SerializationError("Blank block data in database");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (reply->type == REDIS_REPLY_STRING) {
|
||||
/*
|
||||
Make sure sector is loaded
|
||||
*/
|
||||
MapSector *sector = srvmap->createSector(p2d);
|
||||
|
||||
try {
|
||||
std::istringstream is(std::string(reply->str, reply->len), std::ios_base::binary);
|
||||
freeReplyObject(reply); // std::string copies the memory so we can already do this here
|
||||
u8 version = SER_FMT_VER_INVALID;
|
||||
is.read((char *)&version, 1);
|
||||
|
||||
if (is.fail())
|
||||
throw SerializationError("ServerMap::loadBlock(): Failed"
|
||||
" to read MapBlock version");
|
||||
|
||||
MapBlock *block = NULL;
|
||||
bool created_new = false;
|
||||
block = sector->getBlockNoCreateNoEx(blockpos.Y);
|
||||
if (block == NULL)
|
||||
{
|
||||
block = sector->createBlankBlockNoInsert(blockpos.Y);
|
||||
created_new = true;
|
||||
}
|
||||
|
||||
// Read basic data
|
||||
block->deSerialize(is, version, true);
|
||||
|
||||
// If it's a new block, insert it to the map
|
||||
if (created_new)
|
||||
sector->insertBlock(block);
|
||||
|
||||
// We just loaded it from, so it's up-to-date.
|
||||
block->resetModified();
|
||||
}
|
||||
catch (SerializationError &e)
|
||||
{
|
||||
errorstream << "Invalid block data in database"
|
||||
<< " (" << blockpos.X << "," << blockpos.Y << "," << blockpos.Z
|
||||
<< ") (SerializationError): " << e.what() << std::endl;
|
||||
// TODO: Block should be marked as invalid in memory so that it is
|
||||
// not touched but the game can run
|
||||
|
||||
if (g_settings->getBool("ignore_world_load_errors")) {
|
||||
errorstream << "Ignoring block load error. Duck and cover! "
|
||||
<< "(ignore_world_load_errors)" << std::endl;
|
||||
} else {
|
||||
throw SerializationError("Invalid block data in database");
|
||||
}
|
||||
}
|
||||
|
||||
return srvmap->getBlockNoCreateNoEx(blockpos); // should not be using this here
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Database_Redis::listAllLoadableBlocks(std::list<v3s16> &dst)
|
||||
{
|
||||
redisReply *reply;
|
||||
reply = (redisReply*) redisCommand(ctx, "HKEYS %s", hash.c_str());
|
||||
if(!reply)
|
||||
throw FileNotGoodException(std::string("redis command 'HKEYS %s' failed: ") + ctx->errstr);
|
||||
if(reply->type != REDIS_REPLY_ARRAY)
|
||||
throw FileNotGoodException("Failed to get keys from database");
|
||||
for(size_t i = 0; i < reply->elements; i++)
|
||||
{
|
||||
assert(reply->element[i]->type == REDIS_REPLY_STRING);
|
||||
dst.push_back(getIntegerAsBlock(stoi64(reply->element[i]->str)));
|
||||
}
|
||||
freeReplyObject(reply);
|
||||
}
|
||||
|
||||
Database_Redis::~Database_Redis()
|
||||
{
|
||||
redisFree(ctx);
|
||||
}
|
||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Minetest
|
||||
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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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() {};
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{}
|
||||
};
|
||||
|
|
382
src/game.cpp
382
src/game.cpp
|
@ -28,7 +28,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "IMeshCache.h"
|
||||
#include "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,¤t_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(),¤t_formspec);
|
||||
current_textdest = new LocalFormspecHandler("MT_PAUSE_MENU");
|
||||
GUIFormSpecMenu *menu =
|
||||
new GUIFormSpecMenu(device, guiroot, -1, &g_menumgr, NULL, NULL, tsrc);
|
||||
menu->doPause = true;
|
||||
menu->setFormSource(current_formspec);
|
||||
menu->setTextDest(current_textdest);
|
||||
menu->drop();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void the_game(bool &kill, bool random_input, InputHandler *input,
|
||||
IrrlichtDevice *device, gui::IGUIFont* font, std::string map_dir,
|
||||
std::string playername, std::string password,
|
||||
std::string address /* If "", local server is used */,
|
||||
u16 port, std::wstring &error_message, ChatBackend &chat_backend,
|
||||
const SubgameSpec &gamespec /* Used for local game */,
|
||||
bool simple_singleplayer_mode)
|
||||
{
|
||||
FormspecFormSource* current_formspec = 0;
|
||||
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();
|
||||
|
|
|
@ -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] == '#') {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,173 +0,0 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "guiMessageMenu.h"
|
||||
#include "debug.h"
|
||||
#include "serialization.h"
|
||||
#include <string>
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
|
||||
#include "gettext.h"
|
||||
|
||||
GUIMessageMenu::GUIMessageMenu(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IMenuManager *menumgr,
|
||||
std::wstring message_text
|
||||
):
|
||||
GUIModalMenu(env, parent, id, menumgr),
|
||||
m_message_text(message_text),
|
||||
m_status(false)
|
||||
{
|
||||
}
|
||||
|
||||
GUIMessageMenu::~GUIMessageMenu()
|
||||
{
|
||||
removeChildren();
|
||||
}
|
||||
|
||||
void GUIMessageMenu::removeChildren()
|
||||
{
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(256);
|
||||
if(e != NULL)
|
||||
e->remove();
|
||||
}
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(257);
|
||||
if(e != NULL)
|
||||
e->remove();
|
||||
}
|
||||
}
|
||||
|
||||
void GUIMessageMenu::regenerateGui(v2u32 screensize)
|
||||
{
|
||||
/*
|
||||
Remove stuff
|
||||
*/
|
||||
removeChildren();
|
||||
|
||||
/*
|
||||
Calculate new sizes and positions
|
||||
*/
|
||||
core::rect<s32> rect(
|
||||
screensize.X/2 - 580/2,
|
||||
screensize.Y/2 - 300/2,
|
||||
screensize.X/2 + 580/2,
|
||||
screensize.Y/2 + 300/2
|
||||
);
|
||||
|
||||
DesiredRect = rect;
|
||||
recalculateAbsolutePosition(false);
|
||||
|
||||
v2s32 size = rect.getSize();
|
||||
|
||||
gui::IGUISkin *skin = Environment->getSkin();
|
||||
gui::IGUIFont *font = skin->getFont();
|
||||
s32 msg_h = font->getDimension(m_message_text.c_str()).Height;
|
||||
s32 msg_w = font->getDimension(m_message_text.c_str()).Width;
|
||||
if(msg_h > 200)
|
||||
msg_h = 200;
|
||||
if(msg_w > 540)
|
||||
msg_w = 540;
|
||||
|
||||
/*
|
||||
Add stuff
|
||||
*/
|
||||
{
|
||||
core::rect<s32> rect(0, 0, msg_w, msg_h);
|
||||
rect += v2s32(size.X/2-msg_w/2, size.Y/2-30/2 - msg_h/2);
|
||||
Environment->addStaticText(m_message_text.c_str(),
|
||||
rect, false, true, this, -1);
|
||||
}
|
||||
|
||||
int bw = 140;
|
||||
{
|
||||
core::rect<s32> rect(0, 0, bw, 30);
|
||||
rect = rect + v2s32(size.X/2-bw/2, size.Y/2-30/2+5 + msg_h/2);
|
||||
wchar_t* text = wgettext("Proceed");
|
||||
gui::IGUIElement *e =
|
||||
Environment->addButton(rect, this, 257,
|
||||
text);
|
||||
Environment->setFocus(e);
|
||||
delete[] text;
|
||||
}
|
||||
}
|
||||
|
||||
void GUIMessageMenu::drawMenu()
|
||||
{
|
||||
gui::IGUISkin* skin = Environment->getSkin();
|
||||
if (!skin)
|
||||
return;
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
|
||||
video::SColor bgcolor(140,0,0,0);
|
||||
driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
|
||||
|
||||
gui::IGUIElement::draw();
|
||||
}
|
||||
|
||||
bool GUIMessageMenu::OnEvent(const SEvent& event)
|
||||
{
|
||||
if(event.EventType==EET_KEY_INPUT_EVENT)
|
||||
{
|
||||
if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
|
||||
{
|
||||
m_status = true;
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
|
||||
{
|
||||
m_status = true;
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(event.EventType==EET_GUI_EVENT)
|
||||
{
|
||||
if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
|
||||
&& isVisible())
|
||||
{
|
||||
if(!canTakeFocus(event.GUIEvent.Element))
|
||||
{
|
||||
dstream<<"GUIMessageMenu: Not allowing focus change."
|
||||
<<std::endl;
|
||||
// Returning true disables focus change
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
|
||||
{
|
||||
switch(event.GUIEvent.Caller->getID())
|
||||
{
|
||||
case 257:
|
||||
m_status = true;
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Parent ? Parent->OnEvent(event) : false;
|
||||
}
|
||||
|
|
@ -1,280 +0,0 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "guiPauseMenu.h"
|
||||
#include "debug.h"
|
||||
#include "serialization.h"
|
||||
#include "porting.h"
|
||||
#include "config.h"
|
||||
#include "version.h"
|
||||
#include "main.h"
|
||||
#include <IGUICheckBox.h>
|
||||
#include <IGUIEditBox.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIFont.h>
|
||||
#include "gettext.h"
|
||||
#include "util/string.h"
|
||||
|
||||
GUIPauseMenu::GUIPauseMenu(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IGameCallback *gamecallback,
|
||||
IMenuManager *menumgr,
|
||||
bool simple_singleplayer_mode):
|
||||
GUIModalMenu(env, parent, id, menumgr),
|
||||
m_gamecallback(gamecallback),
|
||||
m_simple_singleplayer_mode(simple_singleplayer_mode)
|
||||
{
|
||||
}
|
||||
|
||||
GUIPauseMenu::~GUIPauseMenu()
|
||||
{
|
||||
removeChildren();
|
||||
}
|
||||
|
||||
void GUIPauseMenu::removeChildren()
|
||||
{
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(256);
|
||||
if(e != NULL)
|
||||
e->remove();
|
||||
}
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(257);
|
||||
if(e != NULL)
|
||||
e->remove();
|
||||
}
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(258);
|
||||
if(e != NULL)
|
||||
e->remove();
|
||||
}
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(259);
|
||||
if(e != NULL)
|
||||
e->remove();
|
||||
}
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(260);
|
||||
if(e != NULL)
|
||||
e->remove();
|
||||
}
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(261);
|
||||
if(e != NULL)
|
||||
e->remove();
|
||||
}
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(262);
|
||||
if(e != NULL)
|
||||
e->remove();
|
||||
}
|
||||
}
|
||||
|
||||
void GUIPauseMenu::regenerateGui(v2u32 screensize)
|
||||
{
|
||||
/*
|
||||
Remove stuff
|
||||
*/
|
||||
removeChildren();
|
||||
|
||||
/*
|
||||
Calculate new sizes and positions
|
||||
*/
|
||||
core::rect<s32> rect(
|
||||
screensize.X/2 - 580/2,
|
||||
screensize.Y/2 - 300/2,
|
||||
screensize.X/2 + 580/2,
|
||||
screensize.Y/2 + 300/2
|
||||
);
|
||||
|
||||
DesiredRect = rect;
|
||||
recalculateAbsolutePosition(false);
|
||||
|
||||
v2s32 size = rect.getSize();
|
||||
|
||||
/*
|
||||
Add stuff
|
||||
*/
|
||||
const s32 btn_height = 30;
|
||||
const s32 btn_gap = 20;
|
||||
const s32 btn_num = m_simple_singleplayer_mode ? 4 : 5;
|
||||
s32 btn_y = size.Y/2-((btn_num*btn_height+(btn_num-1)*btn_gap))/2;
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 140, btn_height);
|
||||
rect = rect + v2s32(size.X/2-140/2, btn_y);
|
||||
wchar_t* text = wgettext("Continue");
|
||||
Environment->addButton(rect, this, 256,
|
||||
text);
|
||||
delete[] text;
|
||||
}
|
||||
btn_y += btn_height + btn_gap;
|
||||
if(!m_simple_singleplayer_mode)
|
||||
{
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 140, btn_height);
|
||||
rect = rect + v2s32(size.X/2-140/2, btn_y);
|
||||
wchar_t* text = wgettext("Change Password");
|
||||
Environment->addButton(rect, this, 261,
|
||||
text);
|
||||
delete[] text;
|
||||
}
|
||||
btn_y += btn_height + btn_gap;
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 140, btn_height);
|
||||
rect = rect + v2s32(size.X/2-140/2, btn_y);
|
||||
wchar_t* text = wgettext("Sound Volume");
|
||||
Environment->addButton(rect, this, 262,
|
||||
text);
|
||||
delete[] text;
|
||||
}
|
||||
btn_y += btn_height + btn_gap;
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 140, btn_height);
|
||||
rect = rect + v2s32(size.X/2-140/2, btn_y);
|
||||
wchar_t* text = wgettext("Exit to Menu");
|
||||
Environment->addButton(rect, this, 260,
|
||||
text);
|
||||
delete[] text;
|
||||
}
|
||||
btn_y += btn_height + btn_gap;
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 140, btn_height);
|
||||
rect = rect + v2s32(size.X/2-140/2, btn_y);
|
||||
wchar_t* text = wgettext("Exit to OS");
|
||||
Environment->addButton(rect, this, 257,
|
||||
text);
|
||||
delete[] text;
|
||||
}
|
||||
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 180, 240);
|
||||
rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2);
|
||||
wchar_t* text = wgettext("Default Controls:\n"
|
||||
"- WASD: move\n"
|
||||
"- Space: jump/climb\n"
|
||||
"- Shift: sneak/go down\n"
|
||||
"- Q: drop item\n"
|
||||
"- I: inventory\n"
|
||||
"- Mouse: turn/look\n"
|
||||
"- Mouse left: dig/punch\n"
|
||||
"- Mouse right: place/use\n"
|
||||
"- Mouse wheel: select item\n"
|
||||
"- T: chat\n"
|
||||
);
|
||||
Environment->addStaticText(text, rect, false, true, this, 258);
|
||||
delete[] text;
|
||||
|
||||
}
|
||||
{
|
||||
core::rect<s32> rect(0, 0, 180, 220);
|
||||
rect = rect + v2s32(size.X/2 - 90 - rect.getWidth(), size.Y/2-rect.getHeight()/2);
|
||||
|
||||
v2u32 max_texture_size;
|
||||
{
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
max_texture_size = driver->getMaxTextureSize();
|
||||
}
|
||||
|
||||
std::ostringstream os;
|
||||
os<<"Minetest\n";
|
||||
os<<minetest_build_info<<"\n";
|
||||
os<<"path_user = "<<wrap_rows(porting::path_user, 20)<<"\n";
|
||||
|
||||
Environment->addStaticText(narrow_to_wide(os.str()).c_str(), rect, false, true, this, 259);
|
||||
}
|
||||
}
|
||||
|
||||
void GUIPauseMenu::drawMenu()
|
||||
{
|
||||
gui::IGUISkin* skin = Environment->getSkin();
|
||||
if (!skin)
|
||||
return;
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
|
||||
video::SColor bgcolor(140,0,0,0);
|
||||
driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
|
||||
|
||||
gui::IGUIElement::draw();
|
||||
}
|
||||
|
||||
bool GUIPauseMenu::OnEvent(const SEvent& event)
|
||||
{
|
||||
|
||||
if(event.EventType==EET_KEY_INPUT_EVENT)
|
||||
{
|
||||
if(event.KeyInput.PressedDown)
|
||||
{
|
||||
if(event.KeyInput.Key==KEY_ESCAPE)
|
||||
{
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
else if(event.KeyInput.Key==KEY_RETURN)
|
||||
{
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(event.EventType==EET_GUI_EVENT)
|
||||
{
|
||||
if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
|
||||
&& isVisible())
|
||||
{
|
||||
if(!canTakeFocus(event.GUIEvent.Element))
|
||||
{
|
||||
dstream<<"GUIPauseMenu: Not allowing focus change."
|
||||
<<std::endl;
|
||||
// Returning true disables focus change
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
|
||||
{
|
||||
switch(event.GUIEvent.Caller->getID())
|
||||
{
|
||||
case 256: // continue
|
||||
quitMenu();
|
||||
// ALWAYS return immediately after quitMenu()
|
||||
return true;
|
||||
case 261:
|
||||
m_gamecallback->changePassword();
|
||||
quitMenu();
|
||||
return true;
|
||||
case 262:
|
||||
m_gamecallback->changeVolume();
|
||||
quitMenu();
|
||||
return true;
|
||||
case 260: // disconnect
|
||||
m_gamecallback->disconnect();
|
||||
quitMenu();
|
||||
return true;
|
||||
case 257: // exit
|
||||
m_gamecallback->exitToOS();
|
||||
quitMenu();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Parent ? Parent->OnEvent(event) : false;
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef GUIPAUSEMENU_HEADER
|
||||
#define GUIPAUSEMENU_HEADER
|
||||
|
||||
#include "irrlichttypes_extrabloated.h"
|
||||
#include "modalMenu.h"
|
||||
|
||||
class IGameCallback
|
||||
{
|
||||
public:
|
||||
virtual void exitToOS() = 0;
|
||||
virtual void disconnect() = 0;
|
||||
virtual void changePassword() = 0;
|
||||
virtual void changeVolume() = 0;
|
||||
};
|
||||
|
||||
class GUIPauseMenu : public GUIModalMenu
|
||||
{
|
||||
public:
|
||||
GUIPauseMenu(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IGameCallback *gamecallback,
|
||||
IMenuManager *menumgr,
|
||||
bool simple_singleplayer_mode);
|
||||
~GUIPauseMenu();
|
||||
|
||||
void removeChildren();
|
||||
/*
|
||||
Remove and re-add (or reposition) stuff
|
||||
*/
|
||||
void regenerateGui(v2u32 screensize);
|
||||
|
||||
void drawMenu();
|
||||
|
||||
bool OnEvent(const SEvent& event);
|
||||
|
||||
bool pausesGame(){ return true; }
|
||||
|
||||
private:
|
||||
IGameCallback *m_gamecallback;
|
||||
bool m_simple_singleplayer_mode;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -41,8 +41,7 @@ GUIVolumeChange::GUIVolumeChange(gui::IGUIEnvironment* env,
|
|||
IMenuManager *menumgr,
|
||||
Client* client
|
||||
):
|
||||
GUIModalMenu(env, parent, id, menumgr),
|
||||
m_client(client)
|
||||
GUIModalMenu(env, parent, id, menumgr)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -44,11 +44,7 @@ public:
|
|||
|
||||
bool OnEvent(const SEvent& event);
|
||||
|
||||
bool pausesGame(){ return true; }
|
||||
|
||||
private:
|
||||
Client* m_client;
|
||||
|
||||
bool pausesGame() { return true; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -566,6 +566,8 @@ protected:
|
|||
log_register_thread("CurlFetchThread");
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
porting::setThreadName("CurlFetchThread");
|
||||
|
||||
CurlHandlePool pool;
|
||||
|
||||
m_multi = curl_multi_init();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
49
src/main.cpp
49
src/main.cpp
|
@ -55,7 +55,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "constants.h"
|
||||
#include "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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
487
src/map.cpp
487
src/map.cpp
|
@ -46,6 +46,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#if USE_LEVELDB
|
||||
#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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
/*
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -209,7 +209,7 @@ Ore *createOre(OreType type);
|
|||
|
||||
|
||||
enum DecorationType {
|
||||
DECO_SIMPLE,
|
||||
DECO_SIMPLE = 1,
|
||||
DECO_SCHEMATIC,
|
||||
DECO_LSYSTEM
|
||||
};
|
||||
|
|
|
@ -26,9 +26,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void NoiseIndev::init(NoiseIndevParams *np, int seed, int sx, int sy, int sz) {
|
||||
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) {
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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(),
|
||||
|
|
10
src/player.h
10
src/player.h
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "irrlichttypes_bloated.h"
|
||||
#include "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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 ¶ms)
|
|||
}
|
||||
|
||||
/******************************************************************************/
|
||||
u32 getflagsfield(lua_State *L, int table, const char *fieldname,
|
||||
FlagDesc *flagdesc, u32 *flagmask)
|
||||
|
||||
bool getflagsfield(lua_State *L, int table, const char *fieldname,
|
||||
FlagDesc *flagdesc, u32 *flags, u32 *flagmask)
|
||||
{
|
||||
u32 flags = 0;
|
||||
|
||||
lua_getfield(L, table, fieldname);
|
||||
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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[] =
|
||||
{
|
||||
|
|
|
@ -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) {}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ struct ItemDefinition;
|
|||
class LuaItemStack;
|
||||
class ModApiItemMod;
|
||||
class InventoryList;
|
||||
class InventoryLocation;
|
||||
struct InventoryLocation;
|
||||
|
||||
class ScriptApiItem
|
||||
: virtual public ScriptApiBase
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue