diff options
45 files changed, 1717 insertions, 162 deletions
diff --git a/builtin/builtin.lua b/builtin/builtin.lua index bf33cbe6b..f10c6c7cf 100644 --- a/builtin/builtin.lua +++ b/builtin/builtin.lua @@ -24,4 +24,5 @@ dofile(minetest.get_modpath("__builtin").."/chatcommands.lua") dofile(minetest.get_modpath("__builtin").."/static_spawn.lua") dofile(minetest.get_modpath("__builtin").."/detached_inventory.lua") dofile(minetest.get_modpath("__builtin").."/falling.lua") +dofile(minetest.get_modpath("__builtin").."/features.lua") diff --git a/builtin/chatcommands.lua b/builtin/chatcommands.lua index 9f14749f4..f548fb01d 100644 --- a/builtin/chatcommands.lua +++ b/builtin/chatcommands.lua @@ -675,7 +675,7 @@ minetest.register_chatcommand("msg", { if found then if minetest.env:get_player_by_name(sendto) then minetest.log("action", "PM from "..name.." to "..sendto..": "..message) - minetest.chat_send_player(sendto, "PM from "..name..": "..message) + minetest.chat_send_player(sendto, "PM from "..name..": "..message, false) minetest.chat_send_player(name, "Message sent") else minetest.chat_send_player(name, "The player "..sendto.." is not online") diff --git a/builtin/features.lua b/builtin/features.lua new file mode 100644 index 000000000..0eef2519d --- /dev/null +++ b/builtin/features.lua @@ -0,0 +1,28 @@ +-- Minetest: builtin/features.lua + +minetest.features = { + "glasslike_framed" = true, + "nodebox_as_selectionbox" = true, + "chat_send_player_param3" = true, + "get_all_craft_recipes_works" = true, + "use_texture_alpha" = true, +} + +function minetest.has_feature(arg) + if type(arg) == "table" then + missing_features = {} + result = true + for ft, _ in pairs(arg) do + if not minetest.features[ftr] then + missing_features[ftr] = true + result = false + end + end + return result, missing_features + elseif type(arg) == "string" then + if not minetest.features[arg] then + return false, {[arg]=true} + end + return true, {} + end +end diff --git a/client/shaders/test_shader_3/base.txt b/client/shaders/test_shader_3/base.txt new file mode 100644 index 000000000..1c2647118 --- /dev/null +++ b/client/shaders/test_shader_3/base.txt @@ -0,0 +1 @@ +trans_alphach diff --git a/client/shaders/test_shader_3/opengl_fragment.glsl b/client/shaders/test_shader_3/opengl_fragment.glsl new file mode 100644 index 000000000..535774c11 --- /dev/null +++ b/client/shaders/test_shader_3/opengl_fragment.glsl @@ -0,0 +1,25 @@ +
+uniform sampler2D myTexture;
+uniform float fogDistance;
+
+varying vec3 vPosition;
+
+void main (void)
+{
+ vec4 col = texture2D(myTexture, vec2(gl_TexCoord[0]));
+ col *= gl_Color;
+ float a = col.a; + col = col * col; // SRGB -> Linear
+ col *= 1.8;
+ col.r = 1.0 - exp(1.0 - col.r) / exp(1.0);
+ col.g = 1.0 - exp(1.0 - col.g) / exp(1.0);
+ col.b = 1.0 - exp(1.0 - col.b) / exp(1.0); + col = sqrt(col); // Linear -> SRGB + + if(fogDistance != 0.0){
+ float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
+ a = mix(a, 0.0, d);
+ } +
+ gl_FragColor = vec4(col.r, col.g, col.b, a);
+}
diff --git a/client/shaders/test_shader_3/opengl_vertex.glsl b/client/shaders/test_shader_3/opengl_vertex.glsl new file mode 100644 index 000000000..2881bad21 --- /dev/null +++ b/client/shaders/test_shader_3/opengl_vertex.glsl @@ -0,0 +1,51 @@ +
+uniform mat4 mWorldViewProj;
+uniform mat4 mInvWorld;
+uniform mat4 mTransWorld;
+uniform float dayNightRatio;
+
+varying vec3 vPosition;
+
+void main(void)
+{
+ gl_Position = mWorldViewProj * gl_Vertex;
+
+ vPosition = (mWorldViewProj * gl_Vertex).xyz;
+
+ 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 * 1.0; // Make light sources brighter
+ float b = rg;
+
+ // Moonlight is blue
+ b += (day - night) / 13.0;
+ rg -= (day - night) / 13.0;
+
+ // Emphase blue a bit in darker places
+ // See C++ implementation in mapblock_mesh.cpp finalColorBlend()
+ b += max(0.0, (1.0 - abs(b - 0.13)/0.17) * 0.025);
+
+ // Artificial light is yellow-ish
+ // See C++ implementation in mapblock_mesh.cpp finalColorBlend()
+ rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);
+
+ color.r = rg;
+ color.g = rg;
+ color.b = b;
+
+ color.a = gl_Color.a;
+
+ gl_FrontColor = gl_BackColor = color;
+
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+}
diff --git a/doc/lua_api.txt b/doc/lua_api.txt index aa4503879..597f98c2c 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -329,6 +329,7 @@ Look for examples in games/minimal or games/minetest_game. - liquid - flowingliquid - glasslike +- glasslike_framed - allfaces - allfaces_optional - torchlike @@ -409,6 +410,12 @@ ranging in value from 0 to 1. The name field is not yet used, but should contain a description of what the HUD element represents. The direction field is the direction in which something is drawn. 0 draws from left to right, 1 draws from right to left, 2 draws from top to bottom, and 3 draws from bottom to top. +The alignment field specifies how the item will be aligned. It ranges from -1 to 1, +with 0 being the center, -1 is moved to the left/up, and 1 is to the right/down. Fractional +values can be used. +The offset field specifies a pixel offset from the position. Contrary to position, +the offset is not scaled to screen size. This allows for some precisely-positioned +items in the HUD. Below are the specific uses for fields in each type; fields not listed for that type are ignored. Note: Future revisions to the HUD API may be incompatible; the HUD API is still in the experimental stages. @@ -418,6 +425,8 @@ Note: Future revisions to the HUD API may be incompatible; the HUD API is still - scale: The scale of the image, with 1 being the original texture size. Only the X coordinate scale is used. - text: The name of the texture that is displayed. + - alignment: The alignment of the image. + - offset: offset in pixels from position. - text Displays text on the HUD. - scale: Defines the bounding rectangle of the text. @@ -425,12 +434,15 @@ Note: Future revisions to the HUD API may be incompatible; the HUD API is still - text: The text to be displayed in the HUD element. - number: An integer containing the RGB value of the color used to draw the text. Specify 0xFFFFFF for white text, 0xFF0000 for red, and so on. + - alignment: The alignment of the text. + - offset: offset in pixels from position. - statbar Displays a horizontal bar made up of half-images. - text: The name of the texture that is used. - number: The number of half-textures that are displayed. If odd, will end with a vertically center-split texture. - direction + - offset: offset in pixels from position. - inventory - text: The name of the inventory list to be displayed. - number: Number of items in the inventory to be displayed. @@ -900,6 +912,11 @@ minetest.get_modnames() -> list of installed mods minetest.get_worldpath() -> eg. "/home/user/.minetest/world" ^ Useful for storing custom data minetest.is_singleplayer() +minetest.features +^ table containing API feature flags: {foo=true, bar=true} +minetest.has_feature(arg) -> bool, missing_features +^ arg: string or table in format {foo=true, bar=true} +^ missing_features: {foo=true, bar=true} minetest.debug(line) ^ Always printed to stderr and logfile (print() is redirected here) @@ -991,10 +1008,12 @@ minetest.auth_reload() ^ These call the authentication handler minetest.check_player_privs(name, {priv1=true,...}) -> bool, missing_privs ^ A quickhand for checking privileges +minetest.get_player_ip(name) -> IP address string Chat: minetest.chat_send_all(text) -minetest.chat_send_player(name, text) +minetest.chat_send_player(name, text, prepend) +^ prepend: optional, if it is set to false "Server -!- " will not be prepended to the message Inventory: minetest.get_inventory(location) -> InvRef @@ -1420,6 +1439,10 @@ Player-only: (no-op for other objects) - hud_change(id, stat, value): change a value of a previously added HUD element ^ element stat values: position, name, scale, text, number, item, dir - hud_get(id): gets the HUD element definition structure of the specified ID +- hud_set_flags(flags): sets specified HUD flags to true/false + ^ flags: (is visible) hotbar, healthbar, crosshair, wielditem + ^ pass a table containing a true/false value of each flag to be set or unset + ^ if a flag is nil, the flag is not modified InvRef: Reference to an inventory methods: @@ -1636,6 +1659,7 @@ Node definition (register_node) ^ Special textures of node; used rarely (old field name: special_materials) ^ List can be shortened to needed length alpha = 255, + use_texture_alpha = false, -- Use texture's alpha channel post_effect_color = {a=0, r=0, g=0, b=0}, -- If player is inside node paramtype = "none", -- See "Nodes" paramtype2 = "none", -- See "Nodes" @@ -1857,4 +1881,8 @@ HUD Definition (hud_add, hud_get) ^ Selected item in inventory. 0 for no item selected. direction = 0, ^ Direction: 0: left-right, 1: right-left, 2: top-bottom, 3: bottom-top + alignment = {x=0, y=0}, + ^ See "HUD Element Types" + offset = {x=0, y=0}, + ^ See "HUD Element Types" } diff --git a/minetest.conf.example b/minetest.conf.example index 838987c33..36ef31459 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -136,6 +136,8 @@ #screenshot_path = . # Amount of view bobbing (0 = no view bobbing, 1.0 = normal, 2.0 = double) #view_bobbing_amount = 1.0 +# Amount of fall bobbing (0 = no fall bobbing, 1.0 = normal, 2.0 = double) +#fall_bobbing_amount = 0.0 # Anaglyph stereo #anaglyph = false #anaglyph_strength = 0.1 diff --git a/po/no/minetest.po b/po/no/minetest.po new file mode 100644 index 000000000..58d0d95c9 --- /dev/null +++ b/po/no/minetest.po @@ -0,0 +1,757 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: minetest\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-03-30 19:56+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: src/guiConfigureWorld.cpp:125 +msgid "" +"Warning: Some mods are not configured yet.\n" +"They will be enabled by default when you save the configuration. " +msgstr "" + +#: src/guiConfigureWorld.cpp:144 +msgid "" +"Warning: Some configured mods are missing.\n" +"Their setting will be removed when you save the configuration. " +msgstr "" + +#: src/guiConfigureWorld.cpp:208 +msgid "enabled" +msgstr "" + +#: src/guiConfigureWorld.cpp:215 +msgid "Enable All" +msgstr "" + +#: src/guiConfigureWorld.cpp:222 +msgid "Disable All" +msgstr "" + +#: src/guiConfigureWorld.cpp:228 +msgid "depends on:" +msgstr "" + +#: src/guiConfigureWorld.cpp:240 +msgid "is required by:" +msgstr "" + +#: src/guiConfigureWorld.cpp:262 src/guiCreateWorld.cpp:165 +#: src/guiKeyChangeMenu.cpp:179 src/keycode.cpp:223 +msgid "Cancel" +msgstr "" + +#: src/guiConfigureWorld.cpp:268 src/guiKeyChangeMenu.cpp:173 +msgid "Save" +msgstr "" + +#: src/guiConfigureWorld.cpp:394 +msgid "Configuration saved. " +msgstr "" + +#: src/guiConfigureWorld.cpp:402 +msgid "Warning: Configuration not consistent. " +msgstr "" + +#: src/guiConfirmMenu.cpp:120 +msgid "Yes" +msgstr "" + +#: src/guiConfirmMenu.cpp:126 +msgid "No" +msgstr "" + +#: src/guiCreateWorld.cpp:116 +msgid "World name" +msgstr "" + +#: src/guiCreateWorld.cpp:135 +msgid "Game" +msgstr "" + +#: src/guiCreateWorld.cpp:159 +msgid "Create" +msgstr "" + +#: src/guiDeathScreen.cpp:96 +msgid "You died." +msgstr "" + +#: src/guiDeathScreen.cpp:104 +msgid "Respawn" +msgstr "" + +#: src/guiFormSpecMenu.cpp:582 +msgid "Left click: Move all items, Right click: Move single item" +msgstr "" + +#: src/guiFormSpecMenu.cpp:607 src/guiMessageMenu.cpp:109 +#: src/guiTextInputMenu.cpp:131 +msgid "Proceed" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:114 +msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:151 +msgid "\"Use\" = climb down" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:164 +msgid "Double tap \"jump\" to toggle fly" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:269 +msgid "Key already in use" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:347 +msgid "press key" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:372 +msgid "Forward" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:373 +msgid "Backward" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:228 +msgid "Left" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:375 src/keycode.cpp:228 +msgid "Right" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:376 +msgid "Use" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:377 +msgid "Jump" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:378 +msgid "Sneak" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:379 +msgid "Drop" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:380 +msgid "Inventory" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:381 +msgid "Chat" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:382 +msgid "Command" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:383 +msgid "Console" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:384 +msgid "Toggle fly" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:385 +msgid "Toggle fast" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:386 +msgid "Toggle noclip" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:387 +msgid "Range select" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:388 +msgid "Print stacks" +msgstr "" + +#: src/guiMainMenu.cpp:92 +msgid "Cannot create world: Name contains invalid characters" +msgstr "" + +#: src/guiMainMenu.cpp:101 +msgid "Cannot create world: A world by this name already exists" +msgstr "" + +#: src/guiMainMenu.cpp:283 +msgid "Singleplayer" +msgstr "" + +#: src/guiMainMenu.cpp:284 +msgid "Multiplayer" +msgstr "" + +#: src/guiMainMenu.cpp:285 +msgid "Advanced" +msgstr "" + +#: src/guiMainMenu.cpp:286 +msgid "Settings" +msgstr "" + +#: src/guiMainMenu.cpp:287 +msgid "Credits" +msgstr "" + +#: src/guiMainMenu.cpp:317 +msgid "Select World:" +msgstr "" + +#: src/guiMainMenu.cpp:339 src/guiMainMenu.cpp:511 src/keycode.cpp:229 +msgid "Delete" +msgstr "" + +#: src/guiMainMenu.cpp:346 +msgid "New" +msgstr "" + +#: src/guiMainMenu.cpp:354 +msgid "Configure" +msgstr "" + +#: src/guiMainMenu.cpp:369 src/keycode.cpp:248 +msgid "Play" +msgstr "" + +#: src/guiMainMenu.cpp:380 src/guiMainMenu.cpp:619 +msgid "Creative Mode" +msgstr "" + +#: src/guiMainMenu.cpp:386 src/guiMainMenu.cpp:625 +msgid "Enable Damage" +msgstr "" + +#: src/guiMainMenu.cpp:406 src/guiMainMenu.cpp:541 +msgid "Name/Password" +msgstr "" + +#: src/guiMainMenu.cpp:442 src/guiMainMenu.cpp:459 src/guiMainMenu.cpp:1184 +msgid "Favorites:" +msgstr "" + +#: src/guiMainMenu.cpp:450 src/guiMainMenu.cpp:1194 +msgid "Public Server List:" +msgstr "" + +#: src/guiMainMenu.cpp:470 src/guiMainMenu.cpp:568 +msgid "Address/Port" +msgstr "" + +#: src/guiMainMenu.cpp:497 src/guiMainMenu.cpp:1183 +msgid "Show Public" +msgstr "" + +#: src/guiMainMenu.cpp:501 src/guiMainMenu.cpp:1193 +msgid "Show Favorites" +msgstr "" + +#: src/guiMainMenu.cpp:521 +msgid "Connect" +msgstr "" + +#: src/guiMainMenu.cpp:591 +msgid "Leave address blank to start a local server." +msgstr "" + +#: src/guiMainMenu.cpp:600 +msgid "Start Game / Connect" +msgstr "" + +#: src/guiMainMenu.cpp:632 +msgid "Public" +msgstr "" + +#: src/guiMainMenu.cpp:640 src/guiMainMenu.cpp:1113 +msgid "Delete world" +msgstr "" + +#: src/guiMainMenu.cpp:647 +msgid "Create world" +msgstr "" + +#: src/guiMainMenu.cpp:681 +msgid "Fancy trees" +msgstr "" + +#: src/guiMainMenu.cpp:687 +msgid "Smooth Lighting" +msgstr "" + +#: src/guiMainMenu.cpp:693 +msgid "3D Clouds" +msgstr "" + +#: src/guiMainMenu.cpp:699 +msgid "Opaque water" +msgstr "" + +#: src/guiMainMenu.cpp:709 +msgid "Mip-Mapping" +msgstr "" + +#: src/guiMainMenu.cpp:716 +msgid "Anisotropic Filtering" +msgstr "" + +#: src/guiMainMenu.cpp:723 +msgid "Bi-Linear Filtering" +msgstr "" + +#: src/guiMainMenu.cpp:730 +msgid "Tri-Linear Filtering" +msgstr "" + +#: src/guiMainMenu.cpp:738 +msgid "Shaders" +msgstr "" + +#: src/guiMainMenu.cpp:745 +msgid "Preload item visuals" +msgstr "" + +#: src/guiMainMenu.cpp:752 +msgid "Enable Particles" +msgstr "" + +#: src/guiMainMenu.cpp:759 +msgid "Finite liquid" +msgstr "" + +#: src/guiMainMenu.cpp:769 +msgid "Change keys" +msgstr "" + +#: src/guiMainMenu.cpp:1084 +msgid "Address required." +msgstr "" + +#: src/guiMainMenu.cpp:1102 +msgid "Cannot delete world: Nothing selected" +msgstr "" + +#: src/guiMainMenu.cpp:1117 +msgid "Files to be deleted" +msgstr "" + +#: src/guiMainMenu.cpp:1133 +msgid "Cannot create world: No games found" +msgstr "" + +#: src/guiMainMenu.cpp:1149 +msgid "Cannot configure world: Nothing selected" +msgstr "" + +#: src/guiMainMenu.cpp:1256 +msgid "Failed to delete all world files" +msgstr "" + +#: src/guiPasswordChange.cpp:108 +msgid "Old Password" +msgstr "" + +#: src/guiPasswordChange.cpp:125 +msgid "New Password" +msgstr "" + +#: src/guiPasswordChange.cpp:141 +msgid "Confirm Password" +msgstr "" + +#: src/guiPasswordChange.cpp:158 +msgid "Change" +msgstr "" + +#: src/guiPasswordChange.cpp:167 +msgid "Passwords do not match!" +msgstr "" + +#: src/guiPauseMenu.cpp:123 +msgid "Continue" +msgstr "" + +#: src/guiPauseMenu.cpp:132 +msgid "Change Password" +msgstr "" + +#: src/guiPauseMenu.cpp:140 +msgid "Sound Volume" +msgstr "" + +#: src/guiPauseMenu.cpp:147 +msgid "Exit to Menu" +msgstr "" + +#: src/guiPauseMenu.cpp:154 +msgid "Exit to OS" +msgstr "" + +#: src/guiPauseMenu.cpp:161 +msgid "" +"Default Controls:\n" +"- WASD: Walk\n" +"- Mouse left: dig/hit\n" +"- Mouse right: place/use\n" +"- Mouse wheel: select item\n" +"- 0...9: select item\n" +"- Shift: sneak\n" +"- R: Toggle viewing all loaded chunks\n" +"- I: Inventory menu\n" +"- ESC: This menu\n" +"- T: Chat\n" +msgstr "" + +#: src/guiVolumeChange.cpp:108 +msgid "Sound Volume: " +msgstr "" + +#: src/guiVolumeChange.cpp:121 +msgid "Exit" +msgstr "" + +#: src/keycode.cpp:223 +msgid "Left Button" +msgstr "" + +#: src/keycode.cpp:223 +msgid "Middle Button" +msgstr "" + +#: src/keycode.cpp:223 +msgid "Right Button" +msgstr "" + +#: src/keycode.cpp:223 +msgid "X Button 1" +msgstr "" + +#: src/keycode.cpp:224 +msgid "Back" +msgstr "" + +#: src/keycode.cpp:224 +msgid "Clear" +msgstr "" + +#: src/keycode.cpp:224 +msgid "Return" +msgstr "" + +#: src/keycode.cpp:224 +msgid "Tab" +msgstr "" + +#: src/keycode.cpp:224 +msgid "X Button 2" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Capital" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Control" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Kana" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Menu" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Pause" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Shift" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Convert" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Escape" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Final" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Junja" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Kanji" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Nonconvert" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Accept" +msgstr "" + +#: src/keycode.cpp:227 +msgid "End" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Home" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Mode Change" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Next" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Prior" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Space" +msgstr "" + +#: src/keycode.cpp:228 +msgid "Down" +msgstr "" + +#: src/keycode.cpp:228 +msgid "Execute" +msgstr "" + +#: src/keycode.cpp:228 +msgid "Print" +msgstr "" + +#: src/keycode.cpp:228 +msgid "Select" +msgstr "" + +#: src/keycode.cpp:228 +msgid "Up" +msgstr "" + +#: src/keycode.cpp:229 +msgid "Help" +msgstr "" + +#: src/keycode.cpp:229 +msgid "Insert" +msgstr "" + +#: src/keycode.cpp:229 +msgid "Snapshot" +msgstr "" + +#: src/keycode.cpp:232 +msgid "Left Windows" +msgstr "" + +#: src/keycode.cpp:233 +msgid "Apps" +msgstr "" + +#: src/keycode.cpp:233 +msgid "Numpad 0" +msgstr "" + +#: src/keycode.cpp:233 +msgid "Numpad 1" +msgstr "" + +#: src/keycode.cpp:233 +msgid "Right Windows" +msgstr "" + +#: src/keycode.cpp:233 +msgid "Sleep" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 2" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 3" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 4" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 5" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 6" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 7" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad *" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad +" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad -" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad /" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad 8" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad 9" +msgstr "" + +#: src/keycode.cpp:239 +msgid "Num Lock" +msgstr "" + +#: src/keycode.cpp:239 +msgid "Scroll Lock" +msgstr "" + +#: src/keycode.cpp:240 +msgid "Left Shift" +msgstr "" + +#: src/keycode.cpp:240 +msgid "Right Shift" +msgstr "" + +#: src/keycode.cpp:241 +msgid "Left Control" +msgstr "" + +#: src/keycode.cpp:241 +msgid "Left Menu" +msgstr "" + +#: src/keycode.cpp:241 +msgid "Right Control" +msgstr "" + +#: src/keycode.cpp:241 +msgid "Right Menu" +msgstr "" + +#: src/keycode.cpp:243 +msgid "Comma" +msgstr "" + +#: src/keycode.cpp:243 +msgid "Minus" +msgstr "" + +#: src/keycode.cpp:243 +msgid "Period" +msgstr "" + +#: src/keycode.cpp:243 +msgid "Plus" +msgstr "" + +#: src/keycode.cpp:247 +msgid "Attn" +msgstr "" + +#: src/keycode.cpp:247 +msgid "CrSel" +msgstr "" + +#: src/keycode.cpp:248 +msgid "Erase OEF" +msgstr "" + +#: src/keycode.cpp:248 +msgid "ExSel" +msgstr "" + +#: src/keycode.cpp:248 +msgid "OEM Clear" +msgstr "" + +#: src/keycode.cpp:248 +msgid "PA1" +msgstr "" + +#: src/keycode.cpp:248 +msgid "Zoom" +msgstr "" + +#: src/main.cpp:1506 +msgid "Main Menu" +msgstr "" + +#: src/main.cpp:1830 +msgid "Failed to initialize world" +msgstr "" + +#: src/main.cpp:1842 +msgid "No world selected and no address provided. Nothing to do." +msgstr "" + +#: src/main.cpp:1850 +msgid "Could not find or load game \"" +msgstr "" + +#: src/main.cpp:1864 +msgid "Invalid gamespec." +msgstr "" + +#: src/main.cpp:1904 +msgid "Connection error (timed out?)" +msgstr "" + +#: src/main.cpp:1915 +msgid "" +"\n" +"Check debug.txt for details." +msgstr "" diff --git a/src/camera.cpp b/src/camera.cpp index 211ecfd70..6224a2b8e 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -263,6 +263,8 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize, fall_bobbing = sin(fall_bobbing * 0.5 * M_PI) * -1; // Amplify according to the intensity of the impact fall_bobbing *= (1 - rangelim(50 / player->camera_impact, 0, 1)) * 5; + + fall_bobbing *= g_settings->getFloat("fall_bobbing_amount"); } // Set head node transformation diff --git a/src/cavegen.cpp b/src/cavegen.cpp index bef50c7a7..01543252a 100644 --- a/src/cavegen.cpp +++ b/src/cavegen.cpp @@ -20,18 +20,21 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/numeric.h" #include "map.h" #include "mapgen.h" +#include "mapgen_v6.h" +#include "mapgen_v7.h" #include "cavegen.h" -CaveV6::CaveV6(Mapgen *mg, PseudoRandom *ps, PseudoRandom *ps2, - bool is_large_cave, content_t c_water, content_t c_lava) { - this->vm = mg->vm; +CaveV6::CaveV6(MapgenV6 *mg, PseudoRandom *ps, PseudoRandom *ps2, bool is_large_cave) { + this->mg = mg; + this->vm = mg->vm; + this->ndef = mg->ndef; this->water_level = mg->water_level; this->large_cave = is_large_cave; this->ps = ps; this->ps2 = ps2; - this->c_water_source = c_water; - this->c_lava_source = c_lava; + this->c_water_source = mg->c_water_source; + this->c_lava_source = mg->c_lava_source; min_tunnel_diameter = 2; max_tunnel_diameter = ps->range(2, 6); @@ -152,13 +155,6 @@ void CaveV6::makeTunnel(bool dirswitch) { ); } - /*if(large_cave){ - v3f p = orp + vec; - s16 h = find_ground_level_clever(vmanip, v2s16(p.X, p.Z), ndef); - route_y_min = h - rs/3; - route_y_max = h + rs; - }*/ - vec += main_direction; v3f rp = orp + vec; @@ -181,7 +177,7 @@ void CaveV6::makeTunnel(bool dirswitch) { float veclen = vec.getLength(); // As odd as it sounds, veclen is *exactly* 0.0 sometimes, causing a FPE - if (veclen == 0.0) + if (veclen < 0.05) veclen = 1.0; // Every second section is rough @@ -220,11 +216,7 @@ void CaveV6::carveRoute(v3f vec, float f, bool randomize_xz) { for (s16 x0 = -si - ps->range(0,1); x0 <= si - 1 + ps->range(0,1); x0++) { s16 maxabsxz = MYMAX(abs(x0), abs(z0)); s16 si2 = rs / 2 - MYMAX(0, maxabsxz - rs / 7 - 1); - for (s16 y0 = -si2; y0 <= si2; y0++) { - // Make better floors in small caves - //if(y0 <= -rs/2 && rs<=7) - // continue; - + for (s16 y0 = -si2; y0 <= si2; y0++) { if (large_cave_is_flat) { // Make large caves not so tall if (rs > 7 && abs(y0) >= rs / 3) @@ -242,7 +234,7 @@ void CaveV6::carveRoute(v3f vec, float f, bool randomize_xz) { if (large_cave) { int full_ymin = node_min.Y - MAP_BLOCKSIZE; int full_ymax = node_max.Y + MAP_BLOCKSIZE; - + if (flooded && full_ymin < water_level && full_ymax > water_level) { vm->m_data[i] = (p.Y <= water_level) ? waternode : airnode; } else if (flooded && full_ymax < water_level) { @@ -264,3 +256,278 @@ void CaveV6::carveRoute(v3f vec, float f, bool randomize_xz) { } } } + + +///////////////////////////////////////// Caves V7 + +CaveV7::CaveV7(MapgenV7 *mg, PseudoRandom *ps, bool is_large_cave) { + this->mg = mg; + this->vm = mg->vm; + this->ndef = mg->ndef; + this->water_level = mg->water_level; + this->large_cave = is_large_cave; + this->ps = ps; + this->c_water_source = mg->c_water_source; + this->c_lava_source = mg->c_lava_source; + + dswitchint = ps->range(1, 14); + flooded = ps->range(1, 2) == 2; + + if (large_cave) { + part_max_length_rs = ps->range(2, 4); + tunnel_routepoints = ps->range(5, ps->range(15, 30)); + min_tunnel_diameter = 5; + max_tunnel_diameter = ps->range(7, ps->range(8, 24)); + } else { + part_max_length_rs = ps->range(2, 9); + tunnel_routepoints = ps->range(10, ps->range(15, 30)); + min_tunnel_diameter = 2; + max_tunnel_diameter = ps->range(2, 6); + } + + large_cave_is_flat = (ps->range(0, 1) == 0); +} + + +void CaveV7::makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height) { + node_min = nmin; + node_max = nmax; + max_stone_y = max_stone_height; + main_direction = v3f(0, 0, 0); + + // Allowed route area size in nodes + ar = node_max - node_min + v3s16(1, 1, 1); + // Area starting point in nodes + of = node_min; + + // Allow a bit more + //(this should be more than the maximum radius of the tunnel) + s16 insure = 10; + s16 more = MAP_BLOCKSIZE - max_tunnel_diameter / 2 - insure; + ar += v3s16(1,0,1) * more * 2; + of -= v3s16(1,0,1) * more; + + route_y_min = 0; + // Allow half a diameter + 7 over stone surface + route_y_max = -of.Y + max_stone_y + max_tunnel_diameter / 2 + 7; + + // Limit maximum to area + route_y_max = rangelim(route_y_max, 0, ar.Y - 1); + + if (large_cave) { + s16 min = 0; + if (node_min.Y < water_level && node_max.Y > water_level) { + min = water_level - max_tunnel_diameter/3 - of.Y; + route_y_max = water_level + max_tunnel_diameter/3 - of.Y; + } + route_y_min = ps->range(min, min + max_tunnel_diameter); + route_y_min = rangelim(route_y_min, 0, route_y_max); + } + + s16 route_start_y_min = route_y_min; + s16 route_start_y_max = route_y_max; + + route_start_y_min = rangelim(route_start_y_min, 0, ar.Y - 1); + route_start_y_max = rangelim(route_start_y_max, route_start_y_min, ar.Y - 1); + + // Randomize starting position + orp = v3f( + (float)(ps->next() % ar.X) + 0.5, + (float)(ps->range(route_start_y_min, route_start_y_max)) + 0.5, + (float)(ps->next() % ar.Z) + 0.5 + ); + + // Generate some tunnel starting from orp + for (u16 j = 0; j < tunnel_routepoints; j++) + makeTunnel(j % dswitchint == 0); +} + + +void CaveV7::makeTunnel(bool dirswitch) { + if (dirswitch && !large_cave) { + main_direction = v3f( + ((float)(ps->next() % 20) - (float)10) / 10, + ((float)(ps->next() % 20) - (float)10) / 30, + ((float)(ps->next() % 20) - (float)10) / 10 + ); + main_direction *= (float)ps->range(0, 10) / 10; + } + + // Randomize size + s16 min_d = min_tunnel_diameter; + s16 max_d = max_tunnel_diameter; + rs = ps->range(min_d, max_d); + + v3s16 maxlen; + if (large_cave) { + maxlen = v3s16( + rs * part_max_length_rs, + rs * part_max_length_rs / 2, + rs * part_max_length_rs + ); + } else { + maxlen = v3s16( + rs * part_max_length_rs, + ps->range(1, rs * part_max_length_rs), + rs * part_max_length_rs + ); + } + + v3f vec; + // Jump downward sometimes + if (!large_cave && ps->range(0, 12) == 0) { + vec = v3f( + (float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2, + (float)(ps->next() % (maxlen.Y * 2)) - (float)maxlen.Y, + (float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2 + ); + } else { + vec = v3f( + (float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2, + (float)(ps->next() % (maxlen.Y * 1)) - (float)maxlen.Y / 2, + (float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2 + ); + } + + // Do not make large caves that are above ground. + // It is only necessary to check the startpoint and endpoint. + if (large_cave) { + v3s16 orpi(orp.X, orp.Y, orp.Z); + v3s16 veci(vec.X, vec.Y, vec.Z); + v3s16 p; + + p = orpi + veci + of + rs / 2; + if (p.Z >= node_min.Z && p.Z <= node_max.Z && + p.X >= node_min.X && p.X <= node_max.X) { + u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X); + s16 h = mg->ridge_heightmap[index]; + if (h < p.Y) + return; + } else if (p.Y > water_level) { + return; // If it's not in our heightmap, use a simple heuristic + } + + p = orpi + of + rs / 2; + if (p.Z >= node_min.Z && p.Z <= node_max.Z && + p.X >= node_min.X && p.X <= node_max.X) { + u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X); + s16 h = mg->ridge_heightmap[index]; + if (h < p.Y) + return; + } else if (p.Y > water_level) { + return; + } + } + + vec += main_direction; + + v3f rp = orp + vec; + if (rp.X < 0) + rp.X = 0; + else if (rp.X >= ar.X) + rp.X = ar.X - 1; + + if (rp.Y < route_y_min) + rp.Y = route_y_min; + else if (rp.Y >= route_y_max) + rp.Y = route_y_max - 1; + + if (rp.Z < 0) + rp.Z = 0; + else if (rp.Z >= ar.Z) + rp.Z = ar.Z - 1; + + vec = rp - orp; + + float veclen = vec.getLength(); + if (veclen < 0.05) + veclen = 1.0; + + // Every second section is rough + bool randomize_xz = (ps->range(1, 2) == 1); + + // Make a ravine every once in a while if it's long enough + float xylen = vec.X * vec.X + vec.Z * vec.Z; + bool is_ravine = (xylen > 500.0) && !large_cave && (ps->range(1, 8) == 1); + + // Carve routes + for (float f = 0; f < 1.0; f += 1.0 / veclen) + carveRoute(vec, f, randomize_xz, is_ravine); + + orp = rp; +} + + +void CaveV7::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) { + MapNode airnode(CONTENT_AIR); + MapNode waternode(c_water_source); + MapNode lavanode(c_lava_source); + MapNode liquidnode = ps->range(0, 4) ? lavanode : waternode; + + v3s16 startp(orp.X, orp.Y, orp.Z); + startp += of; + + v3f fp = orp + vec * f; + fp.X += 0.1 * ps->range(-10, 10); + fp.Z += 0.1 * ps->range(-10, 10); + v3s16 cp(fp.X, fp.Y, fp.Z); + + s16 d0 = -rs/2; + s16 d1 = d0 + rs; + if (randomize_xz) { + d0 += ps->range(-1, 1); + d1 += ps->range(-1, 1); + } + + bool flat_cave_floor = !large_cave && ps->range(0, 2) == 2; + + for (s16 z0 = d0; z0 <= d1; z0++) { + s16 si = rs / 2 - MYMAX(0, abs(z0) - rs / 7 - 1); + for (s16 x0 = -si - ps->range(0,1); x0 <= si - 1 + ps->range(0,1); x0++) { + s16 maxabsxz = MYMAX(abs(x0), abs(z0)); + + s16 si2 = is_ravine ? MYMIN(ps->range(25, 26), ar.Y) : + rs / 2 - MYMAX(0, maxabsxz - rs / 7 - 1); + + for (s16 y0 = -si2; y0 <= si2; y0++) { + // Make better floors in small caves + if(flat_cave_floor && y0 <= -rs/2 && rs<=7) + continue; + + if (large_cave_is_flat) { + // Make large caves not so tall + if (rs > 7 && abs(y0) >= rs / 3) + continue; + } + + v3s16 p(cp.X + x0, cp.Y + y0, cp.Z + z0); + p += of; + + if (vm->m_area.contains(p) == false) + continue; + + u32 i = vm->m_area.index(p); + + // Don't replace air or water or lava + content_t c = vm->m_data[i].getContent(); + if (c == CONTENT_AIR || c == c_water_source || c == c_lava_source) + continue; + + if (large_cave) { + int full_ymin = node_min.Y - MAP_BLOCKSIZE; + int full_ymax = node_max.Y + MAP_BLOCKSIZE; + + if (flooded && full_ymin < water_level && full_ymax > water_level) + vm->m_data[i] = (p.Y <= water_level) ? waternode : airnode; + else if (flooded && full_ymax < water_level) + vm->m_data[i] = (p.Y < startp.Y - 4) ? liquidnode : airnode; + else + vm->m_data[i] = airnode; + } else { + vm->m_data[i] = airnode; + vm->m_flags[i] |= VMANIP_FLAG_CAVE; + } + } + } + } +} diff --git a/src/cavegen.h b/src/cavegen.h index 979226b3e..7822816d6 100644 --- a/src/cavegen.h +++ b/src/cavegen.h @@ -22,9 +22,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #define VMANIP_FLAG_CAVE VOXELFLAG_CHECKED1 +class MapgenV6; +class MapgenV7; + class CaveV6 { public: + MapgenV6 *mg; ManualMapVoxelManipulator *vm; + INodeDefManager *ndef; s16 min_tunnel_diameter; s16 max_tunnel_diameter; @@ -40,10 +45,10 @@ public: v3s16 node_min; v3s16 node_max; - v3f orp; //original point - v3s16 of; + v3f orp; // starting point, relative to caved space + v3s16 of; // absolute coordinates of caved space v3s16 ar; // allowed route area - s16 rs; // radius size + s16 rs; // tunnel radius size v3f main_direction; s16 route_y_min; @@ -58,11 +63,53 @@ public: int water_level; CaveV6() {} - CaveV6(Mapgen *mg, PseudoRandom *ps, PseudoRandom *ps2, bool large_cave, - content_t c_water, content_t c_lava); + CaveV6(MapgenV6 *mg, PseudoRandom *ps, PseudoRandom *ps2, bool large_cave); void makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height); void makeTunnel(bool dirswitch); void carveRoute(v3f vec, float f, bool randomize_xz); }; +class CaveV7 { +public: + MapgenV7 *mg; + ManualMapVoxelManipulator *vm; + INodeDefManager *ndef; + + s16 min_tunnel_diameter; + s16 max_tunnel_diameter; + u16 tunnel_routepoints; + int dswitchint; + int part_max_length_rs; + + bool large_cave; + bool large_cave_is_flat; + bool flooded; + + s16 max_stone_y; + v3s16 node_min; + v3s16 node_max; + + v3f orp; // starting point, relative to caved space + v3s16 of; // absolute coordinates of caved space + v3s16 ar; // allowed route area + s16 rs; // tunnel radius size + v3f main_direction; + + s16 route_y_min; + s16 route_y_max; + + PseudoRandom *ps; + + content_t c_water_source; + content_t c_lava_source; + + int water_level; + + CaveV7() {} + CaveV7(MapgenV7 *mg, PseudoRandom *ps, bool large_cave); + void makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height); + void makeTunnel(bool dirswitch); + void carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine); +}; + #endif diff --git a/src/client.cpp b/src/client.cpp index 03a710599..56505c66c 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -45,6 +45,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "IMeshCache.h" #include "util/serialize.h" #include "config.h" +#include "util/directiontables.h" #if USE_CURL #include <curl/curl.h> @@ -2054,6 +2055,8 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) u32 number = readU32(is); u32 item = readU32(is); u32 dir = readU32(is); + v2f align = readV2F1000(is); + v2f offset = readV2F1000(is); ClientEvent event; event.type = CE_HUDADD; @@ -2066,6 +2069,8 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) event.hudadd.number = number; event.hudadd.item = item; event.hudadd.dir = dir; + event.hudadd.align = new v2f(align); + event.hudadd.offset = new v2f(offset); m_client_event_queue.push_back(event); } else if(command == TOCLIENT_HUDRM) @@ -2092,7 +2097,8 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) u32 id = readU32(is); u8 stat = (HudElementStat)readU8(is); - if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE) + if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE || + stat == HUD_STAT_ALIGN || stat == HUD_STAT_OFFSET) v2fdata = readV2F1000(is); else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT) sdata = deSerializeString(is); @@ -2108,6 +2114,20 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) event.hudchange.data = intdata; m_client_event_queue.push_back(event); } + else if(command == TOCLIENT_HUD_SET_FLAGS) + { + std::string datastring((char *)&data[2], datasize - 2); + std::istringstream is(datastring, std::ios_base::binary); + + Player *player = m_env.getLocalPlayer(); + assert(player != NULL); + + u32 flags = readU32(is); + u32 mask = readU32(is); + + player->hud_flags &= ~mask; + player->hud_flags |= flags; + } else { infostream<<"Client: Ignoring unknown command " @@ -2719,21 +2739,14 @@ void Client::addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server, bool } catch(InvalidPositionException &e){} // Leading edge - try{ - v3s16 p = blockpos + v3s16(-1,0,0); - addUpdateMeshTask(p, false, urgent); - } - catch(InvalidPositionException &e){} - try{ - v3s16 p = blockpos + v3s16(0,-1,0); - addUpdateMeshTask(p, false, urgent); - } - catch(InvalidPositionException &e){} - try{ - v3s16 p = blockpos + v3s16(0,0,-1); - addUpdateMeshTask(p, false, urgent); + for (int i=0;i<6;i++) + { + try{ + v3s16 p = blockpos + g_6dirs[i]; + addUpdateMeshTask(p, false, urgent); + } + catch(InvalidPositionException &e){} } - catch(InvalidPositionException &e){} } void Client::addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server, bool urgent) diff --git a/src/client.h b/src/client.h index f59588680..67ba6c565 100644 --- a/src/client.h +++ b/src/client.h @@ -230,6 +230,8 @@ struct ClientEvent u32 number; u32 item; u32 dir; + v2f *align; + v2f *offset; } hudadd; struct{ u32 id; diff --git a/src/clientserver.h b/src/clientserver.h index 6f7bb4402..cfa87ada7 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -94,6 +94,7 @@ SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed); TOCLIENT_HUD_ADD TOCLIENT_HUD_RM TOCLIENT_HUD_CHANGE + TOCLIENT_HUD_BUILTIN_ENABLE */ #define LATEST_PROTOCOL_VERSION 20 @@ -452,15 +453,17 @@ enum ToClientCommand u32 number u32 item u32 dir + v2f1000 align + v2f1000 offset */ - TOCLIENT_HUDRM = 0x50, + TOCLIENT_HUDRM = 0x4a, /* u16 command u32 id */ - TOCLIENT_HUDCHANGE = 0x51, + TOCLIENT_HUDCHANGE = 0x4b, /* u16 command u32 id @@ -470,6 +473,13 @@ enum ToClientCommand u8[len] data | u32 data] */ + + TOCLIENT_HUD_SET_FLAGS = 0x4c, + /* + u16 command + u32 flags + u32 mask + */ }; enum ToServerCommand diff --git a/src/content_abm.cpp b/src/content_abm.cpp index ccd9ca19c..e20201dcf 100644 --- a/src/content_abm.cpp +++ b/src/content_abm.cpp @@ -51,11 +51,15 @@ public: ServerMap *map = &env->getServerMap(); MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0)); + content_t c_snow = ndef->getId("snow"); if(ndef->get(n_top).light_propagates && !ndef->get(n_top).isLiquid() && n_top.getLightBlend(env->getDayNightRatio(), ndef) >= 13) { - n.setContent(ndef->getId("mapgen_dirt_with_grass")); + if(c_snow != CONTENT_IGNORE && n_top.getContent() == c_snow) + n.setContent(ndef->getId("dirt_with_snow")); + else + n.setContent(ndef->getId("mapgen_dirt_with_grass")); map->addNodeWithEvent(p, n); } } diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index 84d5f067c..155b39ab6 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -740,8 +740,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, continue; // The face at Z+ - video::S3DVertex vertices[4] = - { + video::S3DVertex vertices[4] = { video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, ap.x0(), ap.y1()), video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, @@ -781,6 +780,132 @@ void mapblock_mesh_generate_special(MeshMakeData *data, collector.append(tile, vertices, 4, indices, 6); } break;} + case NDT_GLASSLIKE_FRAMED: + { + static const v3s16 dirs[6] = { + v3s16( 0, 1, 0), + v3s16( 0,-1, 0), + v3s16( 1, 0, 0), + v3s16(-1, 0, 0), + v3s16( 0, 0, 1), + v3s16( 0, 0,-1) + }; + 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); + video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source)); + v3f pos = intToFloat(p, BS); + static const float a=BS/2; + static const float b=.876*(BS/2); + static const aabb3f frame_edges[12] = { + aabb3f( b, b,-a, a, a, a), // y+ + aabb3f(-a, b,-a,-b, a, a), // y+ + aabb3f( b,-a,-a, a,-b, a), // y- + aabb3f(-a,-a,-a,-b,-b, a), // y- + aabb3f( b,-a, b, a, a, a), // x+ + aabb3f( b,-a,-a, a, a,-b), // x+ + aabb3f(-a,-a, b,-b, a, a), // x- + aabb3f(-a,-a,-a,-b, a,-b), // x- + aabb3f(-a, b, b, a, a, a), // z+ + aabb3f(-a,-a, b, a,-b, a), // z+ + aabb3f(-a,-a,-a, a,-b,-b), // z- + aabb3f(-a, b,-a, a, a,-b) // z- + }; + aabb3f glass_faces[6] = { + aabb3f(-a, a,-a, a, a, a), // y+ + aabb3f(-a,-a,-a, a,-a, a), // y- + aabb3f( a,-a,-a, a, a, a), // x+ + aabb3f(-a,-a,-a,-a, a, a), // x- + aabb3f(-a,-a, a, a, a, a), // z+ + aabb3f(-a,-a,-a, a, a,-a) // z- + }; + + int visible_faces[6] = {0,0,0,0,0,0}; + int nb[18] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + u8 i; + content_t current = n.getContent(); + content_t content; + MapNode n2; + v3s16 n2p; + for(i=0; i<18; i++) + { + n2p = blockpos_nodes + p + g_26dirs[i]; + n2 = data->m_vmanip.getNodeNoEx(n2p); + content_t n2c = n2.getContent(); + //TODO: remove CONTENT_IGNORE check when getNodeNoEx is fixed + if (n2c == current || n2c == CONTENT_IGNORE) + nb[i]=1; + } + for(i=0; i<6; i++) + { + n2p = blockpos_nodes + p + dirs[i]; + n2 = data->m_vmanip.getNodeNoEx(n2p); + content = n2.getContent(); + const ContentFeatures &f2 = nodedef->get(content); + if (content == CONTENT_AIR || f2.isLiquid()) + visible_faces[i]=1; + } + static const u8 nb_triplet[12*3] = { + 1,2, 7, 1,5, 6, 4,2,15, 4,5,14, + 2,0,11, 2,3,13, 5,0,10, 5,3,12, + 0,1, 8, 0,4,16, 3,4,17, 3,1, 9 + }; + + f32 tx1,ty1,tz1,tx2,ty2,tz2; + aabb3f box; + for(i=0; i<12; i++) + { + int edge_invisible; + if (nb[nb_triplet[i*3+2]]==1) + edge_invisible=nb[nb_triplet[i*3]] & nb[nb_triplet[i*3+1]]; + else + edge_invisible=nb[nb_triplet[i*3]] ^ nb[nb_triplet[i*3+1]]; + if (edge_invisible) + continue; + box=frame_edges[i]; + box.MinEdge += pos; + box.MaxEdge += pos; + tx1 = (box.MinEdge.X/BS)+0.5; + ty1 = (box.MinEdge.Y/BS)+0.5; + tz1 = (box.MinEdge.Z/BS)+0.5; + tx2 = (box.MaxEdge.X/BS)+0.5; + ty2 = (box.MaxEdge.Y/BS)+0.5; + tz2 = (box.MaxEdge.Z/BS)+0.5; + f32 txc1[24] = { + tx1, 1-tz2, tx2, 1-tz1, + tx1, tz1, tx2, tz2, + tz1, 1-ty2, tz2, 1-ty1, + 1-tz2, 1-ty2, 1-tz1, 1-ty1, + 1-tx2, 1-ty2, 1-tx1, 1-ty1, + tx1, 1-ty2, tx2, 1-ty1, + }; + makeCuboid(&collector, box, &tiles[0], 1, c, txc1); + } + for(i=0; i<6; i++) + { + if (visible_faces[i]==0) + continue; + box=glass_faces[i]; + box.MinEdge += pos; + box.MaxEdge += pos; + tx1 = (box.MinEdge.X/BS)+0.5; + ty1 = (box.MinEdge.Y/BS)+0.5; + tz1 = (box.MinEdge.Z/BS)+0.5; + tx2 = (box.MaxEdge.X/BS)+0.5; + ty2 = (box.MaxEdge.Y/BS)+0.5; + tz2 = (box.MaxEdge.Z/BS)+0.5; + f32 txc2[24] = { + tx1, 1-tz2, tx2, 1-tz1, + tx1, tz1, tx2, tz2, + tz1, 1-ty2, tz2, 1-ty1, + 1-tz2, 1-ty2, 1-tz1, 1-ty1, + 1-tx2, 1-ty2, 1-tx1, 1-ty1, + tx1, 1-ty2, tx2, 1-ty1, + }; + makeCuboid(&collector, box, &tiles[1], 1, c, txc2); + } + break;} case NDT_ALLFACES: { TileSpec tile_leaves = getNodeTile(n, p, diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 3526ecbd2..24a9186f7 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -1472,6 +1472,11 @@ std::string PlayerSAO::getPropertyPacket() } bool PlayerSAO::getCollisionBox(aabb3f *toset) { - //player collision handling is already done clientside no need to do it twice - return false; + //update collision box + *toset = m_player->getCollisionbox(); + + toset->MinEdge += m_base_position; + toset->MaxEdge += m_base_position; + + return true; } diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 9875c6ecb..09ec45697 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -107,6 +107,7 @@ void set_default_settings(Settings *settings) settings->setDefault("enable_clouds", "true"); settings->setDefault("screenshot_path", "."); settings->setDefault("view_bobbing_amount", "1.0"); + settings->setDefault("fall_bobbing_amount", "0.0"); settings->setDefault("enable_3d_clouds", "true"); settings->setDefault("cloud_height", "120"); settings->setDefault("menu_clouds", "true"); diff --git a/src/environment.cpp b/src/environment.cpp index fc7972b2c..438c9ef4f 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -1295,16 +1295,17 @@ bool isFreeServerActiveObjectId(u16 id, u16 getFreeServerActiveObjectId( std::map<u16, ServerActiveObject*> &objects) { - u16 new_id = 1; + //try to reuse id's as late as possible + static u16 last_used_id = 0; + u16 startid = last_used_id; for(;;) { - if(isFreeServerActiveObjectId(new_id, objects)) - return new_id; + last_used_id ++; + if(isFreeServerActiveObjectId(last_used_id, objects)) + return last_used_id; - if(new_id == 65535) + if(last_used_id == startid) return 0; - - new_id++; } } @@ -2296,16 +2297,17 @@ bool isFreeClientActiveObjectId(u16 id, u16 getFreeClientActiveObjectId( std::map<u16, ClientActiveObject*> &objects) { - u16 new_id = 1; + //try to reuse id's as late as possible + static u16 last_used_id = 0; + u16 startid = last_used_id; for(;;) { - if(isFreeClientActiveObjectId(new_id, objects)) - return new_id; + last_used_id ++; + if(isFreeClientActiveObjectId(last_used_id, objects)) + return last_used_id; - if(new_id == 65535) + if(last_used_id == startid) return 0; - - new_id++; } } diff --git a/src/game.cpp b/src/game.cpp index a2d94ac0a..189003e4c 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -2106,6 +2106,8 @@ void the_game( delete event.hudadd.name; delete event.hudadd.scale; delete event.hudadd.text; + delete event.hudadd.align; + delete event.hudadd.offset; continue; } @@ -2118,6 +2120,8 @@ void the_game( e->number = event.hudadd.number; e->item = event.hudadd.item; e->dir = event.hudadd.dir; + e->align = *event.hudadd.align; + e->offset = *event.hudadd.offset; if (id == nhudelem) player->hud.push_back(e); @@ -2128,6 +2132,8 @@ void the_game( delete event.hudadd.name; delete event.hudadd.scale; delete event.hudadd.text; + delete event.hudadd.align; + delete event.hudadd.offset; } else if (event.type == CE_HUDRM) { @@ -2169,6 +2175,12 @@ void the_game( case HUD_STAT_DIR: e->dir = event.hudchange.data; break; + case HUD_STAT_ALIGN: + e->align = *event.hudchange.v2fdata; + break; + case HUD_STAT_OFFSET: + e->offset = *event.hudchange.v2fdata; + break; } delete event.hudchange.v2fdata; @@ -3058,7 +3070,7 @@ void the_game( /* Wielded tool */ - if(show_hud) + if(show_hud && (player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE)) { // Warning: This clears the Z buffer. camera.drawWieldedTool(); diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index 431b40e63..06e7cdff7 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -57,6 +57,7 @@ const wchar_t *contrib_core_strs[] = { }; const wchar_t *contrib_active_strs[] = { + L"kahrl <kahrl@gmx.net>", L"sfan5 <sfan5@live.de>", L"sapier <sapier@gmx.net>", L"Vanessa Ezekowitz (VanessaE) <vanessaezekowitz@gmail.com>", @@ -69,7 +70,6 @@ const wchar_t *contrib_active_strs[] = { }; const wchar_t *contrib_previous_strs[] = { - L"kahrl <kahrl@gmx.net>", L"Giuseppe Bilotta (Oblomov) <giuseppe.bilotta@gmail.com>", L"Jonathan Neuschafer <j.neuschaefer@gmx.net>", L"Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net>", diff --git a/src/hud.cpp b/src/hud.cpp index 77cf23173..65c78ca50 100644 --- a/src/hud.cpp +++ b/src/hud.cpp @@ -45,6 +45,8 @@ Hud::Hud(video::IVideoDriver *driver, gui::IGUIEnvironment* guienv, hotbar_imagesize = 48; hotbar_itemcount = 8; + tsrc = gamedef->getTextureSource(); + v3f crosshair_color = g_settings->getV3F("crosshair_color"); u32 cross_r = rangelim(myround(crosshair_color.X), 0, 255); u32 cross_g = rangelim(myround(crosshair_color.Y), 0, 255); @@ -57,6 +59,8 @@ Hud::Hud(video::IVideoDriver *driver, gui::IGUIEnvironment* guienv, u32 sbox_g = rangelim(myround(selectionbox_color.Y), 0, 255); u32 sbox_b = rangelim(myround(selectionbox_color.Z), 0, 255); selectionbox_argb = video::SColor(255, sbox_r, sbox_g, sbox_b); + + use_crosshair_image = tsrc->isKnownSourceImage("crosshair.png"); } @@ -175,8 +179,7 @@ void Hud::drawLuaElements() { v2s32 pos(e->pos.X * screensize.X, e->pos.Y * screensize.Y); switch (e->type) { case HUD_ELEM_IMAGE: { - video::ITexture *texture = - gamedef->getTextureSource()->getTextureRaw(e->text); + video::ITexture *texture = tsrc->getTextureRaw(e->text); if (!texture) continue; @@ -186,6 +189,10 @@ void Hud::drawLuaElements() { core::rect<s32> rect(0, 0, imgsize.Width * e->scale.X, imgsize.Height * e->scale.X); rect += pos; + v2s32 offset((e->align.X - 1.0) * ((imgsize.Width * e->scale.X) / 2), + (e->align.Y - 1.0) * ((imgsize.Height * e->scale.X) / 2)); + rect += offset; + rect += v2s32(e->offset.X, e->offset.Y); driver->draw2DImage(texture, rect, core::rect<s32>(core::position2d<s32>(0,0), imgsize), NULL, colors, true); @@ -195,11 +202,17 @@ void Hud::drawLuaElements() { (e->number >> 8) & 0xFF, (e->number >> 0) & 0xFF); core::rect<s32> size(0, 0, e->scale.X, text_height * e->scale.Y); - font->draw(narrow_to_wide(e->text).c_str(), size + pos, color); + std::wstring text = narrow_to_wide(e->text); + core::dimension2d<u32> textsize = font->getDimension(text.c_str()); + v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2), + (e->align.Y - 1.0) * (textsize.Height / 2)); + v2s32 offs(e->offset.X, e->offset.Y); + font->draw(text.c_str(), size + pos + offset + offs, color); + break; } + case HUD_ELEM_STATBAR: { + v2s32 offs(e->offset.X, e->offset.Y); + drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number, offs); break; } - case HUD_ELEM_STATBAR: - drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number); - break; case HUD_ELEM_INVENTORY: { InventoryList *inv = inventory->getList(e->text); drawItem(pos, hotbar_imagesize, e->number, inv, e->item, e->dir); @@ -212,12 +225,11 @@ void Hud::drawLuaElements() { } -void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s32 count) { +void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s32 count, v2s32 offset) { const video::SColor color(255, 255, 255, 255); const video::SColor colors[] = {color, color, color, color}; - video::ITexture *stat_texture = - gamedef->getTextureSource()->getTextureRaw(texture); + video::ITexture *stat_texture = tsrc->getTextureRaw(texture); if (!stat_texture) return; @@ -227,6 +239,8 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s if (corner & HUD_CORNER_LOWER) p -= srcd.Height; + p += offset; + v2s32 steppos; switch (drawdir) { case HUD_DIR_RIGHT_LEFT: @@ -276,17 +290,32 @@ void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem) { s32 width = hotbar_itemcount * (hotbar_imagesize + padding * 2); v2s32 pos = centerlowerpos - v2s32(width / 2, hotbar_imagesize + padding * 2); - drawItem(pos, hotbar_imagesize, hotbar_itemcount, mainlist, playeritem + 1, 0); - drawStatbar(pos - v2s32(0, 4), HUD_CORNER_LOWER, HUD_DIR_LEFT_RIGHT, - "heart.png", halfheartcount); + if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) + drawItem(pos, hotbar_imagesize, hotbar_itemcount, mainlist, playeritem + 1, 0); + if (player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE) + drawStatbar(pos - v2s32(0, 4), HUD_CORNER_LOWER, HUD_DIR_LEFT_RIGHT, + "heart.png", halfheartcount, v2s32(0, 0)); } void Hud::drawCrosshair() { - driver->draw2DLine(displaycenter - v2s32(10, 0), - displaycenter + v2s32(10, 0), crosshair_argb); - driver->draw2DLine(displaycenter - v2s32(0, 10), - displaycenter + v2s32(0, 10), crosshair_argb); + if (!(player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE)) + return; + + if (use_crosshair_image) { + video::ITexture *crosshair = tsrc->getTextureRaw("crosshair.png"); + v2u32 size = crosshair->getOriginalSize(); + v2s32 lsize = v2s32(displaycenter.X - (size.X / 2), + displaycenter.Y - (size.Y / 2)); + driver->draw2DImage(crosshair, lsize, + core::rect<s32>(0, 0, size.X, size.Y), + 0, crosshair_argb, true); + } else { + driver->draw2DLine(displaycenter - v2s32(10, 0), + displaycenter + v2s32(10, 0), crosshair_argb); + driver->draw2DLine(displaycenter - v2s32(0, 10), + displaycenter + v2s32(0, 10), crosshair_argb); + } } @@ -31,6 +31,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #define HUD_CORNER_LOWER 1 #define HUD_CORNER_CENTER 2 +#define HUD_FLAG_HOTBAR_VISIBLE (1 << 0) +#define HUD_FLAG_HEALTHBAR_VISIBLE (1 << 1) +#define HUD_FLAG_CROSSHAIR_VISIBLE (1 << 2) +#define HUD_FLAG_WIELDITEM_VISIBLE (1 << 3) + class Player; enum HudElementType { @@ -47,7 +52,9 @@ enum HudElementStat { HUD_STAT_TEXT, HUD_STAT_NUMBER, HUD_STAT_ITEM, - HUD_STAT_DIR + HUD_STAT_DIR, + HUD_STAT_ALIGN, + HUD_STAT_OFFSET }; struct HudElement { @@ -59,6 +66,8 @@ struct HudElement { u32 number; u32 item; u32 dir; + v2f align; + v2f offset; }; @@ -73,8 +82,6 @@ inline u32 hud_get_free_id(Player *player) { #ifndef SERVER -#include <deque> - #include <IGUIFont.h> #include "gamedef.h" @@ -90,7 +97,8 @@ public: IGameDef *gamedef; LocalPlayer *player; Inventory *inventory; - + ITextureSource *tsrc; + v2u32 screensize; v2s32 displaycenter; s32 hotbar_imagesize; @@ -98,6 +106,7 @@ public: video::SColor crosshair_argb; video::SColor selectionbox_argb; + bool use_crosshair_image; Hud(video::IVideoDriver *driver, gui::IGUIEnvironment* guienv, gui::IGUIFont *font, u32 text_height, IGameDef *gamedef, @@ -106,7 +115,8 @@ public: void drawItem(v2s32 upperleftpos, s32 imgsize, s32 itemcount, InventoryList *mainlist, u16 selectitem, u16 direction); void drawLuaElements(); - void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s32 count); + void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, + std::string texture, s32 count, v2s32 offset); void drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem); void resizeHotbar(); diff --git a/src/itemdef.cpp b/src/itemdef.cpp index 784919ae2..05328ea48 100644 --- a/src/itemdef.cpp +++ b/src/itemdef.cpp @@ -247,7 +247,8 @@ public: i = values.begin(); i != values.end(); ++i) { ClientCached *cc = *i; - cc->wield_mesh->drop(); + if (cc->wield_mesh) + cc->wield_mesh->drop(); delete cc; } diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 6b7b0943c..13117d881 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -154,9 +154,6 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d, // This should always apply, otherwise there are glitches assert(d > pos_max_d); - float player_radius = BS*0.30; - float player_height = BS*1.55; - // Maximum distance over border for sneaking f32 sneak_max = BS*0.4; @@ -184,24 +181,12 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d, } } - /* - Calculate player collision box (new and old) - */ - core::aabbox3d<f32> playerbox( - -player_radius, - 0.0, - -player_radius, - player_radius, - player_height, - player_radius - ); - float player_stepheight = touching_ground ? (BS*0.6) : (BS*0.2); v3f accel_f = v3f(0,0,0); collisionMoveResult result = collisionMoveSimple(env, m_gamedef, - pos_max_d, playerbox, player_stepheight, dtime, + pos_max_d, m_collisionbox, player_stepheight, dtime, position, m_speed, accel_f); /* diff --git a/src/map.cpp b/src/map.cpp index c4884a45a..821805d4e 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1764,7 +1764,7 @@ void Map::transformLiquidsFinite(std::map<v3s16, MapBlock*> & modified_blocks) } // prevent lakes in air above unloaded blocks - if (p0.Y > water_level && neighbors[D_BOTTOM].n.getContent() == CONTENT_IGNORE) { + if (liquid_levels[D_TOP] == 0 && (p0.Y > water_level || !fast_flood) && neighbors[D_BOTTOM].n.getContent() == CONTENT_IGNORE) { --total_level; } diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp index f68a79e41..f8a0b5f06 100644 --- a/src/mapblock_mesh.cpp +++ b/src/mapblock_mesh.cpp @@ -1099,6 +1099,8 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data): getShader("test_shader_1").material; video::E_MATERIAL_TYPE shadermat2 = m_gamedef->getShaderSource()-> getShader("test_shader_2").material; + video::E_MATERIAL_TYPE shadermat3 = m_gamedef->getShaderSource()-> + getShader("test_shader_3").material; for(u32 i = 0; i < collector.prebuffers.size(); i++) { PreMeshBuffer &p = collector.prebuffers[i]; @@ -1174,7 +1176,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data): = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; material.setTexture(0, p.tile.texture.atlas); if(enable_shaders) - p.tile.applyMaterialOptionsWithShaders(material, shadermat1, shadermat2); + p.tile.applyMaterialOptionsWithShaders(material, shadermat1, shadermat2, shadermat3); else p.tile.applyMaterialOptions(material); diff --git a/src/mapgen_indev.cpp b/src/mapgen_indev.cpp index 7f0faf16f..2eeaf13eb 100644 --- a/src/mapgen_indev.cpp +++ b/src/mapgen_indev.cpp @@ -274,23 +274,21 @@ void MapgenIndev::generateCaves(int max_stone_y) { for (u32 i = 0; i < caves_count + bruises_count; i++) { bool large_cave = (i >= caves_count); - CaveIndev cave(this, &ps, &ps2, node_min, large_cave, - c_water_source, c_lava_source); + CaveIndev cave(this, &ps, &ps2, node_min, large_cave); cave.makeCave(node_min, node_max, max_stone_y); } } -CaveIndev::CaveIndev(Mapgen *mg, PseudoRandom *ps, PseudoRandom *ps2, - v3s16 node_min, bool is_large_cave, - content_t c_water, content_t c_lava) { +CaveIndev::CaveIndev(MapgenIndev *mg, PseudoRandom *ps, PseudoRandom *ps2, + v3s16 node_min, bool is_large_cave) { this->vm = mg->vm; this->water_level = mg->water_level; this->large_cave = is_large_cave; this->ps = ps; this->ps2 = ps2; - this->c_water_source = c_water; - this->c_lava_source = c_lava; + this->c_water_source = mg->c_water_source; + this->c_lava_source = mg->c_lava_source; min_tunnel_diameter = 2; max_tunnel_diameter = ps->range(2,6); @@ -303,7 +301,7 @@ CaveIndev::CaveIndev(Mapgen *mg, PseudoRandom *ps, PseudoRandom *ps2, flooded = !ps->range(0, 3); tunnel_routepoints = ps->range(5, 30); min_tunnel_diameter = 30; - max_tunnel_diameter = ps->range(40, ps->range(80, 200)); + max_tunnel_diameter = ps->range(40, ps->range(80, 150)); } else { tunnel_routepoints = ps->range(5, ps->range(15,30)); min_tunnel_diameter = 5; diff --git a/src/mapgen_indev.h b/src/mapgen_indev.h index bd6faa21c..87ae39d09 100644 --- a/src/mapgen_indev.h +++ b/src/mapgen_indev.h @@ -153,8 +153,8 @@ struct MapgenFactoryIndev : public MapgenFactoryV6 { class CaveIndev : public CaveV6 { public: - CaveIndev(Mapgen *mg, PseudoRandom *ps, PseudoRandom *ps2, v3s16 node_min, - bool is_large_cave, content_t c_water, content_t c_lava); + CaveIndev(MapgenIndev *mg, PseudoRandom *ps, PseudoRandom *ps2, + v3s16 node_min, bool is_large_cave); }; #endif diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp index 352afd2f3..d90d142d5 100644 --- a/src/mapgen_v6.cpp +++ b/src/mapgen_v6.cpp @@ -948,7 +948,7 @@ void MapgenV6::generateCaves(int max_stone_y) { for (u32 i = 0; i < caves_count + bruises_count; i++) { bool large_cave = (i >= caves_count); - CaveV6 cave(this, &ps, &ps2, large_cave, c_water_source, c_lava_source); + CaveV6 cave(this, &ps, &ps2, large_cave); cave.makeCave(node_min, node_max, max_stone_y); } diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp index efcf78672..4bfc866e2 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -78,7 +78,7 @@ MapgenV7::MapgenV7(int mapgenid, MapgenV7Params *params, EmergeManager *emerge) this->water_level = params->water_level; this->flags = params->flags; this->csize = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE; -// this->ystride = csize.X; //////fix this + this->ystride = csize.X; //////fix this this->biomemap = new u8[csize.X * csize.Z]; this->heightmap = new s16[csize.X * csize.Z]; @@ -187,7 +187,6 @@ void MapgenV7::makeChunk(BlockMakeData *data) { generateCaves(stone_surface_max_y); addTopNodes(); - //v3s16 central_area_size = node_max - node_min + v3s16(1,1,1); if (flags & MG_DUNGEONS) { DungeonGen dgen(ndef, data->seed, water_level); @@ -452,7 +451,8 @@ void MapgenV7::addTopNodes() { vm->m_area.add_y(em, i, 1); } // If dirt, grow grass on it. - if (vm->m_data[i].getContent() == CONTENT_AIR) { + if (y > water_level - 10 && + vm->m_data[i].getContent() == CONTENT_AIR) { vm->m_area.add_y(em, i, -1); if (vm->m_data[i].getContent() == c_dirt) vm->m_data[i] = MapNode(c_dirt_with_grass); @@ -489,7 +489,8 @@ void MapgenV7::addTopNodes() { vm->m_area.add_y(em, i, 1); } // If dirt, grow grass on it. - if (vm->m_data[i].getContent() == CONTENT_AIR) { + if (y > water_level - 10 && + vm->m_data[i].getContent() == CONTENT_AIR) { vm->m_area.add_y(em, i, -1); if (vm->m_data[i].getContent() == c_dirt) vm->m_data[i] = MapNode(c_dirt_with_grass); @@ -502,22 +503,22 @@ void MapgenV7::addTopNodes() { #include "mapgen_v6.h" void MapgenV7::generateCaves(int max_stone_y) { PseudoRandom ps(blockseed + 21343); - PseudoRandom ps2(blockseed + 1032); int volume_nodes = (node_max.X - node_min.X + 1) * - (node_max.Y - node_min.Y + 1) * MAP_BLOCKSIZE; + (node_max.Y - node_min.Y + 1) * + (node_max.Z - node_min.Z + 1); float cave_amount = NoisePerlin2D(&nparams_v6_def_cave, node_min.X, node_min.Y, seed); - - u32 caves_count = MYMAX(0.0, cave_amount) * volume_nodes / 50000; + + u32 caves_count = MYMAX(0.0, cave_amount) * volume_nodes / 250000; for (u32 i = 0; i < caves_count; i++) { - CaveV6 cave(this, &ps, &ps2, false, c_water_source, c_lava_source); + CaveV7 cave(this, &ps, false); cave.makeCave(node_min, node_max, max_stone_y); } - - u32 bruises_count = (ps.range(1, 6) == 1) ? ps.range(0, ps.range(0, 2)) : 1; + + u32 bruises_count = (ps.range(1, 8) == 1) ? ps.range(0, ps.range(0, 2)) : 1; for (u32 i = 0; i < bruises_count; i++) { - CaveV6 cave(this, &ps, &ps2, true, c_water_source, c_lava_source); + CaveV7 cave(this, &ps, true); cave.makeCave(node_min, node_max, max_stone_y); } } diff --git a/src/nodedef.cpp b/src/nodedef.cpp index e2b72333f..ba3e42e98 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -628,6 +628,10 @@ public: f->solidness = 0; f->visual_solidness = 1; break; + case NDT_GLASSLIKE_FRAMED: + f->solidness = 0; + f->visual_solidness = 1; + break; case NDT_ALLFACES: f->solidness = 0; f->visual_solidness = 1; @@ -658,15 +662,11 @@ public: break; } - u8 material_type = 0; - if(is_liquid){ - if(f->alpha == 255) - material_type = TILE_MATERIAL_LIQUID_OPAQUE; - else - material_type = TILE_MATERIAL_LIQUID_TRANSPARENT; - } else{ - material_type = TILE_MATERIAL_BASIC; - } + u8 material_type; + if (is_liquid) + material_type = (f->alpha == 255) ? TILE_MATERIAL_LIQUID_OPAQUE : TILE_MATERIAL_LIQUID_TRANSPARENT; + else + material_type = (f->alpha == 255) ? TILE_MATERIAL_BASIC : TILE_MATERIAL_ALPHA; // Tiles (fill in f->tiles[]) for(u16 j=0; j<6; j++){ diff --git a/src/nodedef.h b/src/nodedef.h index d846489ae..2691aca33 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -141,6 +141,9 @@ enum NodeDrawType NDT_FENCELIKE, NDT_RAILLIKE, NDT_NODEBOX, + NDT_GLASSLIKE_FRAMED, // Glass-like, draw connected frames and all all + // visible faces + // uses 2 textures, one for frames, second for faces }; #define CF_SPECIAL_COUNT 2 diff --git a/src/player.cpp b/src/player.cpp index 1ca9423b0..34f0fda08 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "player.h" +#include "hud.h" #include "constants.h" #include "gamedef.h" #include "connection.h" // PEER_ID_INEXISTENT @@ -41,7 +42,8 @@ Player::Player(IGameDef *gamedef): m_pitch(0), m_yaw(0), m_speed(0,0,0), - m_position(0,0,0) + m_position(0,0,0), + m_collisionbox(-BS*0.30,0.0,-BS*0.30,BS*0.30,BS*1.55,BS*0.30) { updateName("<not set>"); inventory.clear(); @@ -52,30 +54,33 @@ Player::Player(IGameDef *gamedef): inventory.addList("craftresult", 1); // Can be redefined via Lua - inventory_formspec = "size[8,7.5]" + inventory_formspec = "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;]" "list[current_player;craftpreview;7,1;1,1;]"; // Initialize movement settings at default values, so movement can work if the server fails to send them - movement_acceleration_default = 3 * BS; - movement_acceleration_air = 2 * BS; - movement_acceleration_fast = 10 * BS; - movement_speed_walk = 4 * BS; - movement_speed_crouch = 1.35 * BS; - movement_speed_fast = 20 * BS; - movement_speed_climb = 2 * BS; - movement_speed_jump = 6.5 * BS; - movement_liquid_fluidity = 1 * BS; - movement_liquid_fluidity_smooth = 0.5 * BS; - movement_liquid_sink = 10 * BS; - movement_gravity = 9.81 * BS; + movement_acceleration_default = 3 * BS; + movement_acceleration_air = 2 * BS; + movement_acceleration_fast = 10 * BS; + movement_speed_walk = 4 * BS; + movement_speed_crouch = 1.35 * BS; + movement_speed_fast = 20 * BS; + movement_speed_climb = 2 * BS; + movement_speed_jump = 6.5 * BS; + movement_liquid_fluidity = 1 * BS; + movement_liquid_fluidity_smooth = 0.5 * BS; + movement_liquid_sink = 10 * BS; + movement_gravity = 9.81 * BS; // Movement overrides are multipliers and must be 1 by default - physics_override_speed = 1; - physics_override_jump = 1; + physics_override_speed = 1; + physics_override_jump = 1; physics_override_gravity = 1; + + hud_flags = HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE | + HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE; } Player::~Player() diff --git a/src/player.h b/src/player.h index d0e50d2c3..fade6de01 100644 --- a/src/player.h +++ b/src/player.h @@ -180,6 +180,10 @@ public: return m_name; } + core::aabbox3d<f32> getCollisionbox() { + return m_collisionbox; + } + virtual bool isLocal() const { return false; } virtual PlayerSAO *getPlayerSAO() @@ -245,6 +249,7 @@ public: u32 keyPressed; std::vector<HudElement *> hud; + u32 hud_flags; protected: IGameDef *m_gamedef; @@ -254,6 +259,7 @@ protected: f32 m_yaw; v3f m_speed; v3f m_position; + core::aabbox3d<f32> m_collisionbox; }; diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 8d472e6b8..f0fe1950e 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -754,15 +754,18 @@ static int l_chat_send_all(lua_State *L) return 0; } -// chat_send_player(name, text) +// chat_send_player(name, text, prepend) static int l_chat_send_player(lua_State *L) { const char *name = luaL_checkstring(L, 1); const char *text = luaL_checkstring(L, 2); + bool prepend = true; + if (lua_isboolean(L, 3)) + prepend = lua_toboolean(L, 3); // Get server from registry Server *server = get_server(L); // Send - server->notifyPlayer(name, narrow_to_wide(text)); + server->notifyPlayer(name, narrow_to_wide(text), prepend); return 0; } @@ -785,6 +788,31 @@ static int l_get_player_privs(lua_State *L) return 1; } +// get_player_ip() +static int l_get_player_ip(lua_State *L) +{ + const char * name = luaL_checkstring(L, 1); + Player *player = get_env(L)->getPlayer(name); + if(player == NULL) + { + lua_pushnil(L); // no such player + return 1; + } + try + { + Address addr = get_server(L)->getPeerAddress(get_env(L)->getPlayer(name)->peer_id); + std::string ip_str = addr.serializeString(); + lua_pushstring(L, ip_str.c_str()); + return 1; + } + catch(con::PeerNotFoundException) // unlikely + { + dstream << __FUNCTION_NAME << ": peer was not found" << std::endl; + lua_pushnil(L); // error + return 1; + } +} + // get_ban_list() static int l_get_ban_list(lua_State *L) { @@ -1081,6 +1109,7 @@ static const struct luaL_Reg minetest_f [] = { {"chat_send_all", l_chat_send_all}, {"chat_send_player", l_chat_send_player}, {"get_player_privs", l_get_player_privs}, + {"get_player_ip", l_get_player_ip}, {"get_ban_list", l_get_ban_list}, {"get_ban_description", l_get_ban_description}, {"ban_player", l_ban_player}, diff --git a/src/scriptapi_content.cpp b/src/scriptapi_content.cpp index 3b7ed5179..30fd70349 100644 --- a/src/scriptapi_content.cpp +++ b/src/scriptapi_content.cpp @@ -225,6 +225,11 @@ ContentFeatures read_content_features(lua_State *L, int index) lua_pop(L, 1); f.alpha = getintfield_default(L, index, "alpha", 255); + + bool usealpha = getboolfield_default(L, index, + "use_texture_alpha", false); + if (usealpha) + f.alpha = 0; /* Other stuff */ diff --git a/src/scriptapi_node.cpp b/src/scriptapi_node.cpp index 5ffcaeb9d..2fea50fa1 100644 --- a/src/scriptapi_node.cpp +++ b/src/scriptapi_node.cpp @@ -34,6 +34,7 @@ struct EnumString es_DrawType[] = {NDT_LIQUID, "liquid"}, {NDT_FLOWINGLIQUID, "flowingliquid"}, {NDT_GLASSLIKE, "glasslike"}, + {NDT_GLASSLIKE_FRAMED, "glasslike_framed"}, {NDT_ALLFACES, "allfaces"}, {NDT_ALLFACES_OPTIONAL, "allfaces_optional"}, {NDT_TORCHLIKE, "torchlike"}, diff --git a/src/scriptapi_object.cpp b/src/scriptapi_object.cpp index 9152c9eb3..4dfdeb8c8 100644 --- a/src/scriptapi_object.cpp +++ b/src/scriptapi_object.cpp @@ -47,6 +47,17 @@ struct EnumString es_HudElementStat[] = {HUD_STAT_NUMBER, "number"}, {HUD_STAT_ITEM, "item"}, {HUD_STAT_DIR, "direction"}, + {HUD_STAT_ALIGN, "alignment"}, + {HUD_STAT_OFFSET, "offset"}, + {0, NULL}, +}; + +struct EnumString es_HudBuiltinElement[] = +{ + {HUD_FLAG_HOTBAR_VISIBLE, "hotbar"}, + {HUD_FLAG_HEALTHBAR_VISIBLE, "healthbar"}, + {HUD_FLAG_CROSSHAIR_VISIBLE, "crosshair"}, + {HUD_FLAG_WIELDITEM_VISIBLE, "wielditem"}, {0, NULL}, }; @@ -751,6 +762,14 @@ int ObjectRef::l_hud_add(lua_State *L) elem->item = getintfield_default(L, 2, "item", 0); elem->dir = getintfield_default(L, 2, "direction", 0); + lua_getfield(L, 2, "alignment"); + elem->align = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); + lua_pop(L, 1); + + lua_getfield(L, 2, "offset"); + elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); + lua_pop(L, 1); + u32 id = get_server(L)->hudAdd(player, elem); if (id == (u32)-1) { delete elem; @@ -833,6 +852,12 @@ int ObjectRef::l_hud_change(lua_State *L) case HUD_STAT_DIR: e->dir = lua_tonumber(L, 4); value = &e->dir; + case HUD_STAT_ALIGN: + e->align = read_v2f(L, 4); + value = &e->align; + case HUD_STAT_OFFSET: + e->offset = read_v2f(L, 4); + value = &e->offset; } get_server(L)->hudChange(player, id, stat, value); @@ -886,6 +911,32 @@ int ObjectRef::l_hud_get(lua_State *L) return 1; } +// hud_set_flags(self, flags) +int ObjectRef::l_hud_set_flags(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + u32 flags = 0; + u32 mask = 0; + bool flag; + + const EnumString *esp = es_HudBuiltinElement; + for (int i = 0; esp[i].str; i++) { + if (getboolfield(L, 2, esp[i].str, flag)) { + flags |= esp[i].num * flag; + mask |= esp[i].num; + } + } + if (!get_server(L)->hudSetFlags(player, flags, mask)) + return 0; + + lua_pushboolean(L, true); + return 1; +} + ObjectRef::ObjectRef(ServerActiveObject *object): m_object(object) { @@ -996,8 +1047,7 @@ const luaL_reg ObjectRef::methods[] = { luamethod(ObjectRef, hud_remove), luamethod(ObjectRef, hud_change), luamethod(ObjectRef, hud_get), - //luamethod(ObjectRef, hud_lock_next_bar), - //luamethod(ObjectRef, hud_unlock_bar), + luamethod(ObjectRef, hud_set_flags), {0,0} }; diff --git a/src/scriptapi_object.h b/src/scriptapi_object.h index fd46f2cf6..82535ee94 100644 --- a/src/scriptapi_object.h +++ b/src/scriptapi_object.h @@ -202,6 +202,9 @@ private: // hud_get(self, id) static int l_hud_get(lua_State *L); + // hud_set_flags(self, flags) + static int l_hud_set_flags(lua_State *L); + public: ObjectRef(ServerActiveObject *object); diff --git a/src/server.cpp b/src/server.cpp index 7fad623c2..d5e505190 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3616,6 +3616,8 @@ void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form) writeU32(os, form->number); writeU32(os, form->item); writeU32(os, form->dir); + writeV2F1000(os, form->align); + writeV2F1000(os, form->offset); // Make data buffer std::string s = os.str(); @@ -3650,6 +3652,8 @@ void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value switch (stat) { case HUD_STAT_POS: case HUD_STAT_SCALE: + case HUD_STAT_ALIGN: + case HUD_STAT_OFFSET: writeV2F1000(os, *(v2f *)value); break; case HUD_STAT_NAME: @@ -3671,6 +3675,22 @@ void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value m_con.Send(peer_id, 0, data, true); } +void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask) +{ + std::ostringstream os(std::ios_base::binary); + + // Write command + writeU16(os, TOCLIENT_HUD_SET_FLAGS); + writeU32(os, flags); + writeU32(os, mask); + + // Make data buffer + std::string s = os.str(); + SharedBuffer<u8> data((u8 *)s.c_str(), s.size()); + // Send as reliable + m_con.Send(peer_id, 0, data, true); +} + void Server::BroadcastChatMessage(const std::wstring &message) { for(std::map<u16, RemoteClient*>::iterator @@ -4602,12 +4622,15 @@ void Server::saveConfig() g_settings->updateConfigFile(m_path_config.c_str()); } -void Server::notifyPlayer(const char *name, const std::wstring msg) +void Server::notifyPlayer(const char *name, const std::wstring msg, const bool prepend = true) { Player *player = m_env->getPlayer(name); if(!player) return; - SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg); + if (prepend) + SendChatMessage(player->peer_id, std::wstring(L"Server -!- ")+msg); + else + SendChatMessage(player->peer_id, msg); } bool Server::showFormspec(const char *playername, const std::string &formspec, const std::string &formname) @@ -4657,6 +4680,14 @@ bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data) return true; } +bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) { + if (!player) + return false; + + SendHUDSetFlags(player->peer_id, flags, mask); + return true; +} + void Server::notifyPlayers(const std::wstring msg) { BroadcastChatMessage(msg); diff --git a/src/server.h b/src/server.h index 52606b0cb..dcd007d23 100644 --- a/src/server.h +++ b/src/server.h @@ -456,7 +456,7 @@ public: } // Envlock and conlock should be locked when calling this - void notifyPlayer(const char *name, const std::wstring msg); + void notifyPlayer(const char *name, const std::wstring msg, const bool prepend); void notifyPlayers(const std::wstring msg); void spawnParticle(const char *playername, v3f pos, v3f velocity, v3f acceleration, @@ -540,6 +540,7 @@ public: u32 hudAdd(Player *player, HudElement *element); bool hudRemove(Player *player, u32 id); bool hudChange(Player *player, u32 id, HudElementStat stat, void *value); + bool hudSetFlags(Player *player, u32 flags, u32 mask); private: @@ -583,6 +584,8 @@ private: void SendHUDAdd(u16 peer_id, u32 id, HudElement *form); void SendHUDRemove(u16 peer_id, u32 id); void SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value); + void SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask); + /* Send a node removal/addition event to all clients except ignore_id. Additionally, if far_players!=NULL, players further away than diff --git a/src/serverlist.cpp b/src/serverlist.cpp index 93f9d2435..7053436d0 100644 --- a/src/serverlist.cpp +++ b/src/serverlist.cpp @@ -38,10 +38,12 @@ std::string getFilePath() { std::string serverlist_file = g_settings->get("serverlist_file"); - std::string rel_path = std::string("client") + DIR_DELIM - + "serverlist" + DIR_DELIM - + serverlist_file; - std::string path = porting::path_share + DIR_DELIM + rel_path; + std::string dir_path = std::string("client") + DIR_DELIM + + "serverlist" + DIR_DELIM; + fs::CreateDir(porting::path_user + DIR_DELIM + "client"); + fs::CreateDir(porting::path_user + DIR_DELIM + dir_path); + std::string rel_path = dir_path + serverlist_file; + std::string path = porting::path_user + DIR_DELIM + rel_path; return path; } diff --git a/src/tile.h b/src/tile.h index c5c7f9303..ea5c4be54 100644 --- a/src/tile.h +++ b/src/tile.h @@ -162,6 +162,7 @@ IWritableTextureSource* createTextureSource(IrrlichtDevice *device); enum MaterialType{ TILE_MATERIAL_BASIC, + TILE_MATERIAL_ALPHA, TILE_MATERIAL_LIQUID_TRANSPARENT, TILE_MATERIAL_LIQUID_OPAQUE, }; @@ -222,6 +223,9 @@ struct TileSpec case TILE_MATERIAL_BASIC: material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; break; + case TILE_MATERIAL_ALPHA: + material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + break; case TILE_MATERIAL_LIQUID_TRANSPARENT: material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; break; @@ -233,12 +237,16 @@ struct TileSpec } void applyMaterialOptionsWithShaders(video::SMaterial &material, const video::E_MATERIAL_TYPE &basic, - const video::E_MATERIAL_TYPE &liquid) const + const video::E_MATERIAL_TYPE &liquid, + const video::E_MATERIAL_TYPE &alpha) const { switch(material_type){ case TILE_MATERIAL_BASIC: material.MaterialType = basic; break; + case TILE_MATERIAL_ALPHA: + material.MaterialType = alpha; + break; case TILE_MATERIAL_LIQUID_TRANSPARENT: material.MaterialType = liquid; break; |