aboutsummaryrefslogtreecommitdiff
path: root/cmake/Modules/FindNcursesw.cmake
blob: e572c704af5ba649319f690bd8a1a5b4394320c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#.rst:
# FindNcursesw
# ------------
#
# Find the ncursesw (wide ncurses) include file and library.
#
# Based on FindCurses.cmake which comes with CMake.
#
# Checks for ncursesw first. If not found, it then executes the
# regular old FindCurses.cmake to look for for ncurses (or curses).
#
#
# Result Variables
# ^^^^^^^^^^^^^^^^
#
# This module defines the following variables:
#
# ``CURSES_FOUND``
#   True if curses is found.
# ``NCURSESW_FOUND``
#   True if ncursesw is found.
# ``CURSES_INCLUDE_DIRS``
#   The include directories needed to use Curses.
# ``CURSES_LIBRARIES``
#   The libraries needed to use Curses.
# ``CURSES_HAVE_CURSES_H``
#   True if curses.h is available.
# ``CURSES_HAVE_NCURSES_H``
#   True if ncurses.h is available.
# ``CURSES_HAVE_NCURSES_NCURSES_H``
#   True if ``ncurses/ncurses.h`` is available.
# ``CURSES_HAVE_NCURSES_CURSES_H``
#   True if ``ncurses/curses.h`` is available.
# ``CURSES_HAVE_NCURSESW_NCURSES_H``
#   True if ``ncursesw/ncurses.h`` is available.
# ``CURSES_HAVE_NCURSESW_CURSES_H``
#   True if ``ncursesw/curses.h`` is available.
#
# Set ``CURSES_NEED_NCURSES`` to ``TRUE`` before the
# ``find_package(Ncursesw)`` call if NCurses functionality is required.
#
#=============================================================================
# Copyright 2001-2014 Kitware, Inc.
# modifications: Copyright 2015 kahrl <kahrl@gmx.net>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
#   notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in the
#   documentation and/or other materials provided with the distribution.
#
# * Neither the names of Kitware, Inc., the Insight Software Consortium,
#   nor the names of their contributors may be used to endorse or promote
#   products derived from this software without specific prior written
#   permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# ------------------------------------------------------------------------------
#
# The above copyright and license notice applies to distributions of
# CMake in source and binary form.  Some source files contain additional
# notices of original copyright by their contributors; see each source
# for details.  Third-party software packages supplied with CMake under
# compatible licenses provide their own copyright notices documented in
# corresponding subdirectories.
#
# ------------------------------------------------------------------------------
#
# CMake was initially developed by Kitware with the following sponsorship:
#
#  * National Library of Medicine at the National Institutes of Health
#    as part of the Insight Segmentation and Registration Toolkit (ITK).
#
#  * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel
#    Visualization Initiative.
#
#  * National Alliance for Medical Image Computing (NAMIC) is funded by the
#    National Institutes of Health through the NIH Roadmap for Medical Research,
#    Grant U54 EB005149.
#
#  * Kitware, Inc.
#=============================================================================

include(CheckLibraryExists)

find_library(CURSES_NCURSESW_LIBRARY NAMES ncursesw
  DOC "Path to libncursesw.so or .lib or .a")

set(CURSES_USE_NCURSES FALSE)
set(CURSES_USE_NCURSESW FALSE)

if(CURSES_NCURSESW_LIBRARY)
  set(CURSES_USE_NCURSES TRUE)
  set(CURSES_USE_NCURSESW TRUE)
endif()

