aboutsummaryrefslogtreecommitdiff
path: root/src/script/cpp_api/s_node.cpp
Commit message (Collapse)AuthorAge
* Merge pull request #8776 from osjc/FixGetNodeJozef Behran2019-08-10
| | | Finish getNode cleanup
* Modernize lua read (part 2 & 3): C++ templating assurance (#7410)Loïc Blot2018-06-30
| | | | | | | | | * Modernize lua read (part 2 & 3): C++ templating assurance Implement the boolean reader Implement the string reader Also remove unused & unimplemented script_error_handler Add a reader with default value
* Node definition manager refactor (#7016)Dániel Juhász2018-02-10
| | | | | | | | | * Rename IWritableNodeDefManager to NodeDefManager * Make INodeDefManager functions const * Use "const *NodeDefManager" instead of "*INodeDefManager" * Remove unused INodeDefManager class * Merge NodeDefManager and CNodeDefManager * Document NodeDefManager
* Unkown nodes: Provide position on interact (#6505)SmallJoker2017-10-07
| | | | * Unkown nodes: Provide position on interact
* Remove nodeupdate completely (#6358)Rui2017-09-01
|
* Modernize source code: last part (#6285)Loïc Blot2017-08-20
| | | | | | | | | | | * Modernize source code: last par * Use empty when needed * Use emplace_back instead of push_back when needed * For range-based loops * Initializers fixes * constructors, destructors default * c++ C stl includes
* Add 'plantlike_rooted' drawtypenumber Zero2017-07-11
| | | | | | | Useful for underwater plants. Node consists of a base cube plus a plantlike extension that can pass through liquid nodes above without creating air bubbles or interfering with liquid flow. Uses paramtype2 'leveled', param2 defines height of plantlike extension.
* Order es_DrawType exactly like enum NodeDrawType in nodedef.h (#5946)Thomas--S2017-06-10
| | | This will help to avoid some strange bugs.
* Fix various points reported by cppcheck (#5656)Loïc Blot2017-04-25
| | | | | | | | | | | | * Fix various performance issues reported by cppcheck + code style (CI) * Make CI happy with code style on master * guiFileSelectMenu: remove useless includes * some performance fixes pointed by cppcheck * remove some useless casts * TextDest: remove unused setFormSpec function * Fix various iterator post-increment reported by cppcheck
* Add on_flood() callback.Auke Kok2017-04-22
| | | | | | | | | | | | | | | | | | | | | This callback is called if a liquid definitely floods a non-air node on the map. The callback arguments are (pos, oldnode, newnode) and can return a `bool` value indicating whether flooding the node should be cancelled (`return true` will prevent the node from flooding). Documentation is added, the callback function was tested with a modified minetest_game. Note that `return true` will likely cause the node's `on_flood()` callback to be called every second until the node gets removed, so care must be taken to prevent many callbacks from using this return value. The current default liquid update interval is 1.0 seconds, which isn't unmanageable. The larger aim of this patch is to remove the lava cooling ABM, which is a significant cost to idle servers that have lava on their map. This callback will be much more efficient.
* Paramtype2: Add missing type CPT2_GLASSLIKE_LIQUID_LEVELparamat2017-03-30
| | | | | | | Add the missing paramtype2 for param2 controlling the liquid level inside the glasslike_framed drawtype. Add missing documentation of the feature to lua_api.txt. Update and improve comments for drawtype enumerations in nodedef.h.
* Add hardware node coloring. Includes:Dániel Juhász2017-01-23
| | | | | | - Increase ContentFeatures serialization version - Color property and palettes for nodes - paramtype2 = "color", "colored facedir" or "colored wallmounted"
* Make plantlike drawtype more funAuke Kok2016-08-26
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Adds several new ways that the plantlike drawtype mesh can be changed. This requires paramtype2 = "meshoptions" to be set in the node definition. The drawtype for these nodes should be "plantlike". These modifications are all done using param2. This field is now a complex bitfield that allows some or more of the combinations to be chosen, and the mesh draw code will choose the options based as neeeded for each plantlike node. bit layout: bits 0, 1 and 2 (values 0x1 through 0x7) are for choosing the plant mesh shape: 0 - ordinary plantlike plant ("x" shaped) 1 - ordinary plant, but rotated 45 degrees ("+" shaped) 2 - a plant with 3 faces ("*" shaped) 3 - a plant with 4 faces ("#" shaped) 4 - a plant with 4 faces ("#" shaped, leaning outwards) 5 through 7 are unused and reserved for future mesh shapes. bit 3 (0x8) causes the plant to be randomly offset in the x,z plane. The plant should fall within the 1x1x1 nodebox if regularly sized. bit 4 (0x10) causes the plant mesh to grow by sqrt(2), and will cause the plant mesh to fill out 1x1x1, and appear slightly larger. Texture makers will want to make their plant texture 23x16 pixels to have the best visual fit in 1x1x1 size. bit 5 (0x20) causes each face of the plant to have a slight negative Y offset in position, descending up to 0.125 downwards into the node below. Because this is per face, this causes the plant model to be less symmetric. bit 6 (0x40) through bit 7 (0x80) are unused and reserved for future use. !(https://youtu.be/qWuI664krsI)
* Nodebox: Allow nodeboxes to "connect"Auke Kok2016-03-12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We introduce a new nodebox type "connected", and allow these nodes to have optional nodeboxes that connect it to other connecting nodeboxes. This is all done at scenedraw time in the client. The client will inspect the surrounding nodes and if they are to be connected to, it will draw the appropriate connecting nodeboxes to make those connections. In the node_box definition, we have to specify separate nodeboxes for each valid connection. This allows us to make nodes that connect only horizontally (the common case) by providing optional nodeboxes for +x, -x, +z, -z directions. Or this allows us to make wires that can connect up and down, by providing nodeboxes that connect it up and down (+y, -y) as well. The optional nodeboxes can be arrays. They are named "connect_top, "connect_bottom", "connect_front", "connect_left", "connect_back" and "connect_right". Here, "front" means the south facing side of the node that has facedir = 0. Additionally, a "fixed" nodebox list present will always be drawn, so one can make a central post, for instance. This "fixed" nodebox can be omitted, or it can be an array of nodeboxes. Collision boxes are also updated in exactly the same fashion, which allows you to walk over the upper extremities of the individual node boxes, or stand really close to them. You can also walk up node noxes that are small in height, all as expected, and unlike the NDT_FENCELIKE nodes. I've posted a screenshot demonstrating the flexibility at http://i.imgur.com/zaJq8jo.png In the screenshot, all connecting nodes are of this new subtype. Transparent textures render incorrectly, Which I don't think is related to this text, as other nodeboxes also have issues with this. A protocol bump is performed in order to be able to send older clients a nodeblock that is usable for them. In order to avoid abuse of users we send older clients a "full-size" node, so that it's impossible for them to try and walk through a fence or wall that's created in this fashion. This was tested with a pre-bump client connected against a server running the new protocol. These nodes connect to other nodes, and you can select which ones those are by specifying node names (or group names) in the connects_to string array: connects_to = { "group:fence", "default:wood" } By default, nodes do not connect to anything, allowing you to create nodes that always have to be paired in order to connect. lua_api.txt is updated to reflect the extension to the node_box API. Example lua code needed to generate these nodes can be found here: https://gist.github.com/sofar/b381c8c192c8e53e6062
* Add new ContentParamType2 "CPT2_DEGROTATE"est312015-10-04
| | | | | | | | | This might break some mods, but it is important for all uses of the param2 to be documented. This doesn't need a serialisation version or network protocol version change, as old clients will still work on new servers, and it is bearable to have new clients getting non rotated plants on old servers.
* Push error handler afresh each time lua_pcall is usedKahrl2015-08-27
| | | | | Fixes "double fault" / "error in error handling" messages (issue #1423) and instead shows a complete backtrace.
* Improve Script CPP API diagnosticskwolekr2015-08-05
|
* Replace instances of std::map<std::string, std::string> with StringMapkwolekr2015-05-19
| | | | | | Also, clean up surrounding code style Replace by-value parameter passing with const refs when possible Fix post-increment of iterators
* Add meshnode drawtype.RealBadAngel2014-10-18
|
* Fix object reference pushing functions when called from coroutinesShadowNinja2014-10-07
|
* Add optional framed glasslike drawtypeBlockMen2014-10-02
|
* Add firelike drawtypeTriBlade92014-09-21
|
* Only push the Lua error handler onceShadowNinja2014-04-27
|
* Pass pointed_thing to on_punch and minetest.register_on_punchnode callbacksShadowNinja2014-01-23
|
* Pass a errfunc to lua_pcall to get a tracebackShadowNinja2013-11-15
|
* Omnicleanup: header cleanup, add ModApiUtil shared between game and mainmenuKahrl2013-08-14
|
* Weather supportproller2013-07-27
|
* Leveled nodeboxproller2013-07-13
|
* Move scriptapi to separate folder (by sapier)sapier2013-05-25
On the lua side, notably minetest.env:<function>(<args>) should now be replaced by minetest.<function>(<args>). The old way is and will stay supported for a long time. Also: Update and clean up lua_api.txt (by celeron55) Move EnvRef to lua and remove add_rat and add_firefly (by kahrl) Add separate src/util/CMakeLists.txt, other minor fixes (by kahrl)
>be64toh(val); } inline void writeU16(u8 *data, u16 i) { u16 val = htobe16(i); memcpy(data, &val, 2); } inline void writeU32(u8 *data, u32 i) { u32 val = htobe32(i); memcpy(data, &val, 4); } inline void writeU64(u8 *data, u64 i) { u64 val = htobe64(i); memcpy(data, &val, 8); } #else // generic byte-swapping implementation inline u16 readU16(const u8 *data) { return ((u16)data[0] << 8) | ((u16)data[1] << 0); } inline u32 readU32(const u8 *data) { return ((u32)data[0] << 24) | ((u32)data[1] << 16) | ((u32)data[2] << 8) | ((u32)data[3] << 0); } inline u64 readU64(const u8 *data) { return ((u64)data[0] << 56) | ((u64)data[1] << 48) | ((u64)data[2] << 40) | ((u64)data[3] << 32) | ((u64)data[4] << 24) | ((u64)data[5] << 16) | ((u64)data[6] << 8) | ((u64)data[7] << 0); } inline void writeU16(u8 *data, u16 i) { data[0] = (i >> 8) & 0xFF; data[1] = (i >> 0) & 0xFF; } inline void writeU32(u8 *data, u32 i) { data[0] = (i >> 24) & 0xFF; data[1] = (i >> 16) & 0xFF; data[2] = (i >> 8) & 0xFF; data[3] = (i >> 0) & 0xFF; } inline void writeU64(u8 *data, u64 i) { data[0] = (i >> 56) & 0xFF; data[1] = (i >> 48) & 0xFF; data[2] = (i >> 40) & 0xFF; data[3] = (i >> 32) & 0xFF; data[4] = (i >> 24) & 0xFF; data[5] = (i >> 16) & 0xFF; data[6] = (i >> 8) & 0xFF; data[7] = (i >> 0) & 0xFF; } #endif // HAVE_ENDIAN_H //////////////// read routines //////////////// inline u8 readU8(const u8 *data) { return ((u8)data[0] << 0); } inline s8 readS8(const u8 *data) { return (s8)readU8(data); } inline s16 readS16(const u8 *data) { return (s16)readU16(data); } inline s32 readS32(const u8 *data) { return (s32)readU32(data); } inline s64 readS64(const u8 *data) { return (s64)readU64(data); } inline f32 readF1000(const u8 *data) { return (f32)readS32(data) / FIXEDPOINT_FACTOR; } inline video::SColor readARGB8(const u8 *data) { video::SColor p(readU32(data)); return p; } inline v2s16 readV2S16(const u8 *data) { v2s16 p; p.X = readS16(&data[0]); p.Y = readS16(&data[2]); return p; } inline v3s16 readV3S16(const u8 *data) { v3s16 p; p.X = readS16(&data[0]); p.Y = readS16(&data[2]); p.Z = readS16(&data[4]); return p; } inline v2s32 readV2S32(const u8 *data) { v2s32 p; p.X = readS32(&data[0]); p.Y = readS32(&data[4]); return p; } inline v3s32 readV3S32(const u8 *data) { v3s32 p; p.X = readS32(&data[0]); p.Y = readS32(&data[4]); p.Z = readS32(&data[8]); return p; } inline v2f readV2F1000(const u8 *data) { v2f p; p.X = (float)readF1000(&data[0]); p.Y = (float)readF1000(&data[4]); return p; } inline v3f readV3F1000(const u8 *data) { v3f p; p.X = (float)readF1000(&data[0]); p.Y = (float)readF1000(&data[4]); p.Z = (float)readF1000(&data[8]); return p; } /////////////// write routines //////////////// inline void writeU8(u8 *data, u8 i) { data[0] = (i >> 0) & 0xFF; } inline void writeS8(u8 *data, s8 i) { writeU8(data, (u8)i); } inline void writeS16(u8 *data, s16 i) { writeU16(data, (u16)i); } inline void writeS32(u8 *data, s32 i) { writeU32(data, (u32)i); } inline void writeS64(u8 *data, s64 i) { writeU64(data, (u64)i); } inline void writeF1000(u8 *data, f32 i) { assert(i >= F1000_MIN && i <= F1000_MAX); writeS32(data, i * FIXEDPOINT_FACTOR); } inline void writeARGB8(u8 *data, video::SColor p) { writeU32(data, p.color); } inline void writeV2S16(u8 *data, v2s16 p) { writeS16(&data[0], p.X); writeS16(&data[2], p.Y); } inline void writeV3S16(u8 *data, v3s16 p) { writeS16(&data[0], p.X); writeS16(&data[2], p.Y); writeS16(&data[4], p.Z); } inline void writeV2S32(u8 *data, v2s32 p) { writeS32(&data[0], p.X); writeS32(&data[4], p.Y); } inline void writeV3S32(u8 *data, v3s32 p) { writeS32(&data[0], p.X); writeS32(&data[4], p.Y); writeS32(&data[8], p.Z); } inline void writeV2F1000(u8 *data, v2f p) { writeF1000(&data[0], p.X); writeF1000(&data[4], p.Y); } inline void writeV3F1000(u8 *data, v3f p) { writeF1000(&data[0], p.X); writeF1000(&data[4], p.Y); writeF1000(&data[8], p.Z); } //// //// Iostream wrapper for data read/write //// #define MAKE_STREAM_READ_FXN(T, N, S) \ inline T read ## N(std::istream &is) \ { \ char buf[S] = {0}; \ is.read(buf, sizeof(buf)); \ return read ## N((u8 *)buf); \ } #define MAKE_STREAM_WRITE_FXN(T, N, S) \ inline void write ## N(std::ostream &os, T val) \ { \ char buf[S]; \ write ## N((u8 *)buf, val); \ os.write(buf, sizeof(buf)); \ } MAKE_STREAM_READ_FXN(u8, U8, 1); MAKE_STREAM_READ_FXN(u16, U16, 2); MAKE_STREAM_READ_FXN(u32, U32, 4); MAKE_STREAM_READ_FXN(u64, U64, 8); MAKE_STREAM_READ_FXN(s8, S8, 1); MAKE_STREAM_READ_FXN(s16, S16, 2); MAKE_STREAM_READ_FXN(s32, S32, 4); MAKE_STREAM_READ_FXN(s64, S64, 8); MAKE_STREAM_READ_FXN(f32, F1000, 4); MAKE_STREAM_READ_FXN(v2s16, V2S16, 4); MAKE_STREAM_READ_FXN(v3s16, V3S16, 6); MAKE_STREAM_READ_FXN(v2s32, V2S32, 8); MAKE_STREAM_READ_FXN(v3s32, V3S32, 12); MAKE_STREAM_READ_FXN(v2f, V2F1000, 8); MAKE_STREAM_READ_FXN(v3f, V3F1000, 12); MAKE_STREAM_READ_FXN(video::SColor, ARGB8, 4); MAKE_STREAM_WRITE_FXN(u8, U8, 1); MAKE_STREAM_WRITE_FXN(u16, U16, 2); MAKE_STREAM_WRITE_FXN(u32, U32, 4); MAKE_STREAM_WRITE_FXN(u64, U64, 8); MAKE_STREAM_WRITE_FXN(s8, S8, 1); MAKE_STREAM_WRITE_FXN(s16, S16, 2); MAKE_STREAM_WRITE_FXN(s32, S32, 4); MAKE_STREAM_WRITE_FXN(s64, S64, 8); MAKE_STREAM_WRITE_FXN(f32, F1000, 4); MAKE_STREAM_WRITE_FXN(v2s16, V2S16, 4); MAKE_STREAM_WRITE_FXN(v3s16, V3S16, 6); MAKE_STREAM_WRITE_FXN(v2s32, V2S32, 8); MAKE_STREAM_WRITE_FXN(v3s32, V3S32, 12); MAKE_STREAM_WRITE_FXN(v2f, V2F1000, 8); MAKE_STREAM_WRITE_FXN(v3f, V3F1000, 12); MAKE_STREAM_WRITE_FXN(video::SColor, ARGB8, 4); //// //// More serialization stuff //// // Creates a string with the length as the first two bytes std::string serializeString(const std::string &plain); // Creates a string with the length as the first two bytes from wide string std::string serializeWideString(const std::wstring &plain); // Reads a string with the length as the first two bytes std::string deSerializeString(std::istream &is); // Reads a wide string with the length as the first two bytes std::wstring deSerializeWideString(std::istream &is); // Creates a string with the length as the first four bytes std::string serializeLongString(const std::string &plain); // Reads a string with the length as the first four bytes std::string deSerializeLongString(std::istream &is); // Creates a string encoded in JSON format (almost equivalent to a C string literal) std::string serializeJsonString(const std::string &plain); // Reads a string encoded in JSON format std::string deSerializeJsonString(std::istream &is); // Creates a string consisting of the hexadecimal representation of `data` std::string serializeHexString(const std::string &data, bool insert_spaces=false); // Creates a string containing comma delimited values of a struct whose layout is // described by the parameter format bool serializeStructToString(std::string *out, std::string format, void *value); // Reads a comma delimited string of values into a struct whose layout is // decribed by the parameter format bool deSerializeStringToStruct(std::string valstr, std::string format, void *out, size_t olen); //// //// BufReader //// extern SerializationError eof_ser_err; #define MAKE_BUFREADER_GETNOEX_FXN(T, N, S) \ inline bool get ## N ## NoEx(T *val) \ { \ if (pos + S > size) \ return false; \ *val = read ## N(data + pos); \ pos += S; \ return true; \ } #define MAKE_BUFREADER_GET_FXN(T, N) \ inline T get ## N() \ { \ T val; \ if (!get ## N ## NoEx(&val)) \ throw eof_ser_err; \ return val; \ } class BufReader { public: BufReader(const u8 *data_, size_t size_) : data(data_), size(size_), pos(0) { } MAKE_BUFREADER_GETNOEX_FXN(u8, U8, 1); MAKE_BUFREADER_GETNOEX_FXN(u16, U16, 2); MAKE_BUFREADER_GETNOEX_FXN(u32, U32, 4); MAKE_BUFREADER_GETNOEX_FXN(u64, U64, 8); MAKE_BUFREADER_GETNOEX_FXN(s8, S8, 1); MAKE_BUFREADER_GETNOEX_FXN(s16, S16, 2); MAKE_BUFREADER_GETNOEX_FXN(s32, S32, 4); MAKE_BUFREADER_GETNOEX_FXN(s64, S64, 8); MAKE_BUFREADER_GETNOEX_FXN(f32, F1000, 4); MAKE_BUFREADER_GETNOEX_FXN(v2s16, V2S16, 4); MAKE_BUFREADER_GETNOEX_FXN(v3s16, V3S16, 6); MAKE_BUFREADER_GETNOEX_FXN(v2s32, V2S32, 8); MAKE_BUFREADER_GETNOEX_FXN(v3s32, V3S32, 12); MAKE_BUFREADER_GETNOEX_FXN(v2f, V2F1000, 8); MAKE_BUFREADER_GETNOEX_FXN(v3f, V3F1000, 12); MAKE_BUFREADER_GETNOEX_FXN(video::SColor, ARGB8, 4); bool getStringNoEx(std::string *val); bool getWideStringNoEx(std::wstring *val); bool getLongStringNoEx(std::string *val); bool getRawDataNoEx(void *data, size_t len); MAKE_BUFREADER_GET_FXN(u8, U8); MAKE_BUFREADER_GET_FXN(u16, U16); MAKE_BUFREADER_GET_FXN(u32, U32); MAKE_BUFREADER_GET_FXN(u64, U64); MAKE_BUFREADER_GET_FXN(s8, S8); MAKE_BUFREADER_GET_FXN(s16, S16); MAKE_BUFREADER_GET_FXN(s32, S32); MAKE_BUFREADER_GET_FXN(s64, S64); MAKE_BUFREADER_GET_FXN(f32, F1000); MAKE_BUFREADER_GET_FXN(v2s16, V2S16); MAKE_BUFREADER_GET_FXN(v3s16, V3S16); MAKE_BUFREADER_GET_FXN(v2s32, V2S32); MAKE_BUFREADER_GET_FXN(v3s32, V3S32); MAKE_BUFREADER_GET_FXN(v2f, V2F1000); MAKE_BUFREADER_GET_FXN(v3f, V3F1000); MAKE_BUFREADER_GET_FXN(video::SColor, ARGB8); MAKE_BUFREADER_GET_FXN(std::string, String); MAKE_BUFREADER_GET_FXN(std::wstring, WideString); MAKE_BUFREADER_GET_FXN(std::string, LongString); inline void getRawData(void *val, size_t len) { if (!getRawDataNoEx(val, len)) throw eof_ser_err; } inline size_t remaining() { assert(pos <= size); return size - pos; } const u8 *data; size_t size; size_t pos; }; #undef MAKE_BUFREADER_GET_FXN #undef MAKE_BUFREADER_GETNOEX_FXN //// //// Vector-based write routines //// inline void putU8(std::vector<u8> *dest, u8 val) { dest->push_back((val >> 0) & 0xFF); } inline void putU16(std::vector<u8> *dest, u16 val) { dest->push_back((val >> 8) & 0xFF); dest->push_back((val >> 0) & 0xFF); } inline void putU32(std::vector<u8> *dest, u32 val) { dest->push_back((val >> 24) & 0xFF); dest->push_back((val >> 16) & 0xFF); dest->push_back((val >> 8) & 0xFF); dest->push_back((val >> 0) & 0xFF); } inline void putU64(std::vector<u8> *dest, u64 val) { dest->push_back((val >> 56) & 0xFF); dest->push_back((val >> 48) & 0xFF); dest->push_back((val >> 40) & 0xFF); dest->push_back((val >> 32) & 0xFF); dest->push_back((val >> 24) & 0xFF); dest->push_back((val >> 16) & 0xFF); dest->push_back((val >> 8) & 0xFF); dest->push_back((val >> 0) & 0xFF); } inline void putS8(std::vector<u8> *dest, s8 val) { putU8(dest, val); } inline void putS16(std::vector<u8> *dest, s16 val) { putU16(dest, val); } inline void putS32(std::vector<u8> *dest, s32 val) { putU32(dest, val); } inline void putS64(std::vector<u8> *dest, s64 val) { putU64(dest, val); } inline void putF1000(std::vector<u8> *dest, f32 val) { putS32(dest, val * FIXEDPOINT_FACTOR); } inline void putV2S16(std::vector<u8> *dest, v2s16 val) { putS16(dest, val.X); putS16(dest, val.Y); } inline void putV3S16(std::vector<u8> *dest, v3s16 val) { putS16(dest, val.X); putS16(dest, val.Y); putS16(dest, val.Z); } inline void putV2S32(std::vector<u8> *dest, v2s32 val) { putS32(dest, val.X); putS32(dest, val.Y); } inline void putV3S32(std::vector<u8> *dest, v3s32 val) { putS32(dest, val.X); putS32(dest, val.Y); putS32(dest, val.Z); } inline void putV2F1000(std::vector<u8> *dest, v2f val) { putF1000(dest, val.X); putF1000(dest, val.Y); } inline void putV3F1000(std::vector<u8> *dest, v3f val) { putF1000(dest, val.X); putF1000(dest, val.Y); putF1000(dest, val.Z); } inline void putARGB8(std::vector<u8> *dest, video::SColor val) { putU32(dest, val.color); } inline void putString(std::vector<u8> *dest, const std::string &val) { if (val.size() > STRING_MAX_LEN) throw SerializationError("String too long"); putU16(dest, val.size()); dest->insert(dest->end(), val.begin(), val.end()); } inline void putWideString(std::vector<u8> *dest, const std::wstring &val) { if (val.size() > WIDE_STRING_MAX_LEN) throw SerializationError("String too long"); putU16(dest, val.size()); for (size_t i = 0; i != val.size(); i++) putU16(dest, val[i]); } inline void putLongString(std::vector<u8> *dest, const std::string &val) { if (val.size() > LONG_STRING_MAX_LEN) throw SerializationError("String too long"); putU32(dest, val.size()); dest->insert(dest->end(), val.begin(), val.end()); } inline void putRawData(std::vector<u8> *dest, const void *src, size_t len) { dest->insert(dest->end(), (u8 *)src, (u8 *)src + len); } #endif