mirror of https://github.com/minetest/minetest.git
Merge branch 'master' of https://github.com/minetest/minetest
Conflicts: doc/lua_api.txt src/tile.cpp
This commit is contained in:
commit
1656ba4d73
|
@ -43,7 +43,6 @@ core.register_entity(":__builtin:falling_node", {
|
|||
|
||||
on_activate = function(self, staticdata)
|
||||
self.object:set_armor_groups({immortal=1})
|
||||
--self.object:setacceleration({x=0, y=-10, z=0})
|
||||
self:set_node({name=staticdata})
|
||||
end,
|
||||
|
||||
|
@ -102,8 +101,12 @@ core.register_entity(":__builtin:falling_node", {
|
|||
core.add_node(np, self.node)
|
||||
self.object:remove()
|
||||
nodeupdate(np)
|
||||
else
|
||||
-- Do nothing
|
||||
return
|
||||
end
|
||||
local vel = self.object:getvelocity()
|
||||
if vector.equals(vel, {x=0,y=0,z=0}) then
|
||||
local npos = self.object:getpos()
|
||||
self.object:setpos(vector.round(npos))
|
||||
end
|
||||
end
|
||||
})
|
||||
|
@ -175,7 +178,7 @@ function nodeupdate_single(p, delay)
|
|||
if delay then
|
||||
core.after(0.1, nodeupdate_single, {x=p.x, y=p.y, z=p.z}, false)
|
||||
else
|
||||
n.level = core.env:get_node_level(p)
|
||||
n.level = core.get_node_level(p)
|
||||
core.remove_node(p)
|
||||
spawn_falling_node(p, n)
|
||||
nodeupdate(p)
|
||||
|
|
|
@ -132,18 +132,18 @@ local function formspec(tabview, name, tabdata)
|
|||
local tab_string =
|
||||
"vertlabel[0,-0.25;" .. fgettext("SETTINGS") .. "]" ..
|
||||
"box[0.75,0;3.25,4;#999999]" ..
|
||||
"checkbox[1,0;cb_fancy_trees;".. fgettext("Fancy Trees") .. ";"
|
||||
.. dump(core.setting_getbool("new_style_leaves")) .. "]"..
|
||||
"checkbox[1,0.5;cb_smooth_lighting;".. fgettext("Smooth Lighting")
|
||||
"checkbox[1,0;cb_smooth_lighting;".. fgettext("Smooth Lighting")
|
||||
.. ";".. dump(core.setting_getbool("smooth_lighting")) .. "]"..
|
||||
"checkbox[1,0.5;cb_particles;".. fgettext("Enable Particles") .. ";"
|
||||
.. dump(core.setting_getbool("enable_particles")) .. "]"..
|
||||
"checkbox[1,1;cb_3d_clouds;".. fgettext("3D Clouds") .. ";"
|
||||
.. dump(core.setting_getbool("enable_3d_clouds")) .. "]"..
|
||||
"checkbox[1,1.5;cb_opaque_water;".. fgettext("Opaque Water") .. ";"
|
||||
"checkbox[1,1.5;cb_fancy_trees;".. fgettext("Fancy Trees") .. ";"
|
||||
.. dump(core.setting_getbool("new_style_leaves")) .. "]"..
|
||||
"checkbox[1,2.0;cb_opaque_water;".. fgettext("Opaque Water") .. ";"
|
||||
.. dump(core.setting_getbool("opaque_water")) .. "]"..
|
||||
"checkbox[1,2.0;cb_pre_ivis;".. fgettext("Preload item visuals") .. ";"
|
||||
.. dump(core.setting_getbool("preload_item_visuals")) .. "]"..
|
||||
"checkbox[1,2.5;cb_particles;".. fgettext("Enable Particles") .. ";"
|
||||
.. dump(core.setting_getbool("enable_particles")) .. "]"..
|
||||
"checkbox[1,2.5;cb_connected_glass;".. fgettext("Connected Glass") .. ";"
|
||||
.. dump(core.setting_getbool("connected_glass")) .. "]"..
|
||||
"dropdown[1,3.25;3;dd_video_driver;"
|
||||
.. video_driver_string .. ";" .. current_video_driver_idx .. "]" ..
|
||||
"tooltip[dd_video_driver;" ..
|
||||
|
@ -259,8 +259,8 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
|
|||
end
|
||||
return true
|
||||
end
|
||||
if fields["cb_pre_ivis"] then
|
||||
core.setting_set("preload_item_visuals", fields["cb_pre_ivis"])
|
||||
if fields["cb_connected_glass"] then
|
||||
core.setting_set("connected_glass", fields["cb_connected_glass"])
|
||||
return true
|
||||
end
|
||||
if fields["cb_particles"] then
|
||||
|
|
|
@ -266,6 +266,11 @@ Advanced texture modifiers:
|
|||
Retrieves a tile at position x,y from the base image
|
||||
which it assumes to be a tilesheet with dimensions w,h.
|
||||
|
||||
[colorize:<color>
|
||||
Colorize the textures with given color
|
||||
<color> as ColorString
|
||||
|
||||
|
||||
Sounds
|
||||
-------
|
||||
Only OGG Vorbis files are supported.
|
||||
|
@ -410,8 +415,7 @@ Nodes can also contain extra data. See "Node Metadata".
|
|||
|
||||
Node drawtypes
|
||||
---------------
|
||||
There are a bunch of different looking node types. These are mostly just
|
||||
copied from Minetest 0.3; more may be made in the future.
|
||||
There are a bunch of different looking node types.
|
||||
|
||||
Look for examples in games/minimal or games/minetest_game.
|
||||
|
||||
|
@ -421,6 +425,7 @@ Look for examples in games/minimal or games/minetest_game.
|
|||
- flowingliquid
|
||||
- glasslike
|
||||
- glasslike_framed
|
||||
- glasslike_framed_optional
|
||||
- allfaces
|
||||
- allfaces_optional
|
||||
- torchlike
|
||||
|
@ -431,6 +436,8 @@ Look for examples in games/minimal or games/minetest_game.
|
|||
- raillike
|
||||
- nodebox -- See below. EXPERIMENTAL
|
||||
|
||||
*_optional drawtypes need less rendering time if deactivated (always client side)
|
||||
|
||||
Node boxes
|
||||
-----------
|
||||
Node selection boxes are defined using "node boxes"
|
||||
|
@ -987,16 +994,16 @@ list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;<starting item index>]
|
|||
^ Show an inventory list
|
||||
|
||||
listcolors[<slot_bg_normal>;<slot_bg_hover>]
|
||||
^ Sets background color of slots in HEX-Color format
|
||||
^ Sets background color of slots as ColorString
|
||||
^ Sets background color of slots on mouse hovering
|
||||
|
||||
listcolors[<slot_bg_normal>;<slot_bg_hover>;<slot_border>]
|
||||
^ Sets background color of slots in HEX-Color format
|
||||
^ Sets background color of slots as ColorString
|
||||
^ Sets background color of slots on mouse hovering
|
||||
^ Sets color of slots border
|
||||
|
||||
listcolors[<slot_bg_normal>;<slot_bg_hover>;<slot_border>;<tooltip_bgcolor>;<tooltip_fontcolor>]
|
||||
^ Sets background color of slots in HEX-Color format
|
||||
^ Sets background color of slots as ColorString
|
||||
^ Sets background color of slots on mouse hovering
|
||||
^ Sets color of slots border
|
||||
^ Sets default background color of tooltips
|
||||
|
@ -1004,8 +1011,8 @@ listcolors[<slot_bg_normal>;<slot_bg_hover>;<slot_border>;<tooltip_bgcolor>;<too
|
|||
|
||||
tooltip[<gui_element_name>;<tooltip_text>;<bgcolor>,<fontcolor>]
|
||||
^ Adds tooltip for an element
|
||||
^ <bgcolor> tooltip background color in HEX-Color format (optional)
|
||||
^ <fontcolor> tooltip font color in HEX-Color format (optional)
|
||||
^ <bgcolor> tooltip background color as ColorString (optional)
|
||||
^ <fontcolor> tooltip font color as ColorString (optional)
|
||||
|
||||
|
||||
image[<X>,<Y>;<W>,<H>;<texture name>]
|
||||
|
@ -1017,7 +1024,7 @@ item_image[<X>,<Y>;<W>,<H>;<item name>]
|
|||
^ Position and size units are inventory slots
|
||||
|
||||
bgcolor[<color>;<fullscreen>]
|
||||
^ Sets background color of formspec in HEX-Color format
|
||||
^ Sets background color of formspec as ColorString
|
||||
^ If true the background color is drawn fullscreen (does not effect the size of the formspec)
|
||||
|
||||
background[<X>,<Y>;<W>,<H>;<texture name>]
|
||||
|
@ -1138,7 +1145,7 @@ box[<X>,<Y>;<W>,<H>;<color>]
|
|||
^ simple colored semitransparent box
|
||||
^ x and y position the box relative to the top left of the menu
|
||||
^ w and h are the size of box
|
||||
^ color in HEX-Color format
|
||||
^ color as ColorString
|
||||
|
||||
dropdown[<X>,<Y>;<W>;<name>;<item 1>,<item 2>, ...,<item n>;<selected idx>]
|
||||
^ show a dropdown field
|
||||
|
@ -1184,15 +1191,15 @@ table[<X>,<Y>;<W>,<H>;<name>;<cell 1>,<cell 2>,...,<cell n>;<selected idx>]
|
|||
tableoptions[<opt 1>;<opt 2>;...]
|
||||
^ sets options for table[]:
|
||||
^ color=#RRGGBB
|
||||
^^ default text color (HEX-Color), defaults to #FFFFFF
|
||||
^^ default text color (ColorString), defaults to #FFFFFF
|
||||
^ background=#RRGGBB
|
||||
^^ table background color (HEX-Color), defaults to #000000
|
||||
^^ table background color (ColorString), defaults to #000000
|
||||
^ border=<true/false>
|
||||
^^ should the table be drawn with a border? (default true)
|
||||
^ highlight=#RRGGBB
|
||||
^^ highlight background color (HEX-Color), defaults to #466432
|
||||
^^ highlight background color (ColorString), defaults to #466432
|
||||
^ highlight_text=#RRGGBB
|
||||
^^ highlight text color (HEX-Color), defaults to #FFFFFF
|
||||
^^ highlight text color (ColorString), defaults to #FFFFFF
|
||||
^ opendepth=<value>
|
||||
^^ all subtrees up to depth < value are open (default value = 0)
|
||||
^^ only useful when there is a column of type "tree"
|
||||
|
@ -1202,7 +1209,7 @@ tablecolumns[<type 1>,<opt 1a>,<opt 1b>,...;<type 2>,<opt 2a>,<opt 2b>;...]
|
|||
^ types: text, image, color, indent, tree
|
||||
^^ text: show cell contents as text
|
||||
^^ image: cell contents are an image index, use column options to define images
|
||||
^^ color: cell contents are a HEX-Color and define color of following cell
|
||||
^^ color: cell contents are a ColorString and define color of following cell
|
||||
^^ indent: cell contents are a number and define indentation of following cell
|
||||
^^ tree: same as indent, but user can open and close subtrees (treeview-like)
|
||||
^ column options:
|
||||
|
@ -1233,8 +1240,8 @@ Inventory location:
|
|||
- "nodemeta:<X>,<Y>,<Z>": Any node metadata
|
||||
- "detached:<name>": A detached inventory
|
||||
|
||||
HEX-Color
|
||||
---------
|
||||
ColorString
|
||||
-----------
|
||||
#RGB
|
||||
^ defines a color in hexadecimal format
|
||||
#RGBA
|
||||
|
@ -2425,7 +2432,6 @@ Node definition (register_node)
|
|||
diggable = true, -- If false, can never be dug
|
||||
climbable = false, -- If true, can be climbed on (ladder)
|
||||
buildable_to = false, -- If true, placed nodes can replace this node
|
||||
drop = "", -- alternatively drop = { max_items = ..., items = { ... } }
|
||||
liquidtype = "none", -- "none"/"source"/"flowing"
|
||||
liquid_alternative_flowing = "", -- Flowing version of source liquid
|
||||
liquid_alternative_source = "", -- Source version of flowing liquid
|
||||
|
@ -2448,6 +2454,17 @@ Node definition (register_node)
|
|||
dug = <SimpleSoundSpec>,
|
||||
place = <SimpleSoundSpec>,
|
||||
},
|
||||
drop = "", -- Name of dropped node when dug. Default is the node itself.
|
||||
-- Alternatively:
|
||||
drop = {
|
||||
max_items = 1, -- Maximum number of items to drop.
|
||||
items = { -- Choose max_items randomly from this list.
|
||||
{
|
||||
items = {"foo:bar", "baz:frob"}, -- Choose one item randomly from this list.
|
||||
rarity = 1, -- Probability of getting is 1 / rarity.
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
on_construct = func(pos),
|
||||
^ Node constructor; always called after adding node
|
||||
|
|
|
@ -101,6 +101,8 @@
|
|||
#liquid_update = 1.0
|
||||
# Enable nice leaves; disable for speed
|
||||
#new_style_leaves = true
|
||||
# Connects glass if supported by node
|
||||
#connected_glass = false
|
||||
# Enable smooth lighting with simple ambient occlusion;
|
||||
# disable for speed or for different looks.
|
||||
#smooth_lighting = true
|
||||
|
|
|
@ -270,9 +270,7 @@ Client::Client(
|
|||
Add local player
|
||||
*/
|
||||
{
|
||||
Player *player = new LocalPlayer(this);
|
||||
|
||||
player->updateName(playername);
|
||||
Player *player = new LocalPlayer(this, playername);
|
||||
|
||||
m_env.addPlayer(player);
|
||||
}
|
||||
|
|
|
@ -74,5 +74,10 @@
|
|||
#define VERSION_EXTRA_STRING CMAKE_VERSION_EXTRA_STRING
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "android_version.h"
|
||||
#define VERSION_STRING CMAKE_VERSION_STRING
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -794,6 +794,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||
collector.append(tile, vertices, 4, indices, 6);
|
||||
}
|
||||
break;}
|
||||
case NDT_GLASSLIKE_FRAMED_OPTIONAL:
|
||||
// This is always pre-converted to something else
|
||||
assert(0);
|
||||
break;
|
||||
case NDT_GLASSLIKE_FRAMED:
|
||||
{
|
||||
static const v3s16 dirs[6] = {
|
||||
|
|
|
@ -100,6 +100,7 @@ void set_default_settings(Settings *settings)
|
|||
settings->setDefault("view_bobbing", "true");
|
||||
settings->setDefault("new_style_water", "false");
|
||||
settings->setDefault("new_style_leaves", "true");
|
||||
settings->setDefault("connected_glass", "false");
|
||||
settings->setDefault("smooth_lighting", "true");
|
||||
settings->setDefault("texture_path", "");
|
||||
settings->setDefault("shader_path", "");
|
||||
|
|
|
@ -132,14 +132,15 @@ void draw_anaglyph_3d_mode(Camera& camera, bool show_hud, Hud& hud,
|
|||
}
|
||||
|
||||
void init_texture(video::IVideoDriver* driver, const v2u32& screensize,
|
||||
video::ITexture** texture)
|
||||
video::ITexture** texture, const char* name)
|
||||
{
|
||||
if (*texture != NULL)
|
||||
{
|
||||
driver->removeTexture(*texture);
|
||||
}
|
||||
*texture = driver->addRenderTargetTexture(
|
||||
core::dimension2d<u32>(screensize.X, screensize.Y));
|
||||
core::dimension2d<u32>(screensize.X, screensize.Y), name,
|
||||
irr::video::ECF_A8R8G8B8);
|
||||
}
|
||||
|
||||
video::ITexture* draw_image(const v2u32& screensize,
|
||||
|
@ -156,13 +157,16 @@ video::ITexture* draw_image(const v2u32& screensize,
|
|||
video::ITexture* image = NULL;
|
||||
|
||||
if (screensize != last_screensize) {
|
||||
init_texture(driver, screensize, &images[1]);
|
||||
image = images[1];
|
||||
init_texture(driver, screensize, &images[0]);
|
||||
image = images[0];
|
||||
init_texture(driver, screensize, &images[1], "mt_drawimage_img1");
|
||||
init_texture(driver, screensize, &images[0], "mt_drawimage_img2");
|
||||
last_screensize = screensize;
|
||||
}
|
||||
|
||||
if (psign == RIGHT)
|
||||
image = images[1];
|
||||
else
|
||||
image = images[0];
|
||||
|
||||
driver->setRenderTarget(image, true, true,
|
||||
irr::video::SColor(255,
|
||||
skycolor.getRed(), skycolor.getGreen(), skycolor.getBlue()));
|
||||
|
@ -205,7 +209,7 @@ video::ITexture* draw_hud(video::IVideoDriver* driver, const v2u32& screensize,
|
|||
video::SColor skycolor, gui::IGUIEnvironment* guienv, Camera& camera )
|
||||
{
|
||||
static video::ITexture* image = NULL;
|
||||
init_texture(driver, screensize, &image);
|
||||
init_texture(driver, screensize, &image, "mt_drawimage_hud");
|
||||
driver->setRenderTarget(image, true, true,
|
||||
irr::video::SColor(255,0,0,0));
|
||||
|
||||
|
|
|
@ -449,11 +449,11 @@ Player *ServerEnvironment::loadPlayer(const std::string &playername)
|
|||
bool newplayer = false;
|
||||
bool found = false;
|
||||
if (!player) {
|
||||
player = new RemotePlayer(m_gamedef);
|
||||
player = new RemotePlayer(m_gamedef, playername.c_str());
|
||||
newplayer = true;
|
||||
}
|
||||
|
||||
RemotePlayer testplayer(m_gamedef);
|
||||
RemotePlayer testplayer(m_gamedef, "");
|
||||
std::string path = players_path + playername;
|
||||
for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES; i++) {
|
||||
// Open file and deserialize
|
||||
|
@ -478,6 +478,7 @@ Player *ServerEnvironment::loadPlayer(const std::string &playername)
|
|||
if (newplayer) {
|
||||
addPlayer(player);
|
||||
}
|
||||
player->setModified(false);
|
||||
return player;
|
||||
}
|
||||
|
||||
|
|
19
src/game.cpp
19
src/game.cpp
|
@ -1102,8 +1102,16 @@ static void updateChat(Client& client, f32 dtime, bool show_debug,
|
|||
if (show_debug)
|
||||
chat_y += line_height;
|
||||
|
||||
core::rect<s32> rect(10, chat_y, font->getDimension(recent_chat.c_str()).Width +10,
|
||||
chat_y + (recent_chat_count * line_height));
|
||||
// first pass to calculate height of text to be set
|
||||
s32 width = std::min(font->getDimension(recent_chat.c_str()).Width + 10,
|
||||
porting::getWindowSize().X - 20);
|
||||
core::rect<s32> rect(10, chat_y, width, chat_y + porting::getWindowSize().Y);
|
||||
guitext_chat->setRelativePosition(rect);
|
||||
|
||||
//now use real height of text and adjust rect according to this size
|
||||
rect = core::rect<s32>(10, chat_y, width,
|
||||
chat_y + guitext_chat->getTextHeight());
|
||||
|
||||
|
||||
guitext_chat->setRelativePosition(rect);
|
||||
// Don't show chat if disabled or empty or profiler is enabled
|
||||
|
@ -2778,8 +2786,13 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
|
|||
if(pointed != pointed_old)
|
||||
{
|
||||
infostream<<"Pointing at "<<pointed.dump()<<std::endl;
|
||||
if (g_settings->getBool("enable_node_highlighting"))
|
||||
if (g_settings->getBool("enable_node_highlighting")) {
|
||||
if (pointed.type == POINTEDTHING_NODE) {
|
||||
client.setHighlighted(pointed.node_undersurface, show_hud);
|
||||
} else {
|
||||
client.setHighlighted(pointed.node_undersurface, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -50,6 +50,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "main.h"
|
||||
#include "settings.h"
|
||||
#include "client.h"
|
||||
#include "util/string.h" // for parseColorString()
|
||||
|
||||
#define MY_CHECKPOS(a,b) \
|
||||
if (v_pos.size() != 2) { \
|
||||
|
@ -1575,7 +1576,7 @@ void GUIFormSpecMenu::parseBox(parserData* data,std::string element)
|
|||
|
||||
video::SColor tmp_color;
|
||||
|
||||
if (parseColor(parts[2], tmp_color, false)) {
|
||||
if (parseColorString(parts[2], tmp_color, false)) {
|
||||
BoxDrawSpec spec(pos, geom, tmp_color);
|
||||
|
||||
m_boxes.push_back(spec);
|
||||
|
@ -1595,7 +1596,7 @@ void GUIFormSpecMenu::parseBackgroundColor(parserData* data,std::string element)
|
|||
if (((parts.size() == 1) || (parts.size() == 2)) ||
|
||||
((parts.size() > 2) && (m_formspec_version > FORMSPEC_API_VERSION)))
|
||||
{
|
||||
parseColor(parts[0],m_bgcolor,false);
|
||||
parseColorString(parts[0],m_bgcolor,false);
|
||||
|
||||
if (parts.size() == 2) {
|
||||
std::string fullscreen = parts[1];
|
||||
|
@ -1613,20 +1614,20 @@ void GUIFormSpecMenu::parseListColors(parserData* data,std::string element)
|
|||
if (((parts.size() == 2) || (parts.size() == 3) || (parts.size() == 5)) ||
|
||||
((parts.size() > 5) && (m_formspec_version > FORMSPEC_API_VERSION)))
|
||||
{
|
||||
parseColor(parts[0], m_slotbg_n, false);
|
||||
parseColor(parts[1], m_slotbg_h, false);
|
||||
parseColorString(parts[0], m_slotbg_n, false);
|
||||
parseColorString(parts[1], m_slotbg_h, false);
|
||||
|
||||
if (parts.size() >= 3) {
|
||||
if (parseColor(parts[2], m_slotbordercolor, false)) {
|
||||
if (parseColorString(parts[2], m_slotbordercolor, false)) {
|
||||
m_slotborder = true;
|
||||
}
|
||||
}
|
||||
if (parts.size() == 5) {
|
||||
video::SColor tmp_color;
|
||||
|
||||
if (parseColor(parts[3], tmp_color, false))
|
||||
if (parseColorString(parts[3], tmp_color, false))
|
||||
m_default_tooltip_bgcolor = tmp_color;
|
||||
if (parseColor(parts[4], tmp_color, false))
|
||||
if (parseColorString(parts[4], tmp_color, false))
|
||||
m_default_tooltip_color = tmp_color;
|
||||
}
|
||||
return;
|
||||
|
@ -1644,7 +1645,7 @@ void GUIFormSpecMenu::parseTooltip(parserData* data, std::string element)
|
|||
} else if (parts.size() == 4) {
|
||||
std::string name = parts[0];
|
||||
video::SColor tmp_color1, tmp_color2;
|
||||
if ( parseColor(parts[2], tmp_color1, false) && parseColor(parts[3], tmp_color2, false) ) {
|
||||
if ( parseColorString(parts[2], tmp_color1, false) && parseColorString(parts[3], tmp_color2, false) ) {
|
||||
m_tooltips[narrow_to_wide(name.c_str())] = TooltipSpec (parts[1], tmp_color1, tmp_color2);
|
||||
return;
|
||||
}
|
||||
|
@ -2141,10 +2142,10 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase)
|
|||
|
||||
// Draw tooltip
|
||||
std::string tooltip_text = "";
|
||||
if(hovering && !m_selected_item)
|
||||
if (hovering && !m_selected_item)
|
||||
tooltip_text = item.getDefinition(m_gamedef->idef()).description;
|
||||
if(tooltip_text != "")
|
||||
{
|
||||
if (tooltip_text != "") {
|
||||
std::vector<std::string> tt_rows = str_split(tooltip_text, '\n');
|
||||
m_tooltip_element->setBackgroundColor(m_default_tooltip_bgcolor);
|
||||
m_tooltip_element->setOverrideColor(m_default_tooltip_color);
|
||||
m_tooltip_element->setVisible(true);
|
||||
|
@ -2153,7 +2154,7 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase)
|
|||
s32 tooltip_x = m_pointer.X + m_btn_height;
|
||||
s32 tooltip_y = m_pointer.Y + m_btn_height;
|
||||
s32 tooltip_width = m_tooltip_element->getTextWidth() + m_btn_height;
|
||||
s32 tooltip_height = m_tooltip_element->getTextHeight() + 5;
|
||||
s32 tooltip_height = m_tooltip_element->getTextHeight() * tt_rows.size() + 5;
|
||||
m_tooltip_element->setRelativePosition(core::rect<s32>(
|
||||
core::position2d<s32>(tooltip_x, tooltip_y),
|
||||
core::dimension2d<s32>(tooltip_width, tooltip_height)));
|
||||
|
@ -2376,13 +2377,8 @@ void GUIFormSpecMenu::drawMenu()
|
|||
s32 tooltip_width = m_tooltip_element->getTextWidth() + m_btn_height;
|
||||
if (tooltip_x + tooltip_width > (s32)screenSize.X)
|
||||
tooltip_x = (s32)screenSize.X - tooltip_width - m_btn_height;
|
||||
int lines_count = 1;
|
||||
size_t i = 0;
|
||||
while ((i = m_tooltips[iter->fname].tooltip.find("\n", i)) != std::string::npos) {
|
||||
lines_count++;
|
||||
i += 2;
|
||||
}
|
||||
s32 tooltip_height = m_tooltip_element->getTextHeight() * lines_count + 5;
|
||||
std::vector<std::string> tt_rows = str_split(m_tooltips[iter->fname].tooltip, '\n');
|
||||
s32 tooltip_height = m_tooltip_element->getTextHeight() * tt_rows.size() + 5;
|
||||
m_tooltip_element->setRelativePosition(core::rect<s32>(
|
||||
core::position2d<s32>(tooltip_x, tooltip_y),
|
||||
core::dimension2d<s32>(tooltip_width, tooltip_height)));
|
||||
|
@ -3393,67 +3389,3 @@ std::wstring GUIFormSpecMenu::getLabelByID(s32 id)
|
|||
}
|
||||
return L"";
|
||||
}
|
||||
|
||||
bool GUIFormSpecMenu::parseColor(const std::string &value, video::SColor &color,
|
||||
bool quiet)
|
||||
{
|
||||
const char *hexpattern = NULL;
|
||||
if (value[0] == '#') {
|
||||
if (value.size() == 9)
|
||||
hexpattern = "#RRGGBBAA";
|
||||
else if (value.size() == 7)
|
||||
hexpattern = "#RRGGBB";
|
||||
else if (value.size() == 5)
|
||||
hexpattern = "#RGBA";
|
||||
else if (value.size() == 4)
|
||||
hexpattern = "#RGB";
|
||||
}
|
||||
|
||||
if (hexpattern) {
|
||||
assert(strlen(hexpattern) == value.size());
|
||||
video::SColor outcolor(255, 255, 255, 255);
|
||||
for (size_t pos = 0; pos < value.size(); ++pos) {
|
||||
// '#' in the pattern means skip that character
|
||||
if (hexpattern[pos] == '#')
|
||||
continue;
|
||||
|
||||
// Else assume hexpattern[pos] is one of 'R' 'G' 'B' 'A'
|
||||
// Read one or two digits, depending on hexpattern
|
||||
unsigned char c1, c2;
|
||||
if (hexpattern[pos+1] == hexpattern[pos]) {
|
||||
// Two digits, e.g. hexpattern == "#RRGGBB"
|
||||
if (!hex_digit_decode(value[pos], c1) ||
|
||||
!hex_digit_decode(value[pos+1], c2))
|
||||
goto fail;
|
||||
++pos;
|
||||
}
|
||||
else {
|
||||
// One digit, e.g. hexpattern == "#RGB"
|
||||
if (!hex_digit_decode(value[pos], c1))
|
||||
goto fail;
|
||||
c2 = c1;
|
||||
}
|
||||
u32 colorpart = ((c1 & 0x0f) << 4) | (c2 & 0x0f);
|
||||
|
||||
// Update outcolor with newly read color part
|
||||
if (hexpattern[pos] == 'R')
|
||||
outcolor.setRed(colorpart);
|
||||
else if (hexpattern[pos] == 'G')
|
||||
outcolor.setGreen(colorpart);
|
||||
else if (hexpattern[pos] == 'B')
|
||||
outcolor.setBlue(colorpart);
|
||||
else if (hexpattern[pos] == 'A')
|
||||
outcolor.setAlpha(colorpart);
|
||||
}
|
||||
|
||||
color = outcolor;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Optionally, named colors could be implemented here
|
||||
|
||||
fail:
|
||||
if (!quiet)
|
||||
errorstream<<"Invalid color: \""<<value<<"\""<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -274,9 +274,6 @@ public:
|
|||
|
||||
GUITable* getTable(std::wstring tablename);
|
||||
|
||||
static bool parseColor(const std::string &value,
|
||||
video::SColor &color, bool quiet);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
bool getAndroidUIInput();
|
||||
#endif
|
||||
|
|
|
@ -32,7 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "gettime.h"
|
||||
#include "util/string.h"
|
||||
#include "util/numeric.h"
|
||||
#include "guiFormSpecMenu.h" // for parseColor()
|
||||
#include "util/string.h" // for parseColorString()
|
||||
#include "main.h"
|
||||
#include "settings.h" // for settings
|
||||
#include "porting.h" // for dpi
|
||||
|
@ -164,7 +164,7 @@ void GUITable::setTextList(const std::vector<std::string> &content,
|
|||
cell->content_index = allocString(s.substr(2));
|
||||
}
|
||||
else if (s[0] == '#' && s.size() >= 7 &&
|
||||
GUIFormSpecMenu::parseColor(
|
||||
parseColorString(
|
||||
s.substr(0,7), cell->color, false)) {
|
||||
// single # for color
|
||||
cell->color_defined = true;
|
||||
|
@ -211,15 +211,15 @@ void GUITable::setTable(const TableOptions &options,
|
|||
const std::string &name = options[k].name;
|
||||
const std::string &value = options[k].value;
|
||||
if (name == "color")
|
||||
GUIFormSpecMenu::parseColor(value, m_color, false);
|
||||
parseColorString(value, m_color, false);
|
||||
else if (name == "background")
|
||||
GUIFormSpecMenu::parseColor(value, m_background, false);
|
||||
parseColorString(value, m_background, false);
|
||||
else if (name == "border")
|
||||
m_border = is_yes(value);
|
||||
else if (name == "highlight")
|
||||
GUIFormSpecMenu::parseColor(value, m_highlight, false);
|
||||
parseColorString(value, m_highlight, false);
|
||||
else if (name == "highlight_text")
|
||||
GUIFormSpecMenu::parseColor(value, m_highlight_text, false);
|
||||
parseColorString(value, m_highlight_text, false);
|
||||
else if (name == "opendepth")
|
||||
opendepth = stoi(value);
|
||||
else
|
||||
|
@ -416,7 +416,7 @@ void GUITable::setTable(const TableOptions &options,
|
|||
else if (columntype == COLUMN_TYPE_COLOR) {
|
||||
for (s32 i = 0; i < rowcount; ++i) {
|
||||
video::SColor cellcolor(255, 255, 255, 255);
|
||||
if (GUIFormSpecMenu::parseColor(content[i * colcount + j], cellcolor, true))
|
||||
if (parseColorString(content[i * colcount + j], cellcolor, true))
|
||||
rows[i].colors.push_back(std::make_pair(cellcolor, j+span));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -831,6 +831,7 @@ Inventory::~Inventory()
|
|||
|
||||
void Inventory::clear()
|
||||
{
|
||||
m_dirty = true;
|
||||
for(u32 i=0; i<m_lists.size(); i++)
|
||||
{
|
||||
delete m_lists[i];
|
||||
|
@ -840,6 +841,7 @@ void Inventory::clear()
|
|||
|
||||
void Inventory::clearContents()
|
||||
{
|
||||
m_dirty = true;
|
||||
for(u32 i=0; i<m_lists.size(); i++)
|
||||
{
|
||||
InventoryList *list = m_lists[i];
|
||||
|
@ -852,12 +854,14 @@ void Inventory::clearContents()
|
|||
|
||||
Inventory::Inventory(IItemDefManager *itemdef)
|
||||
{
|
||||
m_dirty = false;
|
||||
m_itemdef = itemdef;
|
||||
}
|
||||
|
||||
Inventory::Inventory(const Inventory &other)
|
||||
{
|
||||
*this = other;
|
||||
m_dirty = false;
|
||||
}
|
||||
|
||||
Inventory & Inventory::operator = (const Inventory &other)
|
||||
|
@ -865,6 +869,7 @@ Inventory & Inventory::operator = (const Inventory &other)
|
|||
// Gracefully handle self assignment
|
||||
if(this != &other)
|
||||
{
|
||||
m_dirty = true;
|
||||
clear();
|
||||
m_itemdef = other.m_itemdef;
|
||||
for(u32 i=0; i<other.m_lists.size(); i++)
|
||||
|
@ -945,6 +950,7 @@ void Inventory::deSerialize(std::istream &is)
|
|||
|
||||
InventoryList * Inventory::addList(const std::string &name, u32 size)
|
||||
{
|
||||
m_dirty = true;
|
||||
s32 i = getListIndex(name);
|
||||
if(i != -1)
|
||||
{
|
||||
|
@ -990,6 +996,7 @@ bool Inventory::deleteList(const std::string &name)
|
|||
s32 i = getListIndex(name);
|
||||
if(i == -1)
|
||||
return false;
|
||||
m_dirty = true;
|
||||
delete m_lists[i];
|
||||
m_lists.erase(m_lists.begin() + i);
|
||||
return true;
|
||||
|
|
|
@ -279,18 +279,30 @@ public:
|
|||
// A shorthand for adding items. Returns leftover item (possibly empty).
|
||||
ItemStack addItem(const std::string &listname, const ItemStack &newitem)
|
||||
{
|
||||
m_dirty = true;
|
||||
InventoryList *list = getList(listname);
|
||||
if(list == NULL)
|
||||
return newitem;
|
||||
return list->addItem(newitem);
|
||||
}
|
||||
|
||||
bool checkModified() const
|
||||
{
|
||||
return m_dirty;
|
||||
}
|
||||
|
||||
void setModified(const bool x)
|
||||
{
|
||||
m_dirty = x;
|
||||
}
|
||||
|
||||
private:
|
||||
// -1 if not found
|
||||
const s32 getListIndex(const std::string &name) const;
|
||||
|
||||
std::vector<InventoryList*> m_lists;
|
||||
IItemDefManager *m_itemdef;
|
||||
bool m_dirty;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -33,8 +33,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
LocalPlayer
|
||||
*/
|
||||
|
||||
LocalPlayer::LocalPlayer(IGameDef *gamedef):
|
||||
Player(gamedef),
|
||||
LocalPlayer::LocalPlayer(IGameDef *gamedef, const char *name):
|
||||
Player(gamedef, name),
|
||||
parent(0),
|
||||
isAttached(false),
|
||||
overridePosition(v3f(0,0,0)),
|
||||
|
|
|
@ -32,7 +32,7 @@ enum LocalPlayerAnimations {NO_ANIM, WALK_ANIM, DIG_ANIM, WD_ANIM}; // no local
|
|||
class LocalPlayer : public Player
|
||||
{
|
||||
public:
|
||||
LocalPlayer(IGameDef *gamedef);
|
||||
LocalPlayer(IGameDef *gamedef, const char *name);
|
||||
virtual ~LocalPlayer();
|
||||
|
||||
bool isLocal() const
|
||||
|
|
574
src/nodedef.cpp
574
src/nodedef.cpp
|
@ -370,11 +370,69 @@ void ContentFeatures::deSerialize(std::istream &is)
|
|||
CNodeDefManager
|
||||
*/
|
||||
|
||||
class CNodeDefManager: public IWritableNodeDefManager
|
||||
{
|
||||
class CNodeDefManager: public IWritableNodeDefManager {
|
||||
public:
|
||||
void clear()
|
||||
{
|
||||
CNodeDefManager();
|
||||
virtual ~CNodeDefManager();
|
||||
void clear();
|
||||
virtual IWritableNodeDefManager *clone();
|
||||
virtual const ContentFeatures& get(content_t c) const;
|
||||
virtual const ContentFeatures& get(const MapNode &n) const;
|
||||
virtual bool getId(const std::string &name, content_t &result) const;
|
||||
virtual content_t getId(const std::string &name) const;
|
||||
virtual void getIds(const std::string &name, std::set<content_t> &result) const;
|
||||
virtual const ContentFeatures& get(const std::string &name) const;
|
||||
content_t allocateId();
|
||||
virtual content_t set(const std::string &name, const ContentFeatures &def);
|
||||
virtual content_t allocateDummy(const std::string &name);
|
||||
virtual void updateAliases(IItemDefManager *idef);
|
||||
virtual void updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc);
|
||||
void serialize(std::ostream &os, u16 protocol_version);
|
||||
void deSerialize(std::istream &is);
|
||||
|
||||
private:
|
||||
void addNameIdMapping(content_t i, std::string name);
|
||||
#ifndef SERVER
|
||||
void fillTileAttribs(ITextureSource *tsrc, TileSpec *tile, TileDef *tiledef,
|
||||
u32 shader_id, bool use_normal_texture, bool backface_culling,
|
||||
u8 alpha, u8 material_type);
|
||||
#endif
|
||||
|
||||
// Features indexed by id
|
||||
std::vector<ContentFeatures> m_content_features;
|
||||
|
||||
// A mapping for fast converting back and forth between names and ids
|
||||
NameIdMapping m_name_id_mapping;
|
||||
|
||||
// Like m_name_id_mapping, but only from names to ids, and includes
|
||||
// item aliases too. Updated by updateAliases()
|
||||
// Note: Not serialized.
|
||||
|
||||
std::map<std::string, content_t> m_name_id_mapping_with_aliases;
|
||||
|
||||
// A mapping from groups to a list of content_ts (and their levels)
|
||||
// that belong to it. Necessary for a direct lookup in getIds().
|
||||
// Note: Not serialized.
|
||||
std::map<std::string, GroupItems> m_group_to_items;
|
||||
|
||||
// Next possibly free id
|
||||
content_t m_next_id;
|
||||
};
|
||||
|
||||
|
||||
CNodeDefManager::CNodeDefManager()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
CNodeDefManager::~CNodeDefManager()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CNodeDefManager::clear()
|
||||
{
|
||||
m_content_features.clear();
|
||||
m_name_id_mapping.clear();
|
||||
m_name_id_mapping_with_aliases.clear();
|
||||
|
@ -434,51 +492,56 @@ public:
|
|||
m_content_features[c] = f;
|
||||
addNameIdMapping(c, f.name);
|
||||
}
|
||||
}
|
||||
CNodeDefManager()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
virtual ~CNodeDefManager()
|
||||
{
|
||||
}
|
||||
virtual IWritableNodeDefManager* clone()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
IWritableNodeDefManager *CNodeDefManager::clone()
|
||||
{
|
||||
CNodeDefManager *mgr = new CNodeDefManager();
|
||||
*mgr = *this;
|
||||
return mgr;
|
||||
}
|
||||
virtual const ContentFeatures& get(content_t c) const
|
||||
{
|
||||
if(c < m_content_features.size())
|
||||
}
|
||||
|
||||
|
||||
const ContentFeatures& CNodeDefManager::get(content_t c) const
|
||||
{
|
||||
if (c < m_content_features.size())
|
||||
return m_content_features[c];
|
||||
else
|
||||
return m_content_features[CONTENT_UNKNOWN];
|
||||
}
|
||||
virtual const ContentFeatures& get(const MapNode &n) const
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const ContentFeatures& CNodeDefManager::get(const MapNode &n) const
|
||||
{
|
||||
return get(n.getContent());
|
||||
}
|
||||
virtual bool getId(const std::string &name, content_t &result) const
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool CNodeDefManager::getId(const std::string &name, content_t &result) const
|
||||
{
|
||||
std::map<std::string, content_t>::const_iterator
|
||||
i = m_name_id_mapping_with_aliases.find(name);
|
||||
if(i == m_name_id_mapping_with_aliases.end())
|
||||
return false;
|
||||
result = i->second;
|
||||
return true;
|
||||
}
|
||||
virtual content_t getId(const std::string &name) const
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
content_t CNodeDefManager::getId(const std::string &name) const
|
||||
{
|
||||
content_t id = CONTENT_IGNORE;
|
||||
getId(name, id);
|
||||
return id;
|
||||
}
|
||||
virtual void getIds(const std::string &name, std::set<content_t> &result)
|
||||
const
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CNodeDefManager::getIds(const std::string &name,
|
||||
std::set<content_t> &result) const
|
||||
{
|
||||
//TimeTaker t("getIds", NULL, PRECISION_MICRO);
|
||||
if(name.substr(0,6) != "group:"){
|
||||
if (name.substr(0,6) != "group:") {
|
||||
content_t id = CONTENT_IGNORE;
|
||||
if(getId(name, id))
|
||||
result.insert(id);
|
||||
|
@ -498,24 +561,28 @@ public:
|
|||
result.insert((*j).first);
|
||||
}
|
||||
//printf("getIds: %dus\n", t.stop());
|
||||
}
|
||||
virtual const ContentFeatures& get(const std::string &name) const
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const ContentFeatures& CNodeDefManager::get(const std::string &name) const
|
||||
{
|
||||
content_t id = CONTENT_UNKNOWN;
|
||||
getId(name, id);
|
||||
return get(id);
|
||||
}
|
||||
// returns CONTENT_IGNORE if no free ID found
|
||||
content_t allocateId()
|
||||
{
|
||||
for(content_t id = m_next_id;
|
||||
}
|
||||
|
||||
|
||||
// returns CONTENT_IGNORE if no free ID found
|
||||
content_t CNodeDefManager::allocateId()
|
||||
{
|
||||
for (content_t id = m_next_id;
|
||||
id >= m_next_id; // overflow?
|
||||
++id){
|
||||
while(id >= m_content_features.size()){
|
||||
++id) {
|
||||
while (id >= m_content_features.size()) {
|
||||
m_content_features.push_back(ContentFeatures());
|
||||
}
|
||||
const ContentFeatures &f = m_content_features[id];
|
||||
if(f.name == ""){
|
||||
if (f.name == "") {
|
||||
m_next_id = id + 1;
|
||||
return id;
|
||||
}
|
||||
|
@ -523,37 +590,37 @@ public:
|
|||
// If we arrive here, an overflow occurred in id.
|
||||
// That means no ID was found
|
||||
return CONTENT_IGNORE;
|
||||
}
|
||||
// IWritableNodeDefManager
|
||||
virtual content_t set(const std::string &name,
|
||||
const ContentFeatures &def)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// IWritableNodeDefManager
|
||||
content_t CNodeDefManager::set(const std::string &name, const ContentFeatures &def)
|
||||
{
|
||||
assert(name != "");
|
||||
assert(name == def.name);
|
||||
|
||||
// Don't allow redefining ignore (but allow air and unknown)
|
||||
if(name == "ignore"){
|
||||
infostream<<"NodeDefManager: WARNING: Ignoring "
|
||||
<<"CONTENT_IGNORE redefinition"<<std::endl;
|
||||
if (name == "ignore") {
|
||||
infostream << "NodeDefManager: WARNING: Ignoring "
|
||||
"CONTENT_IGNORE redefinition"<<std::endl;
|
||||
return CONTENT_IGNORE;
|
||||
}
|
||||
|
||||
content_t id = CONTENT_IGNORE;
|
||||
bool found = m_name_id_mapping.getId(name, id); // ignore aliases
|
||||
if(!found){
|
||||
if (!m_name_id_mapping.getId(name, id)) { // ignore aliases
|
||||
// Get new id
|
||||
id = allocateId();
|
||||
if(id == CONTENT_IGNORE){
|
||||
infostream<<"NodeDefManager: WARNING: Absolute "
|
||||
<<"limit reached"<<std::endl;
|
||||
if (id == CONTENT_IGNORE) {
|
||||
infostream << "NodeDefManager: WARNING: Absolute "
|
||||
"limit reached" << std::endl;
|
||||
return CONTENT_IGNORE;
|
||||
}
|
||||
assert(id != CONTENT_IGNORE);
|
||||
addNameIdMapping(id, name);
|
||||
}
|
||||
m_content_features[id] = def;
|
||||
verbosestream<<"NodeDefManager: registering content id \""<<id
|
||||
<<"\": name=\""<<def.name<<"\""<<std::endl;
|
||||
verbosestream << "NodeDefManager: registering content id \"" << id
|
||||
<< "\": name=\"" << def.name << "\""<<std::endl;
|
||||
|
||||
// Add this content to the list of all groups it belongs to
|
||||
// FIXME: This should remove a node from groups it no longer
|
||||
|
@ -573,65 +640,70 @@ public:
|
|||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
virtual content_t allocateDummy(const std::string &name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
content_t CNodeDefManager::allocateDummy(const std::string &name)
|
||||
{
|
||||
assert(name != "");
|
||||
ContentFeatures f;
|
||||
f.name = name;
|
||||
return set(name, f);
|
||||
}
|
||||
virtual void updateAliases(IItemDefManager *idef)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CNodeDefManager::updateAliases(IItemDefManager *idef)
|
||||
{
|
||||
std::set<std::string> all = idef->getAll();
|
||||
m_name_id_mapping_with_aliases.clear();
|
||||
for(std::set<std::string>::iterator
|
||||
i = all.begin(); i != all.end(); i++)
|
||||
{
|
||||
for (std::set<std::string>::iterator
|
||||
i = all.begin(); i != all.end(); i++) {
|
||||
std::string name = *i;
|
||||
std::string convert_to = idef->getAlias(name);
|
||||
content_t id;
|
||||
if(m_name_id_mapping.getId(convert_to, id))
|
||||
{
|
||||
if (m_name_id_mapping.getId(convert_to, id)) {
|
||||
m_name_id_mapping_with_aliases.insert(
|
||||
std::make_pair(name, id));
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void updateTextures(ITextureSource *tsrc,
|
||||
IShaderSource *shdsrc)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CNodeDefManager::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc)
|
||||
{
|
||||
#ifndef SERVER
|
||||
infostream<<"CNodeDefManager::updateTextures(): Updating "
|
||||
<<"textures in node definitions"<<std::endl;
|
||||
infostream << "CNodeDefManager::updateTextures(): Updating "
|
||||
"textures in node definitions" << std::endl;
|
||||
|
||||
bool new_style_water = g_settings->getBool("new_style_water");
|
||||
bool new_style_leaves = g_settings->getBool("new_style_leaves");
|
||||
bool connected_glass = g_settings->getBool("connected_glass");
|
||||
bool opaque_water = g_settings->getBool("opaque_water");
|
||||
bool enable_shaders = g_settings->getBool("enable_shaders");
|
||||
bool enable_bumpmapping = g_settings->getBool("enable_bumpmapping");
|
||||
bool enable_parallax_occlusion = g_settings->getBool("enable_parallax_occlusion");
|
||||
|
||||
for(u32 i=0; i<m_content_features.size(); i++)
|
||||
{
|
||||
bool use_normal_texture = enable_shaders &&
|
||||
(enable_bumpmapping || enable_parallax_occlusion);
|
||||
|
||||
for (u32 i = 0; i < m_content_features.size(); i++) {
|
||||
ContentFeatures *f = &m_content_features[i];
|
||||
|
||||
// Figure out the actual tiles to use
|
||||
TileDef tiledef[6];
|
||||
for(u32 j = 0; j < 6; j++)
|
||||
{
|
||||
for (u32 j = 0; j < 6; j++) {
|
||||
tiledef[j] = f->tiledef[j];
|
||||
if(tiledef[j].name == "")
|
||||
if (tiledef[j].name == "")
|
||||
tiledef[j].name = "unknown_node.png";
|
||||
}
|
||||
|
||||
bool is_liquid = false;
|
||||
bool is_water_surface = false;
|
||||
|
||||
u8 material_type;
|
||||
material_type = (f->alpha == 255) ? TILE_MATERIAL_BASIC : TILE_MATERIAL_ALPHA;
|
||||
u8 material_type = (f->alpha == 255) ?
|
||||
TILE_MATERIAL_BASIC : TILE_MATERIAL_ALPHA;
|
||||
|
||||
switch(f->drawtype){
|
||||
switch (f->drawtype) {
|
||||
default:
|
||||
case NDT_NORMAL:
|
||||
f->solidness = 2;
|
||||
|
@ -641,9 +713,9 @@ public:
|
|||
break;
|
||||
case NDT_LIQUID:
|
||||
assert(f->liquid_type == LIQUID_SOURCE);
|
||||
if(opaque_water)
|
||||
if (opaque_water)
|
||||
f->alpha = 255;
|
||||
if(new_style_water){
|
||||
if (new_style_water){
|
||||
f->solidness = 0;
|
||||
} else {
|
||||
f->solidness = 1;
|
||||
|
@ -654,7 +726,7 @@ public:
|
|||
case NDT_FLOWINGLIQUID:
|
||||
assert(f->liquid_type == LIQUID_FLOWING);
|
||||
f->solidness = 0;
|
||||
if(opaque_water)
|
||||
if (opaque_water)
|
||||
f->alpha = 255;
|
||||
is_liquid = true;
|
||||
break;
|
||||
|
@ -666,22 +738,26 @@ public:
|
|||
f->solidness = 0;
|
||||
f->visual_solidness = 1;
|
||||
break;
|
||||
case NDT_GLASSLIKE_FRAMED_OPTIONAL:
|
||||
f->solidness = 0;
|
||||
f->visual_solidness = 1;
|
||||
f->drawtype = connected_glass ? NDT_GLASSLIKE_FRAMED : NDT_GLASSLIKE;
|
||||
break;
|
||||
case NDT_ALLFACES:
|
||||
f->solidness = 0;
|
||||
f->visual_solidness = 1;
|
||||
break;
|
||||
case NDT_ALLFACES_OPTIONAL:
|
||||
if(new_style_leaves){
|
||||
if (new_style_leaves) {
|
||||
f->drawtype = NDT_ALLFACES;
|
||||
f->solidness = 0;
|
||||
f->visual_solidness = 1;
|
||||
} else {
|
||||
f->drawtype = NDT_NORMAL;
|
||||
f->solidness = 2;
|
||||
for(u32 i=0; i<6; i++){
|
||||
for (u32 i = 0; i < 6; i++)
|
||||
tiledef[i].name += std::string("^[noalpha");
|
||||
}
|
||||
}
|
||||
if (f->waving == 1)
|
||||
material_type = TILE_MATERIAL_WAVING_LEAVES;
|
||||
break;
|
||||
|
@ -693,6 +769,8 @@ public:
|
|||
break;
|
||||
case NDT_FIRELIKE:
|
||||
f->backface_culling = false;
|
||||
f->solidness = 0;
|
||||
break;
|
||||
case NDT_TORCHLIKE:
|
||||
case NDT_SIGNLIKE:
|
||||
case NDT_FENCELIKE:
|
||||
|
@ -702,135 +780,108 @@ public:
|
|||
break;
|
||||
}
|
||||
|
||||
if (is_liquid){
|
||||
material_type = (f->alpha == 255) ? TILE_MATERIAL_LIQUID_OPAQUE : TILE_MATERIAL_LIQUID_TRANSPARENT;
|
||||
if (is_liquid) {
|
||||
material_type = (f->alpha == 255) ?
|
||||
TILE_MATERIAL_LIQUID_OPAQUE : TILE_MATERIAL_LIQUID_TRANSPARENT;
|
||||
if (f->name == "default:water_source")
|
||||
is_water_surface = true;
|
||||
}
|
||||
u32 tile_shader[6];
|
||||
for(u16 j=0; j<6; j++)
|
||||
tile_shader[j] = shdsrc->getShader("nodes_shader",material_type, f->drawtype);
|
||||
|
||||
if (is_water_surface)
|
||||
tile_shader[0] = shdsrc->getShader("water_surface_shader",material_type, f->drawtype);
|
||||
u32 tile_shader[6];
|
||||
for (u16 j = 0; j < 6; j++) {
|
||||
tile_shader[j] = shdsrc->getShader("nodes_shader",
|
||||
material_type, f->drawtype);
|
||||
}
|
||||
|
||||
if (is_water_surface) {
|
||||
tile_shader[0] = shdsrc->getShader("water_surface_shader",
|
||||
material_type, f->drawtype);
|
||||
}
|
||||
|
||||
// Tiles (fill in f->tiles[])
|
||||
for(u16 j = 0; j < 6; j++){
|
||||
// Shader
|
||||
f->tiles[j].shader_id = tile_shader[j];
|
||||
// Texture
|
||||
f->tiles[j].texture = tsrc->getTexture(
|
||||
tiledef[j].name,
|
||||
&f->tiles[j].texture_id);
|
||||
// Normal texture
|
||||
if (enable_shaders && (enable_bumpmapping || enable_parallax_occlusion))
|
||||
f->tiles[j].normal_texture = tsrc->getNormalTexture(tiledef[j].name);
|
||||
// Alpha
|
||||
f->tiles[j].alpha = f->alpha;
|
||||
// Material type
|
||||
f->tiles[j].material_type = material_type;
|
||||
// Material flags
|
||||
f->tiles[j].material_flags = 0;
|
||||
if(f->backface_culling)
|
||||
f->tiles[j].material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
|
||||
if(tiledef[j].animation.type == TAT_VERTICAL_FRAMES)
|
||||
f->tiles[j].material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
|
||||
// Animation parameters
|
||||
int frame_count = 1;
|
||||
if(f->tiles[j].material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) {
|
||||
// Get texture size to determine frame count by
|
||||
// aspect ratio
|
||||
v2u32 size = f->tiles[j].texture->getOriginalSize();
|
||||
int frame_height = (float)size.X /
|
||||
(float)tiledef[j].animation.aspect_w *
|
||||
(float)tiledef[j].animation.aspect_h;
|
||||
frame_count = size.Y / frame_height;
|
||||
int frame_length_ms = 1000.0 *
|
||||
tiledef[j].animation.length / frame_count;
|
||||
f->tiles[j].animation_frame_count = frame_count;
|
||||
f->tiles[j].animation_frame_length_ms = frame_length_ms;
|
||||
}
|
||||
if(frame_count == 1) {
|
||||
f->tiles[j].material_flags &= ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
|
||||
} else {
|
||||
std::ostringstream os(std::ios::binary);
|
||||
for (int i = 0; i < frame_count; i++) {
|
||||
FrameSpec frame;
|
||||
os.str("");
|
||||
os<<tiledef[j].name<<"^[verticalframe:"<<frame_count<<":"<<i;
|
||||
frame.texture = tsrc->getTexture(os.str(), &frame.texture_id);
|
||||
if (f->tiles[j].normal_texture)
|
||||
frame.normal_texture = tsrc->getNormalTexture(os.str());
|
||||
f->tiles[j].frames[i]=frame;
|
||||
}
|
||||
}
|
||||
for (u16 j = 0; j < 6; j++) {
|
||||
fillTileAttribs(tsrc, &f->tiles[j], &tiledef[j], tile_shader[j],
|
||||
use_normal_texture, f->backface_culling, f->alpha, material_type);
|
||||
}
|
||||
|
||||
// Special tiles (fill in f->special_tiles[])
|
||||
for(u16 j=0; j<CF_SPECIAL_COUNT; j++){
|
||||
// Shader
|
||||
f->special_tiles[j].shader_id = tile_shader[j];
|
||||
// Texture
|
||||
f->special_tiles[j].texture = tsrc->getTexture(
|
||||
f->tiledef_special[j].name,
|
||||
&f->special_tiles[j].texture_id);
|
||||
// Normal texture
|
||||
if (enable_shaders && (enable_bumpmapping || enable_parallax_occlusion))
|
||||
f->special_tiles[j].normal_texture = tsrc->getNormalTexture(f->tiledef_special[j].name);
|
||||
// Alpha
|
||||
f->special_tiles[j].alpha = f->alpha;
|
||||
// Material type
|
||||
f->special_tiles[j].material_type = material_type;
|
||||
// Material flags
|
||||
f->special_tiles[j].material_flags = 0;
|
||||
if(f->tiledef_special[j].backface_culling)
|
||||
f->special_tiles[j].material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
|
||||
if(f->tiledef_special[j].animation.type == TAT_VERTICAL_FRAMES)
|
||||
f->special_tiles[j].material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
|
||||
// Animation parameters
|
||||
int frame_count = 1;
|
||||
if(f->special_tiles[j].material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) {
|
||||
// Get texture size to determine frame count by
|
||||
// aspect ratio
|
||||
v2u32 size = f->special_tiles[j].texture->getOriginalSize();
|
||||
int frame_height = (float)size.X /
|
||||
(float)f->tiledef_special[j].animation.aspect_w *
|
||||
(float)f->tiledef_special[j].animation.aspect_h;
|
||||
frame_count = size.Y / frame_height;
|
||||
int frame_length_ms = 1000.0 *
|
||||
f->tiledef_special[j].animation.length / frame_count;
|
||||
f->special_tiles[j].animation_frame_count = frame_count;
|
||||
f->special_tiles[j].animation_frame_length_ms = frame_length_ms;
|
||||
}
|
||||
if(frame_count == 1) {
|
||||
f->special_tiles[j].material_flags &= ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
|
||||
} else {
|
||||
std::ostringstream os(std::ios::binary);
|
||||
for (int i = 0; i < frame_count; i++) {
|
||||
FrameSpec frame;
|
||||
os.str("");
|
||||
os<<f->tiledef_special[j].name<<"^[verticalframe:"<<frame_count<<":"<<i;
|
||||
frame.texture = tsrc->getTexture(os.str(), &frame.texture_id);
|
||||
if (f->special_tiles[j].normal_texture)
|
||||
frame.normal_texture = tsrc->getNormalTexture(os.str());
|
||||
f->special_tiles[j].frames[i]=frame;
|
||||
}
|
||||
}
|
||||
for (u16 j = 0; j < CF_SPECIAL_COUNT; j++) {
|
||||
fillTileAttribs(tsrc, &f->special_tiles[j], &f->tiledef_special[j],
|
||||
tile_shader[j], use_normal_texture,
|
||||
f->tiledef_special[j].backface_culling, f->alpha, material_type);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef SERVER
|
||||
void CNodeDefManager::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile,
|
||||
TileDef *tiledef, u32 shader_id, bool use_normal_texture,
|
||||
bool backface_culling, u8 alpha, u8 material_type)
|
||||
{
|
||||
tile->shader_id = shader_id;
|
||||
tile->texture = tsrc->getTexture(tiledef->name, &tile->texture_id);
|
||||
tile->alpha = alpha;
|
||||
tile->material_type = material_type;
|
||||
|
||||
// Normal texture
|
||||
if (use_normal_texture)
|
||||
tile->normal_texture = tsrc->getNormalTexture(tiledef->name);
|
||||
|
||||
// Material flags
|
||||
tile->material_flags = 0;
|
||||
if (backface_culling)
|
||||
tile->material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
|
||||
if (tiledef->animation.type == TAT_VERTICAL_FRAMES)
|
||||
tile->material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
|
||||
|
||||
// Animation parameters
|
||||
int frame_count = 1;
|
||||
if (tile->material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) {
|
||||
// Get texture size to determine frame count by aspect ratio
|
||||
v2u32 size = tile->texture->getOriginalSize();
|
||||
int frame_height = (float)size.X /
|
||||
(float)tiledef->animation.aspect_w *
|
||||
(float)tiledef->animation.aspect_h;
|
||||
frame_count = size.Y / frame_height;
|
||||
int frame_length_ms = 1000.0 * tiledef->animation.length / frame_count;
|
||||
tile->animation_frame_count = frame_count;
|
||||
tile->animation_frame_length_ms = frame_length_ms;
|
||||
}
|
||||
void serialize(std::ostream &os, u16 protocol_version)
|
||||
{
|
||||
|
||||
if (frame_count == 1) {
|
||||
tile->material_flags &= ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
|
||||
} else {
|
||||
std::ostringstream os(std::ios::binary);
|
||||
for (int i = 0; i < frame_count; i++) {
|
||||
FrameSpec frame;
|
||||
|
||||
os.str("");
|
||||
os << tiledef->name << "^[verticalframe:"
|
||||
<< frame_count << ":" << i;
|
||||
|
||||
frame.texture = tsrc->getTexture(os.str(), &frame.texture_id);
|
||||
if (tile->normal_texture)
|
||||
frame.normal_texture = tsrc->getNormalTexture(os.str());
|
||||
tile->frames[i] = frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void CNodeDefManager::serialize(std::ostream &os, u16 protocol_version)
|
||||
{
|
||||
writeU8(os, 1); // version
|
||||
u16 count = 0;
|
||||
std::ostringstream os2(std::ios::binary);
|
||||
for(u32 i = 0; i < m_content_features.size(); i++)
|
||||
{
|
||||
if(i == CONTENT_IGNORE || i == CONTENT_AIR
|
||||
for (u32 i = 0; i < m_content_features.size(); i++) {
|
||||
if (i == CONTENT_IGNORE || i == CONTENT_AIR
|
||||
|| i == CONTENT_UNKNOWN)
|
||||
continue;
|
||||
ContentFeatures *f = &m_content_features[i];
|
||||
if(f->name == "")
|
||||
if (f->name == "")
|
||||
continue;
|
||||
writeU16(os2, i);
|
||||
// Wrap it in a string to allow different lengths without
|
||||
|
@ -843,18 +894,20 @@ public:
|
|||
count++;
|
||||
}
|
||||
writeU16(os, count);
|
||||
os<<serializeLongString(os2.str());
|
||||
}
|
||||
void deSerialize(std::istream &is)
|
||||
{
|
||||
os << serializeLongString(os2.str());
|
||||
}
|
||||
|
||||
|
||||
void CNodeDefManager::deSerialize(std::istream &is)
|
||||
{
|
||||
clear();
|
||||
int version = readU8(is);
|
||||
if(version != 1)
|
||||
if (version != 1)
|
||||
throw SerializationError("unsupported NodeDefinitionManager version");
|
||||
u16 count = readU16(is);
|
||||
std::istringstream is2(deSerializeLongString(is), std::ios::binary);
|
||||
ContentFeatures f;
|
||||
for(u16 n = 0; n < count; n++){
|
||||
for (u16 n = 0; n < count; n++) {
|
||||
u16 i = readU16(is2);
|
||||
|
||||
// Read it from the string wrapper
|
||||
|
@ -863,89 +916,70 @@ public:
|
|||
f.deSerialize(wrapper_is);
|
||||
|
||||
// Check error conditions
|
||||
if(i == CONTENT_IGNORE || i == CONTENT_AIR
|
||||
|| i == CONTENT_UNKNOWN){
|
||||
infostream<<"NodeDefManager::deSerialize(): WARNING: "
|
||||
<<"not changing builtin node "<<i
|
||||
<<std::endl;
|
||||
if (i == CONTENT_IGNORE || i == CONTENT_AIR || i == CONTENT_UNKNOWN) {
|
||||
infostream << "NodeDefManager::deSerialize(): WARNING: "
|
||||
"not changing builtin node " << i << std::endl;
|
||||
continue;
|
||||
}
|
||||
if(f.name == ""){
|
||||
infostream<<"NodeDefManager::deSerialize(): WARNING: "
|
||||
<<"received empty name"<<std::endl;
|
||||
if (f.name == "") {
|
||||
infostream << "NodeDefManager::deSerialize(): WARNING: "
|
||||
"received empty name" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore aliases
|
||||
u16 existing_id;
|
||||
bool found = m_name_id_mapping.getId(f.name, existing_id); // ignore aliases
|
||||
if(found && i != existing_id){
|
||||
infostream<<"NodeDefManager::deSerialize(): WARNING: "
|
||||
<<"already defined with different ID: "
|
||||
<<f.name<<std::endl;
|
||||
if (m_name_id_mapping.getId(f.name, existing_id) && i != existing_id) {
|
||||
infostream << "NodeDefManager::deSerialize(): WARNING: "
|
||||
"already defined with different ID: " << f.name << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// All is ok, add node definition with the requested ID
|
||||
if(i >= m_content_features.size())
|
||||
if (i >= m_content_features.size())
|
||||
m_content_features.resize((u32)(i) + 1);
|
||||
m_content_features[i] = f;
|
||||
addNameIdMapping(i, f.name);
|
||||
verbosestream<<"deserialized "<<f.name<<std::endl;
|
||||
verbosestream << "deserialized " << f.name << std::endl;
|
||||
}
|
||||
}
|
||||
private:
|
||||
void addNameIdMapping(content_t i, std::string name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CNodeDefManager::addNameIdMapping(content_t i, std::string name)
|
||||
{
|
||||
m_name_id_mapping.set(i, name);
|
||||
m_name_id_mapping_with_aliases.insert(std::make_pair(name, i));
|
||||
}
|
||||
private:
|
||||
// Features indexed by id
|
||||
std::vector<ContentFeatures> m_content_features;
|
||||
// A mapping for fast converting back and forth between names and ids
|
||||
NameIdMapping m_name_id_mapping;
|
||||
// Like m_name_id_mapping, but only from names to ids, and includes
|
||||
// item aliases too. Updated by updateAliases()
|
||||
// Note: Not serialized.
|
||||
std::map<std::string, content_t> m_name_id_mapping_with_aliases;
|
||||
// A mapping from groups to a list of content_ts (and their levels)
|
||||
// that belong to it. Necessary for a direct lookup in getIds().
|
||||
// Note: Not serialized.
|
||||
std::map<std::string, GroupItems> m_group_to_items;
|
||||
// Next possibly free id
|
||||
content_t m_next_id;
|
||||
};
|
||||
}
|
||||
|
||||
IWritableNodeDefManager* createNodeDefManager()
|
||||
|
||||
IWritableNodeDefManager *createNodeDefManager()
|
||||
{
|
||||
return new CNodeDefManager();
|
||||
}
|
||||
|
||||
/*
|
||||
Serialization of old ContentFeatures formats
|
||||
*/
|
||||
|
||||
//// Serialization of old ContentFeatures formats
|
||||
void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version)
|
||||
{
|
||||
if(protocol_version == 13)
|
||||
if (protocol_version == 13)
|
||||
{
|
||||
writeU8(os, 5); // version
|
||||
os<<serializeString(name);
|
||||
writeU16(os, groups.size());
|
||||
for(ItemGroupList::const_iterator
|
||||
i = groups.begin(); i != groups.end(); i++){
|
||||
for (ItemGroupList::const_iterator
|
||||
i = groups.begin(); i != groups.end(); i++) {
|
||||
os<<serializeString(i->first);
|
||||
writeS16(os, i->second);
|
||||
}
|
||||
writeU8(os, drawtype);
|
||||
writeF1000(os, visual_scale);
|
||||
writeU8(os, 6);
|
||||
for(u32 i = 0; i < 6; i++)
|
||||
for (u32 i = 0; i < 6; i++)
|
||||
tiledef[i].serialize(os, protocol_version);
|
||||
//CF_SPECIAL_COUNT = 2 before cf ver. 7 and protocol ver. 24
|
||||
writeU8(os, 2);
|
||||
for(u32 i = 0; i < 2; i++){
|
||||
for (u32 i = 0; i < 2; i++)
|
||||
tiledef_special[i].serialize(os, protocol_version);
|
||||
}
|
||||
writeU8(os, alpha);
|
||||
writeU8(os, post_effect_color.getAlpha());
|
||||
writeU8(os, post_effect_color.getRed());
|
||||
|
@ -980,21 +1014,20 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version)
|
|||
writeU8(os, 6); // version
|
||||
os<<serializeString(name);
|
||||
writeU16(os, groups.size());
|
||||
for(ItemGroupList::const_iterator
|
||||
i = groups.begin(); i != groups.end(); i++){
|
||||
for (ItemGroupList::const_iterator
|
||||
i = groups.begin(); i != groups.end(); i++) {
|
||||
os<<serializeString(i->first);
|
||||
writeS16(os, i->second);
|
||||
}
|
||||
writeU8(os, drawtype);
|
||||
writeF1000(os, visual_scale);
|
||||
writeU8(os, 6);
|
||||
for(u32 i = 0; i < 6; i++)
|
||||
for (u32 i = 0; i < 6; i++)
|
||||
tiledef[i].serialize(os, protocol_version);
|
||||
//CF_SPECIAL_COUNT = 2 before cf ver. 7 and protocol ver. 24
|
||||
writeU8(os, 2);
|
||||
for(u32 i = 0; i < 2; i++){
|
||||
for (u32 i = 0; i < 2; i++)
|
||||
tiledef_special[i].serialize(os, protocol_version);
|
||||
}
|
||||
writeU8(os, alpha);
|
||||
writeU8(os, post_effect_color.getAlpha());
|
||||
writeU8(os, post_effect_color.getRed());
|
||||
|
@ -1030,12 +1063,14 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version)
|
|||
writeU8(os, leveled);
|
||||
writeU8(os, liquid_range);
|
||||
} else
|
||||
throw SerializationError("ContentFeatures::serialize(): Unsupported version requested");
|
||||
throw SerializationError("ContentFeatures::serialize(): "
|
||||
"Unsupported version requested");
|
||||
}
|
||||
|
||||
|
||||
void ContentFeatures::deSerializeOld(std::istream &is, int version)
|
||||
{
|
||||
if(version == 5) // In PROTOCOL_VERSION 13
|
||||
if (version == 5) // In PROTOCOL_VERSION 13
|
||||
{
|
||||
name = deSerializeString(is);
|
||||
groups.clear();
|
||||
|
@ -1047,13 +1082,13 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version)
|
|||
}
|
||||
drawtype = (enum NodeDrawType)readU8(is);
|
||||
visual_scale = readF1000(is);
|
||||
if(readU8(is) != 6)
|
||||
if (readU8(is) != 6)
|
||||
throw SerializationError("unsupported tile count");
|
||||
for(u32 i=0; i<6; i++)
|
||||
for (u32 i = 0; i < 6; i++)
|
||||
tiledef[i].deSerialize(is);
|
||||
if(readU8(is) != CF_SPECIAL_COUNT)
|
||||
if (readU8(is) != CF_SPECIAL_COUNT)
|
||||
throw SerializationError("unsupported CF_SPECIAL_COUNT");
|
||||
for(u32 i=0; i<CF_SPECIAL_COUNT; i++)
|
||||
for (u32 i = 0; i < CF_SPECIAL_COUNT; i++)
|
||||
tiledef_special[i].deSerialize(is);
|
||||
alpha = readU8(is);
|
||||
post_effect_color.setAlpha(readU8(is));
|
||||
|
@ -1088,21 +1123,21 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version)
|
|||
name = deSerializeString(is);
|
||||
groups.clear();
|
||||
u32 groups_size = readU16(is);
|
||||
for(u32 i=0; i<groups_size; i++){
|
||||
for (u32 i = 0; i < groups_size; i++) {
|
||||
std::string name = deSerializeString(is);
|
||||
int value = readS16(is);
|
||||
groups[name] = value;
|
||||
}
|
||||
drawtype = (enum NodeDrawType)readU8(is);
|
||||
visual_scale = readF1000(is);
|
||||
if(readU8(is) != 6)
|
||||
if (readU8(is) != 6)
|
||||
throw SerializationError("unsupported tile count");
|
||||
for(u32 i=0; i<6; i++)
|
||||
for (u32 i = 0; i < 6; i++)
|
||||
tiledef[i].deSerialize(is);
|
||||
// CF_SPECIAL_COUNT in version 6 = 2
|
||||
if(readU8(is) != 2)
|
||||
if (readU8(is) != 2)
|
||||
throw SerializationError("unsupported CF_SPECIAL_COUNT");
|
||||
for(u32 i=0; i<2; i++)
|
||||
for (u32 i = 0; i < 2; i++)
|
||||
tiledef_special[i].deSerialize(is);
|
||||
alpha = readU8(is);
|
||||
post_effect_color.setAlpha(readU8(is));
|
||||
|
@ -1138,6 +1173,7 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version)
|
|||
drowning = readU8(is);
|
||||
leveled = readU8(is);
|
||||
liquid_range = readU8(is);
|
||||
} else
|
||||
} else {
|
||||
throw SerializationError("unsupported ContentFeatures version");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,7 +149,9 @@ enum NodeDrawType
|
|||
NDT_GLASSLIKE_FRAMED, // Glass-like, draw connected frames and all all
|
||||
// visible faces
|
||||
// uses 2 textures, one for frames, second for faces
|
||||
NDT_FIRELIKE, // Draw faces slightly rotated and only on connecting nodes
|
||||
NDT_FIRELIKE, // Draw faces slightly rotated and only on connecting nodes,
|
||||
NDT_GLASSLIKE_FRAMED_OPTIONAL, // enabled -> connected, disabled -> Glass-like
|
||||
// uses 2 textures, one for frames, second for faces
|
||||
};
|
||||
|
||||
#define CF_SPECIAL_COUNT 6
|
||||
|
|
|
@ -28,8 +28,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "content_sao.h"
|
||||
#include "filesys.h"
|
||||
#include "log.h"
|
||||
#include "porting.h" // strlcpy
|
||||
|
||||
Player::Player(IGameDef *gamedef):
|
||||
|
||||
Player::Player(IGameDef *gamedef, const char *name):
|
||||
touching_ground(false),
|
||||
in_liquid(false),
|
||||
in_liquid_stable(false),
|
||||
|
@ -52,20 +54,17 @@ Player::Player(IGameDef *gamedef):
|
|||
m_speed(0,0,0),
|
||||
m_position(0,0,0),
|
||||
m_collisionbox(-BS*0.30,0.0,-BS*0.30,BS*0.30,BS*1.75,BS*0.30),
|
||||
m_last_pitch(0),
|
||||
m_last_yaw(0),
|
||||
m_last_pos(0,0,0),
|
||||
m_last_hp(PLAYER_MAX_HP),
|
||||
m_last_inventory(gamedef->idef())
|
||||
m_dirty(false)
|
||||
{
|
||||
updateName("<not set>");
|
||||
strlcpy(m_name, name, PLAYERNAME_SIZE);
|
||||
|
||||
inventory.clear();
|
||||
inventory.addList("main", PLAYER_INVENTORY_SIZE);
|
||||
InventoryList *craft = inventory.addList("craft", 9);
|
||||
craft->setWidth(3);
|
||||
inventory.addList("craftpreview", 1);
|
||||
inventory.addList("craftresult", 1);
|
||||
m_last_inventory = inventory;
|
||||
inventory.setModified(false);
|
||||
|
||||
// Can be redefined via Lua
|
||||
inventory_formspec = "size[8,7.5]"
|
||||
|
@ -205,9 +204,10 @@ void Player::deSerialize(std::istream &is, std::string playername)
|
|||
playername + " not found!");
|
||||
}
|
||||
|
||||
m_dirty = true;
|
||||
//args.getS32("version"); // Version field value not used
|
||||
std::string name = args.get("name");
|
||||
updateName(name.c_str());
|
||||
strlcpy(m_name, name.c_str(), PLAYERNAME_SIZE);
|
||||
setPitch(args.getFloat("pitch"));
|
||||
setYaw(args.getFloat("yaw"));
|
||||
setPosition(args.getV3F("position"));
|
||||
|
@ -237,9 +237,6 @@ void Player::deSerialize(std::istream &is, std::string playername)
|
|||
inventory.getList("craftresult")->changeItem(0, ItemStack());
|
||||
}
|
||||
}
|
||||
|
||||
// Set m_last_*
|
||||
checkModified();
|
||||
}
|
||||
|
||||
u32 Player::addHud(HudElement *toadd)
|
||||
|
@ -290,7 +287,7 @@ void RemotePlayer::save(std::string savedir)
|
|||
*/
|
||||
|
||||
// A player to deserialize files into to check their names
|
||||
RemotePlayer testplayer(m_gamedef);
|
||||
RemotePlayer testplayer(m_gamedef, "");
|
||||
|
||||
savedir += DIR_DELIM;
|
||||
std::string path = savedir + m_name;
|
||||
|
@ -302,6 +299,7 @@ void RemotePlayer::save(std::string savedir)
|
|||
if (!fs::safeWriteToFile(path, ss.str())) {
|
||||
infostream << "Failed to write " << path << std::endl;
|
||||
}
|
||||
setModified(false);
|
||||
return;
|
||||
}
|
||||
// Open file and deserialize
|
||||
|
@ -319,6 +317,7 @@ void RemotePlayer::save(std::string savedir)
|
|||
if (!fs::safeWriteToFile(path, ss.str())) {
|
||||
infostream << "Failed to write " << path << std::endl;
|
||||
}
|
||||
setModified(false);
|
||||
return;
|
||||
}
|
||||
path = savedir + m_name + itos(i);
|
||||
|
|
47
src/player.h
47
src/player.h
|
@ -95,7 +95,7 @@ class Player
|
|||
{
|
||||
public:
|
||||
|
||||
Player(IGameDef *gamedef);
|
||||
Player(IGameDef *gamedef, const char *name);
|
||||
virtual ~Player() = 0;
|
||||
|
||||
virtual void move(f32 dtime, Environment *env, f32 pos_max_d)
|
||||
|
@ -142,16 +142,22 @@ public:
|
|||
|
||||
virtual void setPosition(const v3f &position)
|
||||
{
|
||||
if (position != m_position)
|
||||
m_dirty = true;
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
void setPitch(f32 pitch)
|
||||
{
|
||||
if (pitch != m_pitch)
|
||||
m_dirty = true;
|
||||
m_pitch = pitch;
|
||||
}
|
||||
|
||||
virtual void setYaw(f32 yaw)
|
||||
{
|
||||
if (yaw != m_yaw)
|
||||
m_dirty = true;
|
||||
m_yaw = yaw;
|
||||
}
|
||||
|
||||
|
@ -172,6 +178,8 @@ public:
|
|||
|
||||
virtual void setBreath(u16 breath)
|
||||
{
|
||||
if (breath != m_breath)
|
||||
m_dirty = true;
|
||||
m_breath = breath;
|
||||
}
|
||||
|
||||
|
@ -185,11 +193,6 @@ public:
|
|||
return (m_yaw + 90.) * core::DEGTORAD;
|
||||
}
|
||||
|
||||
void updateName(const char *name)
|
||||
{
|
||||
snprintf(m_name, PLAYERNAME_SIZE, "%s", name);
|
||||
}
|
||||
|
||||
const char * getName() const
|
||||
{
|
||||
return m_name;
|
||||
|
@ -223,21 +226,16 @@ public:
|
|||
void serialize(std::ostream &os);
|
||||
void deSerialize(std::istream &is, std::string playername);
|
||||
|
||||
bool checkModified()
|
||||
bool checkModified() const
|
||||
{
|
||||
if(m_last_hp != hp || m_last_pitch != m_pitch ||
|
||||
m_last_pos != m_position || m_last_yaw != m_yaw ||
|
||||
!(inventory == m_last_inventory))
|
||||
{
|
||||
m_last_hp = hp;
|
||||
m_last_pitch = m_pitch;
|
||||
m_last_pos = m_position;
|
||||
m_last_yaw = m_yaw;
|
||||
m_last_inventory = inventory;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
return m_dirty || inventory.checkModified();
|
||||
}
|
||||
|
||||
void setModified(const bool x)
|
||||
{
|
||||
m_dirty = x;
|
||||
if (x == false)
|
||||
inventory.setModified(x);
|
||||
}
|
||||
|
||||
bool touching_ground;
|
||||
|
@ -316,11 +314,7 @@ protected:
|
|||
v3f m_position;
|
||||
core::aabbox3d<f32> m_collisionbox;
|
||||
|
||||
f32 m_last_pitch;
|
||||
f32 m_last_yaw;
|
||||
v3f m_last_pos;
|
||||
u16 m_last_hp;
|
||||
Inventory m_last_inventory;
|
||||
bool m_dirty;
|
||||
|
||||
std::vector<HudElement *> hud;
|
||||
};
|
||||
|
@ -332,7 +326,10 @@ protected:
|
|||
class RemotePlayer : public Player
|
||||
{
|
||||
public:
|
||||
RemotePlayer(IGameDef *gamedef): Player(gamedef), m_sao(0) {}
|
||||
RemotePlayer(IGameDef *gamedef, const char *name):
|
||||
Player(gamedef, name),
|
||||
m_sao(NULL)
|
||||
{}
|
||||
virtual ~RemotePlayer() {}
|
||||
|
||||
void save(std::string savedir);
|
||||
|
|
|
@ -480,7 +480,7 @@ void initializePaths()
|
|||
bindir + DIR_DELIM + ".." + DIR_DELIM + "share" + DIR_DELIM + PROJECT_NAME);
|
||||
trylist.push_back(bindir + DIR_DELIM + "..");
|
||||
#ifdef __ANDROID__
|
||||
trylist.push_back(DIR_DELIM "sdcard" DIR_DELIM PROJECT_NAME);
|
||||
trylist.push_back(path_user);
|
||||
#endif
|
||||
|
||||
for(std::list<std::string>::const_iterator i = trylist.begin();
|
||||
|
@ -502,8 +502,6 @@ void initializePaths()
|
|||
}
|
||||
#ifndef __ANDROID__
|
||||
path_user = std::string(getenv("HOME")) + DIR_DELIM + "." + PROJECT_NAME;
|
||||
#else
|
||||
path_user = std::string(DIR_DELIM "sdcard" DIR_DELIM PROJECT_NAME DIR_DELIM);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
@ -35,6 +35,7 @@ struct EnumString ScriptApiNode::es_DrawType[] =
|
|||
{NDT_FLOWINGLIQUID, "flowingliquid"},
|
||||
{NDT_GLASSLIKE, "glasslike"},
|
||||
{NDT_GLASSLIKE_FRAMED, "glasslike_framed"},
|
||||
{NDT_GLASSLIKE_FRAMED_OPTIONAL, "glasslike_framed_optional"},
|
||||
{NDT_ALLFACES, "allfaces"},
|
||||
{NDT_ALLFACES_OPTIONAL, "allfaces_optional"},
|
||||
{NDT_TORCHLIKE, "torchlike"},
|
||||
|
|
|
@ -5038,15 +5038,17 @@ PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
|
|||
// Create player if it doesn't exist
|
||||
if (!player) {
|
||||
newplayer = true;
|
||||
player = new RemotePlayer(this);
|
||||
player->updateName(name);
|
||||
/* Set player position */
|
||||
player = new RemotePlayer(this, name);
|
||||
// Set player position
|
||||
infostream<<"Server: Finding spawn place for player \""
|
||||
<<name<<"\""<<std::endl;
|
||||
v3f pos = findSpawnPos(m_env->getServerMap());
|
||||
player->setPosition(pos);
|
||||
|
||||
/* Add player to environment */
|
||||
// Make sure the player is saved
|
||||
player->setModified(true);
|
||||
|
||||
// Add player to environment
|
||||
m_env->addPlayer(player);
|
||||
}
|
||||
|
||||
|
|
|
@ -645,7 +645,8 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
|
|||
"NDT_RAILLIKE",
|
||||
"NDT_NODEBOX",
|
||||
"NDT_GLASSLIKE_FRAMED",
|
||||
"NDT_FIRELIKE"
|
||||
"NDT_FIRELIKE",
|
||||
"NDT_GLASSLIKE_FRAMED_OPTIONAL"
|
||||
};
|
||||
|
||||
for (int i = 0; i < 14; i++){
|
||||
|
|
41
src/tile.cpp
41
src/tile.cpp
|
@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "log.h"
|
||||
#include "gamedef.h"
|
||||
#include "strfnd.h"
|
||||
#include "util/string.h" // for parseColorString()
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <GLES/gl.h>
|
||||
|
@ -1632,10 +1633,46 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
|||
baseimg->drop();
|
||||
baseimg = img;
|
||||
}
|
||||
/*
|
||||
[colorize:color
|
||||
Overlays image with given color
|
||||
color = color as ColorString
|
||||
*/
|
||||
else if (part_of_name.substr(0,10) == "[colorize:") {
|
||||
Strfnd sf(part_of_name);
|
||||
sf.next(":");
|
||||
std::string color_str = sf.next(":");
|
||||
|
||||
if (baseimg == NULL) {
|
||||
errorstream << "generateImagePart(): baseimg != NULL "
|
||||
<< "for part_of_name=\"" << part_of_name
|
||||
<< "\", cancelling." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
video::SColor color;
|
||||
if (!parseColorString(color_str, color, false))
|
||||
return false;
|
||||
|
||||
core::dimension2d<u32> dim = baseimg->getDimension();
|
||||
video::IImage *img = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||
|
||||
if (!img) {
|
||||
errorstream << "generateImagePart(): Could not create image "
|
||||
<< "for part_of_name=\"" << part_of_name
|
||||
<< "\", cancelling." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
img->fill(video::SColor(color));
|
||||
// Overlay the colored image
|
||||
blit_with_alpha_overlay(img, baseimg, v2s32(0,0), v2s32(0,0), dim);
|
||||
img->drop();
|
||||
}
|
||||
else
|
||||
{
|
||||
errorstream<<"generateImagePart(): Invalid "
|
||||
" modification: \""<<part_of_name<<"\""<<std::endl;
|
||||
errorstream << "generateImagePart(): Invalid "
|
||||
" modification: \"" << part_of_name << "\"" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -229,7 +229,7 @@ struct TileSpec
|
|||
// Sets everything else except the texture in the material
|
||||
void applyMaterialOptions(video::SMaterial &material) const
|
||||
{
|
||||
switch(material_type){
|
||||
switch (material_type) {
|
||||
case TILE_MATERIAL_BASIC:
|
||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
break;
|
||||
|
@ -249,12 +249,14 @@ struct TileSpec
|
|||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
break;
|
||||
}
|
||||
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) ? true : false;
|
||||
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING)
|
||||
? true : false;
|
||||
}
|
||||
|
||||
void applyMaterialOptionsWithShaders(video::SMaterial &material) const
|
||||
{
|
||||
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) ? true : false;
|
||||
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING)
|
||||
? true : false;
|
||||
}
|
||||
|
||||
u32 texture_id;
|
||||
|
|
|
@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "string.h"
|
||||
#include "pointer.h"
|
||||
#include "numeric.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
@ -30,7 +31,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "../porting.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
const wchar_t* wide_chars = L" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
|
||||
const wchar_t* wide_chars =
|
||||
L" !\"#$%&'()*+,-./0123456789:;<=>?@"
|
||||
L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`"
|
||||
L"abcdefghijklmnopqrstuvwxyz{|}~";
|
||||
|
||||
int wctomb(char *s, wchar_t wc)
|
||||
{
|
||||
|
@ -300,3 +304,65 @@ u64 read_seed(const char *str)
|
|||
|
||||
return num;
|
||||
}
|
||||
|
||||
bool parseColorString(const std::string &value, video::SColor &color, bool quiet)
|
||||
{
|
||||
const char *hexpattern = NULL;
|
||||
video::SColor outcolor(255, 255, 255, 255);
|
||||
|
||||
if (value[0] == '#') {
|
||||
if (value.size() == 9)
|
||||
hexpattern = "#RRGGBBAA";
|
||||
else if (value.size() == 7)
|
||||
hexpattern = "#RRGGBB";
|
||||
else if (value.size() == 5)
|
||||
hexpattern = "#RGBA";
|
||||
else if (value.size() == 4)
|
||||
hexpattern = "#RGB";
|
||||
}
|
||||
|
||||
if (!hexpattern)
|
||||
goto fail;
|
||||
|
||||
assert(strlen(hexpattern) == value.size());
|
||||
for (size_t pos = 0; pos < value.size(); ++pos) {
|
||||
// '#' in the pattern means skip that character
|
||||
if (hexpattern[pos] == '#')
|
||||
continue;
|
||||
|
||||
// Else assume hexpattern[pos] is one of 'R' 'G' 'B' 'A'
|
||||
// Read one or two digits, depending on hexpattern
|
||||
unsigned char c1, c2;
|
||||
if (hexpattern[pos+1] == hexpattern[pos]) {
|
||||
// Two digits, e.g. hexpattern == "#RRGGBB"
|
||||
if (!hex_digit_decode(value[pos], c1) ||
|
||||
!hex_digit_decode(value[pos+1], c2))
|
||||
goto fail;
|
||||
++pos;
|
||||
} else {
|
||||
// One digit, e.g. hexpattern == "#RGB"
|
||||
if (!hex_digit_decode(value[pos], c1))
|
||||
goto fail;
|
||||
c2 = c1;
|
||||
}
|
||||
u32 colorpart = ((c1 & 0x0f) << 4) | (c2 & 0x0f);
|
||||
|
||||
// Update outcolor with newly read color part
|
||||
if (hexpattern[pos] == 'R')
|
||||
outcolor.setRed(colorpart);
|
||||
else if (hexpattern[pos] == 'G')
|
||||
outcolor.setGreen(colorpart);
|
||||
else if (hexpattern[pos] == 'B')
|
||||
outcolor.setBlue(colorpart);
|
||||
else if (hexpattern[pos] == 'A')
|
||||
outcolor.setAlpha(colorpart);
|
||||
}
|
||||
|
||||
color = outcolor;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
if (!quiet)
|
||||
errorstream << "Invalid color: \"" << value << "\"" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#ifndef UTIL_STRING_HEADER
|
||||
#define UTIL_STRING_HEADER
|
||||
|
||||
#include "../irrlichttypes.h"
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
@ -113,6 +113,16 @@ inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t deli
|
|||
return parts;
|
||||
}
|
||||
|
||||
inline std::vector<std::string> str_split(const std::string &str, char delimiter) {
|
||||
|
||||
std::vector<std::string> parts;
|
||||
std::stringstream sstr(str);
|
||||
std::string part;
|
||||
while(std::getline(sstr, part, delimiter))
|
||||
parts.push_back(part);
|
||||
return parts;
|
||||
}
|
||||
|
||||
inline std::string lowercase(const std::string &s)
|
||||
{
|
||||
std::string s2;
|
||||
|
@ -339,6 +349,7 @@ std::string writeFlagString(u32 flags, const FlagDesc *flagdesc, u32 flagmask);
|
|||
size_t mystrlcpy(char *dst, const char *src, size_t size);
|
||||
char *mystrtok_r(char *s, const char *sep, char **lasts);
|
||||
u64 read_seed(const char *str);
|
||||
bool parseColorString(const std::string &value, video::SColor &color, bool quiet);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -48,7 +48,11 @@ cd ..
|
|||
# directory at the top level. You a recent enough xgettext that supports
|
||||
# --package-name
|
||||
potfile=po/minetest.pot
|
||||
xgettext --package-name=minetest -kN_ -kwgettext -kfgettext -F -n -o $potfile src/*.cpp src/*.h builtin/*.lua
|
||||
xgettext --package-name=minetest \
|
||||
-kN_ -kwgettext -kfgettext \
|
||||
-F -n -o $potfile \
|
||||
`find src/ -name '*.cpp' -o -name '*.h'` \
|
||||
`find builtin/ -name '*.lua'`
|
||||
|
||||
# Now iterate on all languages and create the po file if missing, or update it
|
||||
# if it exists already
|
||||
|
|
Loading…
Reference in New Issue