if(CURSES_USE_NCURSESW)
  get_filename_component(_cursesLibDir "${CURSES_NCURSESW_LIBRARY}" PATH)
  get_filename_component(_cursesParentDir "${_cursesLibDir}" PATH)

  find_path(CURSES_INCLUDE_PATH
    NAMES ncursesw/ncurses.h ncursesw/curses.h ncurses.h curses.h
    HINTS "${_cursesParentDir}/include"
    )

  # Previous versions of FindCurses provided these values.
  if(NOT DEFINED CURSES_LIBRARY)
    set(CURSES_LIBRARY "${CURSES_NCURSESW_LIBRARY}")
  endif()

  CHECK_LIBRARY_EXISTS("${CURSES_NCURSESW_LIBRARY}"
    cbreak "" CURSES_NCURSESW_HAS_CBREAK)
  if(NOT CURSES_NCURSESW_HAS_CBREAK)
    find_library(CURSES_EXTRA_LIBRARY tinfo HINTS "${_cursesLibDir}"
      DOC "Path to libtinfo.so or .lib or .a")
    find_library(CURSES_EXTRA_LIBRARY tinfo )
  endif()

  # Report whether each possible header name exists in the include directory.
  if(NOT DEFINED CURSES_HAVE_NCURSESW_NCURSES_H)
    if(EXISTS "${CURSES_INCLUDE_PATH}/ncursesw/ncurses.h")
      set(CURSES_HAVE_NCURSESW_NCURSES_H "${CURSES_INCLUDE_PATH}/ncursesw/ncurses.h")
    else()
      set(CURSES_HAVE_NCURSESW_NCURSES_H "CURSES_HAVE_NCURSESW_NCURSES_H-NOTFOUND")
    endif()
  endif()
  if(NOT DEFINED CURSES_HAVE_NCURSESW_CURSES_H)
    if(EXISTS "${CURSES_INCLUDE_PATH}/ncursesw/curses.h")
      set(CURSES_HAVE_NCURSESW_CURSES_H "${CURSES_INCLUDE_PATH}/ncursesw/curses.h")
    else()
      set(CURSES_HAVE_NCURSESW_CURSES_H "CURSES_HAVE_NCURSESW_CURSES_H-NOTFOUND")
    endif()
  endif()
  if(NOT DEFINED CURSES_HAVE_NCURSES_H)
    if(EXISTS "${CURSES_INCLUDE_PATH}/ncurses.h")
      set(CURSES_HAVE_NCURSES_H "${CURSES_INCLUDE_PATH}/ncurses.h")
    else()
      set(CURSES_HAVE_NCURSES_H "CURSES_HAVE_NCURSES_H-NOTFOUND")
    endif()
  endif()
  if(NOT DEFINED CURSES_HAVE_CURSES_H)
    if(EXISTS "${CURSES_INCLUDE_PATH}/curses.h")
      set(CURSES_HAVE_CURSES_H "${CURSES_INCLUDE_PATH}/curses.h")
    else()
      set(CURSES_HAVE_CURSES_H "CURSES_HAVE_CURSES_H-NOTFOUND")
    endif()
  endif()


  find_library(CURSES_FORM_LIBRARY form HINTS "${_cursesLibDir}"
    DOC "Path to libform.so or .lib or .a")
  find_library(CURSES_FORM_LIBRARY form )

  # Need to provide the *_LIBRARIES
  set(CURSES_LIBRARIES ${CURSES_LIBRARY})

  if(CURSES_EXTRA_LIBRARY)
    set(CURSES_LIBRARIES ${CURSES_LIBRARIES} ${CURSES_EXTRA_LIBRARY})
  endif()

  if(CURSES_FORM_LIBRARY)
    set(CURSES_LIBRARIES ${CURSES_LIBRARIES} ${CURSES_FORM_LIBRARY})
  endif()

  # Provide the *_INCLUDE_DIRS result.
  set(CURSES_INCLUDE_DIRS ${CURSES_INCLUDE_PATH})
  set(CURSES_INCLUDE_DIR ${CURSES_INCLUDE_PATH}) # compatibility

  # handle the QUIETLY and REQUIRED arguments and set CURSES_FOUND to TRUE if
  # all listed variables are TRUE
  include(FindPackageHandleStandardArgs)
  FIND_PACKAGE_HANDLE_STANDARD_ARGS(Ncursesw DEFAULT_MSG
    CURSES_LIBRARY CURSES_INCLUDE_PATH)
  set(CURSES_FOUND ${NCURSESW_FOUND})

else()
  find_package(Curses)
  set(NCURSESW_FOUND FALSE)
endif()

mark_as_advanced(
  CURSES_INCLUDE_PATH
  CURSES_CURSES_LIBRARY
  CURSES_NCURSES_LIBRARY
  CURSES_NCURSESW_LIBRARY
  CURSES_EXTRA_LIBRARY
  CURSES_FORM_LIBRARY
  )
2013 celeron55, Perttu Ahola <celeron55@gmail.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "irrlichttypes_extrabloated.h" #include "mapnode.h" #include "porting.h" #include "nodedef.h" #include "content_mapnode.h" // For mapnode_translate_*_internal #include "serialization.h" // For ser_ver_supported #include "util/serialize.h" #include "log.h" #include "util/numeric.h" #include <string> #include <sstream> static const Rotation wallmounted_to_rot[] = { ROTATE_0, ROTATE_180, ROTATE_90, ROTATE_270 }; static const u8 rot_to_wallmounted[] = { 2, 4, 3, 5 }; /* MapNode */ // Create directly from a nodename // If name is unknown, sets CONTENT_IGNORE MapNode::MapNode(INodeDefManager *ndef, const std::string &name, u8 a_param1, u8 a_param2) { content_t id = CONTENT_IGNORE; ndef->getId(name, id); param0 = id; param1 = a_param1; param2 = a_param2; } void MapNode::setLight(enum LightBank bank, u8 a_light, const ContentFeatures &f) { // If node doesn't contain light data, ignore this if(f.param_type != CPT_LIGHT) return; if(bank == LIGHTBANK_DAY) { param1 &= 0xf0; param1 |= a_light & 0x0f; } else if(bank == LIGHTBANK_NIGHT) { param1 &= 0x0f; param1 |= (a_light & 0x0f)<<4; } else assert("Invalid light bank" == NULL); } void MapNode::setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr) { setLight(bank, a_light, nodemgr->get(*this)); } bool MapNode::isLightDayNightEq(INodeDefManager *nodemgr) const { const ContentFeatures &f = nodemgr->get(*this); bool isEqual; if (f.param_type == CPT_LIGHT) { u8 day = MYMAX(f.light_source, param1 & 0x0f); u8 night = MYMAX(f.light_source, (param1 >> 4) & 0x0f); isEqual = day == night; } else { isEqual = true; } return isEqual; } u8 MapNode::getLight(enum LightBank bank, INodeDefManager *nodemgr) const { // Select the brightest of [light source, propagated light] const ContentFeatures &f = nodemgr->get(*this); u8 light; if(f.param_type == CPT_LIGHT) light = bank == LIGHTBANK_DAY ? param1 & 0x0f : (param1 >> 4) & 0x0f; else light = 0; return MYMAX(f.light_source, light); } u8 MapNode::getLightRaw(enum LightBank bank, const ContentFeatures &f) const { if(f.param_type == CPT_LIGHT) return bank == LIGHTBANK_DAY ? param1 & 0x0f : (param1 >> 4) & 0x0f; return 0; } u8 MapNode::getLightNoChecks(enum LightBank bank, const ContentFeatures *f) const { return MYMAX(f->light_source, bank == LIGHTBANK_DAY ? param1 & 0x0f : (param1 >> 4) & 0x0f); } bool MapNode::getLightBanks(u8 &lightday, u8 &lightnight, INodeDefManager *nodemgr) const { // Select the brightest of [light source, propagated light] const ContentFeatures &f = nodemgr->get(*this); if(f.param_type == CPT_LIGHT) { lightday = param1 & 0x0f; lightnight = (param1>>4)&0x0f; } else { lightday = 0; lightnight = 0; } if(f.light_source > lightday) lightday = f.light_source; if(f.light_source > lightnight) lightnight = f.light_source; return f.param_type == CPT_LIGHT || f.light_source != 0; } u8 MapNode::getFaceDir(INodeDefManager *nodemgr) const { const ContentFeatures &f = nodemgr->get(*this); if(f.param_type_2 == CPT2_FACEDIR) return (getParam2() & 0x1F) % 24; return 0; } u8 MapNode::getWallMounted(INodeDefManager *nodemgr) const { const ContentFeatures &f = nodemgr->get(*this); if(f.param_type_2 == CPT2_WALLMOUNTED) return getParam2() & 0x07; return 0; } v3s16 MapNode::getWallMountedDir(INodeDefManager *nodemgr) const { switch(getWallMounted(nodemgr)) { case 0: default: return v3s16(0,1,0); case 1: return v3s16(0,-1,0); case 2: return v3s16(1,0,0); case 3: return v3s16(-1,0,0); case 4: return v3s16(0,0,1); case 5: return v3s16(0,0,-1); } } void MapNode::rotateAlongYAxis(INodeDefManager *nodemgr, Rotation rot) { ContentParamType2 cpt2 = nodemgr->get(*this).param_type_2; if (cpt2 == CPT2_FACEDIR) { static const u8 rotate_facedir[24 * 4] = { // Table value = rotated facedir // Columns: 0, 90, 180, 270 degrees rotation around vertical axis // Rotation is anticlockwise as seen from above (+Y) 0, 1, 2, 3, // Initial facedir 0 to 3 1, 2, 3, 0, 2, 3, 0, 1, 3, 0, 1, 2, 4, 13, 10, 19, // 4 to 7 5, 14, 11, 16, 6, 15, 8, 17, 7, 12, 9, 18, 8, 17, 6, 15, // 8 to 11 9, 18, 7, 12, 10, 19, 4, 13, 11, 16, 5, 14, 12, 9, 18, 7, // 12 to 15 13, 10, 19, 4, 14, 11, 16, 5, 15, 8, 17, 6, 16, 5, 14, 11, // 16 to 19 17, 6, 15, 8, 18, 7, 12, 9, 19, 4, 13, 10, 20, 23, 22, 21, // 20 to 23 21, 20, 23, 22, 22, 21, 20, 23, 23, 22, 21, 20 }; u8 facedir = (param2 & 31) % 24; u8 index = facedir * 4 + rot; param2 &= ~31; param2 |= rotate_facedir[index]; } else if (cpt2 == CPT2_WALLMOUNTED) { u8 wmountface = (param2 & 7); if (wmountface <= 1) return; Rotation oldrot = wallmounted_to_rot[wmountface - 2]; param2 &= ~7; param2 |= rot_to_wallmounted[(oldrot - rot) & 3]; } } void transformNodeBox(const MapNode &n, const NodeBox &nodebox, INodeDefManager *nodemgr, std::vector<aabb3f> *p_boxes, u8 neighbors = 0) { std::vector<aabb3f> &boxes = *p_boxes; if (nodebox.type == NODEBOX_FIXED || nodebox.type == NODEBOX_LEVELED) { const std::vector<aabb3f> &fixed = nodebox.fixed; int facedir = n.getFaceDir(nodemgr); u8 axisdir = facedir>>2; facedir&=0x03; for(std::vector<aabb3f>::const_iterator i = fixed.begin(); i != fixed.end(); ++i) { aabb3f box = *i; if (nodebox.type == NODEBOX_LEVELED) { box.MaxEdge.Y = -BS/2 + BS*((float)1/LEVELED_MAX) * n.getLevel(nodemgr); } switch (axisdir) { case 0: if(facedir == 1) { box.MinEdge.rotateXZBy(-90); box.MaxEdge.rotateXZBy(-90); } else if(facedir == 2) { box.MinEdge.rotateXZBy(180); box.MaxEdge.rotateXZBy(180); } else if(facedir == 3) { box.MinEdge.rotateXZBy(90); box.MaxEdge.rotateXZBy(90); } break; case 1: // z+ box.MinEdge.rotateYZBy(90); box.MaxEdge.rotateYZBy(90); if(facedir == 1) { box.MinEdge.rotateXYBy(90); box.MaxEdge.rotateXYBy(90); } else if(facedir == 2) { box.MinEdge.rotateXYBy(180); box.MaxEdge.rotateXYBy(180); } else if(facedir == 3) { box.MinEdge.rotateXYBy(-90); box.MaxEdge.rotateXYBy(-90); } break; case 2: //z- box.MinEdge.rotateYZBy(-90); box.MaxEdge.rotateYZBy(-90); if(facedir == 1) { box.MinEdge.rotateXYBy(-90); box.MaxEdge.rotateXYBy(-90); } else if(facedir == 2) { box.MinEdge.rotateXYBy(180); box.MaxEdge.rotateXYBy(180); } else if(facedir == 3) { box.MinEdge.rotateXYBy(90); box.MaxEdge.rotateXYBy(90); } break; case 3: //x+ box.MinEdge.rotateXYBy(-90); box.MaxEdge.rotateXYBy(-90); if(facedir == 1) { box.MinEdge.rotateYZBy(90); box.MaxEdge.rotateYZBy(90); } else if(facedir == 2) { box.MinEdge.rotateYZBy(180); box.MaxEdge.rotateYZBy(180); } else if(facedir == 3) { box.MinEdge.rotateYZBy(-90); box.MaxEdge.rotateYZBy(-90); } break; case 4: //x- box.MinEdge.rotateXYBy(90); box.MaxEdge.rotateXYBy(90); if(facedir == 1) { box.MinEdge.rotateYZBy(-90); box.MaxEdge.rotateYZBy(-90); } else if(facedir == 2) { box.MinEdge.rotateYZBy(180); box.MaxEdge.rotateYZBy(180); } else if(facedir == 3) { box.MinEdge.rotateYZBy(90); box.MaxEdge.rotateYZBy(90); } break; case 5: box.MinEdge.rotateXYBy(-180); box.MaxEdge.rotateXYBy(-180); if(facedir == 1) { box.MinEdge.rotateXZBy(90); box.MaxEdge.rotateXZBy(90); } else if(facedir == 2) { box.MinEdge.rotateXZBy(180); box.MaxEdge.rotateXZBy(180); } else if(facedir == 3) { box.MinEdge.rotateXZBy(-90); box.MaxEdge.rotateXZBy(-90); } break; default: break; } box.repair(); boxes.push_back(box); } } else if(nodebox.type == NODEBOX_WALLMOUNTED) { v3s16 dir = n.getWallMountedDir(nodemgr); // top if(dir == v3s16(0,1,0)) { boxes.push_back(nodebox.wall_top); } // bottom else if(dir == v3s16(0,-1,0)) { boxes.push_back(nodebox.wall_bottom); } // side else { v3f vertices[2] = { nodebox.wall_side.MinEdge, nodebox.wall_side.MaxEdge }; for(s32 i=0; i<2; i++) { if(dir == v3s16(-1,0,0)) vertices[i].rotateXZBy(0); if(dir == v3s16(1,0,0)) vertices[i].rotateXZBy(180); if(dir == v3s16(0,0,-1)) vertices[i].rotateXZBy(90); if(dir == v3s16(0,0,1)) vertices[i].rotateXZBy(-90); } aabb3f box = aabb3f(vertices[0]); box.addInternalPoint(vertices[1]); boxes.push_back(box); } } else if (nodebox.type == NODEBOX_CONNECTED) { size_t boxes_size = boxes.size(); boxes_size += nodebox.fixed.size(); if (neighbors & 1) boxes_size += nodebox.connect_top.size(); if (neighbors & 2) boxes_size += nodebox.connect_bottom.size(); if (neighbors & 4) boxes_size += nodebox.connect_front.size(); if (neighbors & 8) boxes_size += nodebox.connect_left.size(); if (neighbors & 16) boxes_size += nodebox.connect_back.size(); if (neighbors & 32) boxes_size += nodebox.connect_right.size(); boxes.reserve(boxes_size); #define BOXESPUSHBACK(c) do { \ for (std::vector<aabb3f>::const_iterator \ it = (c).begin(); \ it != (c).end(); ++it) \ (boxes).push_back(*it); \ } while (0) BOXESPUSHBACK(nodebox.fixed); if (neighbors & 1) BOXESPUSHBACK(nodebox.connect_top); if (neighbors & 2) BOXESPUSHBACK(nodebox.connect_bottom); if (neighbors & 4) BOXESPUSHBACK(nodebox.connect_front); if (neighbors & 8) BOXESPUSHBACK(nodebox.connect_left); if (neighbors & 16) BOXESPUSHBACK(nodebox.connect_back); if (neighbors & 32) BOXESPUSHBACK(nodebox.connect_right); } else // NODEBOX_REGULAR { boxes.push_back(aabb3f(-BS/2,-BS/2,-BS/2,BS/2,BS/2,BS/2)); } } void MapNode::getNodeBoxes(INodeDefManager *nodemgr, std::vector<aabb3f> *boxes, u8 neighbors) { const ContentFeatures &f = nodemgr->get(*this); transformNodeBox(*this, f.node_box, nodemgr, boxes, neighbors); } void MapNode::getCollisionBoxes(INodeDefManager *nodemgr, std::vector<aabb3f> *boxes, u8 neighbors) { const ContentFeatures &f = nodemgr->get(*this); if (f.collision_box.fixed.empty()) transformNodeBox(*this, f.node_box, nodemgr, boxes, neighbors); else transformNodeBox(*this, f.collision_box, nodemgr, boxes, neighbors); } void MapNode::getSelectionBoxes(INodeDefManager *nodemgr, std::vector<aabb3f> *boxes, u8 neighbors) { const ContentFeatures &f = nodemgr->get(*this); transformNodeBox(*this, f.selection_box, nodemgr, boxes, neighbors); } u8 MapNode::getMaxLevel(INodeDefManager *nodemgr) const { const ContentFeatures &f = nodemgr->get(*this); // todo: after update in all games leave only if (f.param_type_2 == if( f.liquid_type == LIQUID_FLOWING || f.param_type_2 == CPT2_FLOWINGLIQUID) return LIQUID_LEVEL_MAX; if(f.leveled || f.param_type_2 == CPT2_LEVELED) return LEVELED_MAX; return 0; } u8 MapNode::getLevel(INodeDefManager *nodemgr) const { const ContentFeatures &f = nodemgr->get(*this); // todo: after update in all games leave only if (f.param_type_2 == if(f.liquid_type == LIQUID_SOURCE) return LIQUID_LEVEL_SOURCE; if (f.param_type_2 == CPT2_FLOWINGLIQUID) return getParam2() & LIQUID_LEVEL_MASK; if(f.liquid_type == LIQUID_FLOWING) // can remove if all param_type_2 setted return getParam2() & LIQUID_LEVEL_MASK; if(f.leveled || f.param_type_2 == CPT2_LEVELED) { u8 level = getParam2() & LEVELED_MASK; if(level) return level; if(f.leveled > LEVELED_MAX) return LEVELED_MAX; return f.leveled; //default } return 0; } u8 MapNode::setLevel(INodeDefManager *nodemgr, s8 level) { u8 rest = 0; if (level < 1) { setContent(CONTENT_AIR); return 0; } const ContentFeatures &f = nodemgr->get(*this); if (f.param_type_2 == CPT2_FLOWINGLIQUID || f.liquid_type == LIQUID_FLOWING || f.liquid_type == LIQUID_SOURCE) { if (level >= LIQUID_LEVEL_SOURCE) { rest = level - LIQUID_LEVEL_SOURCE; setContent(nodemgr->getId(f.liquid_alternative_source)); } else { setContent(nodemgr->getId(f.liquid_alternative_flowing)); setParam2(level & LIQUID_LEVEL_MASK); } } else if (f.leveled || f.param_type_2 == CPT2_LEVELED) { if (level > LEVELED_MAX) { rest = level - LEVELED_MAX; level = LEVELED_MAX; } setParam2(level & LEVELED_MASK); } return rest; } u8 MapNode::addLevel(INodeDefManager *nodemgr, s8 add) { s8 level = getLevel(nodemgr); if (add == 0) level = 1; level += add; return setLevel(nodemgr, level); } u32 MapNode::serializedLength(u8 version) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapNode format not supported"); if(version == 0) return 1; else if(version <= 9) return 2; else if(version <= 23) return 3; else return 4; } void MapNode::serialize(u8 *dest, u8 version) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapNode format not supported"); // Can't do this anymore; we have 16-bit dynamically allocated node IDs // in memory; conversion just won't work in this direction. if(version < 24) throw SerializationError("MapNode::serialize: serialization to " "version < 24 not possible"); writeU16(dest+0, param0); writeU8(dest+2, param1); writeU8(dest+3, param2); } void MapNode::deSerialize(u8 *source, u8 version) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapNode format not supported"); if(version <= 21) { deSerialize_pre22(source, version); return; } if(version >= 24){ param0 = readU16(source+0); param1 = readU8(source+2); param2 = readU8(source+3); }else{ param0 = readU8(source+0); param1 = readU8(source+1); param2 = readU8(source+2); if(param0 > 0x7F){ param0 |= ((param2&0xF0)<<4); param2 &= 0x0F; } } } void MapNode::serializeBulk(std::ostream &os, int version, const MapNode *nodes, u32 nodecount, u8 content_width, u8 params_width, bool compressed) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapNode format not supported"); sanity_check(content_width == 2); sanity_check(params_width == 2); // Can't do this anymore; we have 16-bit dynamically allocated node IDs // in memory; conversion just won't work in this direction. if(version < 24) throw SerializationError("MapNode::serializeBulk: serialization to " "version < 24 not possible"); SharedBuffer<u8> databuf(nodecount * (content_width + params_width)); // Serialize content for(u32 i=0; i<nodecount; i++) writeU16(&databuf[i*2], nodes[i].param0); // Serialize param1 u32 start1 = content_width * nodecount; for(u32 i=0; i<nodecount; i++) writeU8(&databuf[start1 + i], nodes[i].param1); // Serialize param2 u32 start2 = (content_width + 1) * nodecount; for(u32 i=0; i<nodecount; i++) writeU8(&databuf[start2 + i], nodes[i].param2); /* Compress data to output stream */ if(compressed) { compressZlib(databuf, os); } else { os.write((const char*) &databuf[0], databuf.getSize()); } } // Deserialize bulk node data void MapNode::deSerializeBulk(std::istream &is, int version, MapNode *nodes, u32 nodecount, u8 content_width, u8 params_width, bool compressed) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapNode format not supported"); if (version < 22 || (content_width != 1 && content_width != 2) || params_width != 2) FATAL_ERROR("Deserialize bulk node data error"); // Uncompress or read data u32 len = nodecount * (content_width + params_width); SharedBuffer<u8> databuf(len); if(compressed) { std::ostringstream os(std::ios_base::binary); decompressZlib(is, os); std::string s = os.str(); if(s.size() != len) throw SerializationError("deSerializeBulkNodes: " "decompress resulted in invalid size"); memcpy(&databuf[0], s.c_str(), len); } else { is.read((char*) &databuf[0], len); if(is.eof() || is.fail()) throw SerializationError("deSerializeBulkNodes: " "failed to read bulk node data"); } // Deserialize content if(content_width == 1) { for(u32 i=0; i<nodecount; i++) nodes[i].param0 = readU8(&databuf[i]); } else if(content_width == 2) { for(u32 i=0; i<nodecount; i++) nodes[i].param0 = readU16(&databuf[i*2]); } // Deserialize param1 u32 start1 = content_width * nodecount; for(u32 i=0; i<nodecount; i++) nodes[i].param1 = readU8(&databuf[start1 + i]); // Deserialize param2 u32 start2 = (content_width + 1) * nodecount; if(content_width == 1) { for(u32 i=0; i<nodecount; i++) { nodes[i].param2 = readU8(&databuf[start2 + i]); if(nodes[i].param0 > 0x7F){ nodes[i].param0 <<= 4; nodes[i].param0 |= (nodes[i].param2&0xF0)>>4; nodes[i].param2 &= 0x0F; } } } else if(content_width == 2) { for(u32 i=0; i<nodecount; i++) nodes[i].param2 = readU8(&databuf[start2 + i]); } } /* Legacy serialization */ void MapNode::deSerialize_pre22(u8 *source, u8 version) { if(version <= 1) { param0 = source[0]; } else if(version <= 9) { param0 = source[0]; param1 = source[1]; } else { param0 = source[0]; param1 = source[1]; param2 = source[2]; if(param0 > 0x7f){ param0 <<= 4; param0 |= (param2&0xf0)>>4; param2 &= 0x0f; } } // Convert special values from old version to new if(version <= 19) { // In these versions, CONTENT_IGNORE and CONTENT_AIR // are 255 and 254 // Version 19 is fucked up with sometimes the old values and sometimes not if(param0 == 255) param0 = CONTENT_IGNORE; else if(param0 == 254) param0 = CONTENT_AIR; } // Translate to our known version *this = mapnode_translate_to_internal(*this, version); }