1 /*
2 nodedef.h
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4 */
5 
6 /*
7 This file is part of Freeminer.
8 
9 Freeminer is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Freeminer  is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Freeminer.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 
23 #ifndef NODEDEF_HEADER
24 #define NODEDEF_HEADER
25 
26 #include "irrlichttypes_bloated.h"
27 #include <string>
28 #include <iostream>
29 #include <map>
30 #include <list>
31 #include <bitset>
32 #include "mapnode.h"
33 #include "tile.h"
34 #ifndef SERVER
35 #include "shader.h"
36 #endif
37 #include "itemgroup.h"
38 #include "sound.h" // SimpleSoundSpec
39 #include "constants.h" // BS
40 #include "fmbitset.h"
41 #include <unordered_set>
42 
43 
44 class IItemDefManager;
45 class ITextureSource;
46 class IShaderSource;
47 class IGameDef;
48 
49 typedef std::list<std::pair<content_t, int> > GroupItems;
50 
51 enum ContentParamType
52 {
53 	CPT_NONE,
54 	CPT_LIGHT,
55 };
56 
57 enum ContentParamType2
58 {
59 	CPT2_NONE,
60 	// Need 8-bit param2
61 	CPT2_FULL,
62 	// Flowing liquid properties
63 	CPT2_FLOWINGLIQUID,
64 	// Direction for chests and furnaces and such
65 	CPT2_FACEDIR,
66 	// Direction for signs, torches and such
67 	CPT2_WALLMOUNTED,
68 	// Block level like FLOWINGLIQUID
69 	CPT2_LEVELED,
70 };
71 
72 enum LiquidType
73 {
74 	LIQUID_NONE,
75 	LIQUID_FLOWING,
76 	LIQUID_SOURCE,
77 };
78 
79 enum NodeBoxType
80 {
81 	NODEBOX_REGULAR, // Regular block; allows buildable_to
82 	NODEBOX_FIXED, // Static separately defined box(es)
83 	NODEBOX_WALLMOUNTED, // Box for wall mounted nodes; (top, bottom, side)
84 	NODEBOX_LEVELED, // Same as fixed, but with dynamic height from param2. for snow, ...
85 };
86 
87 struct NodeBox
88 {
89 	enum NodeBoxType type;
90 	// NODEBOX_REGULAR (no parameters)
91 	// NODEBOX_FIXED
92 	std::vector<aabb3f> fixed;
93 	// NODEBOX_WALLMOUNTED
94 	aabb3f wall_top;
95 	aabb3f wall_bottom;
96 	aabb3f wall_side; // being at the -X side
97 
NodeBoxNodeBox98 	NodeBox()
99 	{ reset(); }
100 
101 	void reset();
102 	void serialize(std::ostream &os, u16 protocol_version) const;
103 	void deSerialize(std::istream &is);
104 };
105 
106 struct MapNode;
107 class NodeMetadata;
108 
109 /*
110 	Stand-alone definition of a TileSpec (basically a server-side TileSpec)
111 */
112 enum TileAnimationType{
113 	TAT_NONE=0,
114 	TAT_VERTICAL_FRAMES=1,
115 };
116 struct TileDef
117 {
118 	std::string name;
119 	bool backface_culling; // Takes effect only in special cases
120 	struct{
121 		enum TileAnimationType type;
122 		int aspect_w; // width for aspect ratio
123 		int aspect_h; // height for aspect ratio
124 		float length; // seconds
125 	} animation;
126 
TileDefTileDef127 	TileDef()
128 	{
129 		name = "";
130 		backface_culling = true;
131 		animation.type = TAT_NONE;
132 		animation.aspect_w = 1;
133 		animation.aspect_h = 1;
134 		animation.length = 1.0;
135 	}
136 
137 	void serialize(std::ostream &os, u16 protocol_version) const;
138 	void deSerialize(std::istream &is);
139 };
140 
141 enum NodeDrawType
142 {
143 	NDT_NORMAL, // A basic solid block
144 	NDT_AIRLIKE, // Nothing is drawn
145 	NDT_LIQUID, // Do not draw face towards same kind of flowing/source liquid
146 	NDT_FLOWINGLIQUID, // A very special kind of thing
147 	NDT_GLASSLIKE, // Glass-like, don't draw faces towards other glass
148 	NDT_ALLFACES, // Leaves-like, draw all faces no matter what
149 	NDT_ALLFACES_OPTIONAL, // Fancy -> allfaces, fast -> normal
150 	NDT_TORCHLIKE,
151 	NDT_SIGNLIKE,
152 	NDT_PLANTLIKE,
153 	NDT_FENCELIKE,
154 	NDT_RAILLIKE,
155 	NDT_NODEBOX,
156 	NDT_GLASSLIKE_FRAMED, // Glass-like, draw connected frames and all all
157 	                      // visible faces
158 						  // uses 2 textures, one for frames, second for faces
159 	NDT_FIRELIKE, // Draw faces slightly rotated and only on connecting nodes,
160 	NDT_GLASSLIKE_FRAMED_OPTIONAL,	// enabled -> connected, disabled -> Glass-like
161 									// uses 2 textures, one for frames, second for faces
162 	NDT_MESH, // Uses static meshes
163 };
164 
165 #define CF_SPECIAL_COUNT 6
166 
167 struct ContentFeatures
168 {
169 	/*
170 		Cached stuff
171 	*/
172 #ifndef SERVER
173 	// 0     1     2     3     4     5
174 	// up    down  right left  back  front
175 	TileSpec tiles[6];
176 	// Special tiles
177 	// - Currently used for flowing liquids
178 	TileSpec special_tiles[CF_SPECIAL_COUNT];
179 #endif
180 	u8 solidness; // Used when choosing which face is drawn
181 	u8 visual_solidness; // When solidness=0, this tells how it looks like
182 	bool backface_culling;
183 	video::SColor color_avg; //far mesh average color
184 
185 //#endif
186 
187 	// Server-side cached callback existence for fast skipping
188 	bool has_on_construct;
189 	bool has_on_destruct;
190 	bool has_after_destruct;
191 	bool has_on_activate;
192 	bool has_on_deactivate;
193 
194 	/*
195 		Actual data
196 	*/
197 
198 	std::string name; // "" = undefined node
199 	ItemGroupList groups; // Same as in itemdef
200 
201 	// Visual definition
202 	enum NodeDrawType drawtype;
203 	std::string mesh;
204 #ifndef SERVER
205 	scene::IMesh *mesh_ptr[24];
206 #endif
207 	float visual_scale; // Misc. scale parameter
208 	TileDef tiledef[6];
209 	TileDef tiledef_special[CF_SPECIAL_COUNT]; // eg. flowing liquid
210 	u8 alpha;
211 
212 	// Post effect color, drawn when the camera is inside the node.
213 	video::SColor post_effect_color;
214 	// Type of MapNode::param1
215 	ContentParamType param_type;
216 	// Type of MapNode::param2
217 	ContentParamType2 param_type_2;
218 	// True for all ground-like things like stone and mud, false for eg. trees
219 	bool is_ground_content;
220 	bool light_propagates;
221 	bool sunlight_propagates;
222 	// This is used for collision detection.
223 	// Also for general solidness queries.
224 	bool walkable;
225 	// Player can point to these
226 	bool pointable;
227 	// Player can dig these
228 	bool diggable;
229 	// Player can climb these
230 	bool climbable;
231 	// Player can build on these
232 	bool buildable_to;
233 	// Player cannot build to these (placement prediction disabled)
234 	bool rightclickable;
235 	// Flowing liquid or snow, value = default level
236 	u8 leveled;
237 	// Whether the node is non-liquid, source liquid or flowing liquid
238 	enum LiquidType liquid_type;
239 	// If the content is liquid, this is the flowing version of the liquid.
240 	std::string liquid_alternative_flowing;
241 	// If the content is liquid, this is the source version of the liquid.
242 	std::string liquid_alternative_source;
243 	// Viscosity for fluid flow, ranging from 1 to 7, with
244 	// 1 giving almost instantaneous propagation and 7 being
245 	// the slowest possible
246 	u8 liquid_viscosity;
247 	// Is liquid renewable (new liquid source will be created between 2 existing)
248 	bool liquid_renewable;
249 	// Ice for water, water for ice
250 	std::string freeze;
251 	std::string melt;
252 	// Number of flowing liquids surrounding source
253 	u8 drowning;
254 	// Amount of light the node emits
255 	u8 light_source;
256 	u32 damage_per_second;
257 	NodeBox node_box;
258 	NodeBox selection_box;
259 	NodeBox collision_box;
260 	// Used for waving leaves/plants
261 	u8 waving;
262 	// Compatibility with old maps
263 	// Set to true if paramtype used to be 'facedir_simple'
264 	bool legacy_facedir_simple;
265 	// Set to true if wall_mounted used to be set to true
266 	bool legacy_wallmounted;
267 
268 	bool is_wire;
269 	bool is_wire_connector;
270 	bool is_circuit_element;
271 	u8 wire_connections[6];
272 	u8 circuit_element_func[64];
273 	u8 circuit_element_delay;
274 
275 	// Sound properties
276 	SimpleSoundSpec sound_footstep;
277 	SimpleSoundSpec sound_dig;
278 	SimpleSoundSpec sound_dug;
279 
280 	/*
281 		Methods
282 	*/
283 
284 	ContentFeatures();
285 	~ContentFeatures();
286 	void reset();
287 	void serialize(std::ostream &os, u16 protocol_version);
288 	void deSerialize(std::istream &is);
289 	void serializeOld(std::ostream &os, u16 protocol_version);
290 	void deSerializeOld(std::istream &is, int version);
291 
292 	/*
293 		Some handy methods
294 	*/
isLiquidContentFeatures295 	bool isLiquid() const{
296 		return (liquid_type != LIQUID_NONE);
297 	}
sameLiquidContentFeatures298 	bool sameLiquid(const ContentFeatures &f) const{
299 		if(!isLiquid() || !f.isLiquid()) return false;
300 		return (liquid_alternative_flowing == f.liquid_alternative_flowing);
301 	}
302 	u8 getMaxLevel(bool compress = 0) const{
303 		if(param_type_2 == CPT2_LEVELED && liquid_type == LIQUID_FLOWING && leveled)
304 			return(compress ? LEVELED_MAX : leveled);
305 		if(leveled || param_type_2 == CPT2_LEVELED)
306 			return LEVELED_MAX;
307 		if(param_type_2 == CPT2_FLOWINGLIQUID || liquid_type == LIQUID_FLOWING) //remove liquid_type
308 			return LIQUID_LEVEL_SOURCE;
309 		return 0;
310 	}
311 
312 };
313 
314 struct NodeResolveInfo {
315 	std::string n_wanted;
316 	std::string n_alt;
317 	content_t c_fallback;
318 	content_t *output;
319 };
320 
321 #define NR_STATUS_FAILURE 0
322 #define NR_STATUS_PENDING 1
323 #define NR_STATUS_SUCCESS 2
324 
325 /**
326 	NodeResolver
327 
328 	NodeResolver attempts to resolve node names to content ID integers. If the
329 	node registration phase has not yet finished at the time the resolution
330 	request is placed, the request is marked as pending and added to an internal
331 	queue.  The name resolution request is later satisfied by writing directly
332 	to the output location when the node registration phase has been completed.
333 
334 	This is primarily intended to be used for objects registered during script
335 	initialization (i.e. while nodes are being registered) that reference
336 	particular nodes.
337 */
338 class NodeResolver {
339 public:
340 	NodeResolver(INodeDefManager *ndef);
341 	~NodeResolver();
342 
343 	/**
344 		Add a request to resolve the node n_wanted and set *content to the
345 		result, or alternatively, n_alt if n_wanted is not found.  If n_alt
346 		cannot be found either, or has not been specified, *content is set
347 		to c_fallback.
348 
349 		If node registration is complete, the request is finished immediately
350 		and NR_STATUS_SUCCESS is returned (or NR_STATUS_FAILURE if no node can
351 		be found).  Otherwise, NR_STATUS_PENDING is returned and the resolution
352 		request is queued.
353 
354 		N.B.  If the memory in which content is located has been deallocated
355 		before the pending request had been satisfied, cancelNode() must be
356 		called.
357 
358 		@param n_wanted Name of node that is wanted.
359 		@param n_alt Name of node in case n_wanted could not be found.  Blank
360 			if no alternative node is desired.
361 		@param c_fallback Content ID that content is set to in case of node
362 			resolution failure (should be CONTENT_AIR, CONTENT_IGNORE, etc.)
363 		@param content Pointer to content_t that receives the result of the
364 			node name resolution.
365 		@return Status of node resolution request.
366 	*/
367 	int addNode(std::string n_wanted, std::string n_alt,
368 		content_t c_fallback, content_t *content);
369 
370 	/**
371 		Add a request to resolve the node(s) specified by nodename.
372 
373 		If node registration is complete, the request is finished immediately
374 		and NR_STATUS_SUCCESS is returned if at least one node is resolved; if
375 		zero were resolved, NR_STATUS_FAILURE.  Otherwise, NR_STATUS_PENDING is
376 		returned and the resolution request is queued.
377 
378 		N.B.  If the memory in which content_vec is located has been deallocated
379 		before the pending request had been satisfied, cancelNodeList() must be
380 		called.
381 
382 		@param nodename Name of node (or node group) to be resolved.
383 		@param content_vec Pointer to content_t vector onto which the results
384 			are added.
385 
386 		@return Status of node resolution request.
387 	*/
388 	int addNodeList(const char *nodename, std::vector<content_t> *content_vec);
389 
390 	/**
391 		Removes all pending requests from the resolution queue to be satisfied
392 		to content.
393 
394 		@param content Location of the content ID for the request being
395 			cancelled.
396 		@return Number of pending requests cancelled.
397 	*/
398 	bool cancelNode(content_t *content);
399 
400 	/**
401 		Removes all pending requests from the resolution queue to be satisfied
402 		to content_vec.
403 
404 		@param content_vec Location of the content ID vector for requests being
405 			cancelled.
406 		@return Number of pending requests cancelled.
407 	*/
408 	int cancelNodeList(std::vector<content_t> *content_vec);
409 
410 	/**
411 		Carries out all pending node resolution requests.  Call this when the
412 		node registration phase has completed.
413 
414 		Internally marks node registration as complete.
415 
416 		@return Number of failed pending requests.
417 	*/
418 	int resolveNodes();
419 
420 	/**
421 		Returns the status of the node registration phase.
422 
423 		@return Boolean of whether the registration phase is complete.
424 	*/
isNodeRegFinished()425 	bool isNodeRegFinished() { return m_is_node_registration_complete; }
426 
427 private:
428 	INodeDefManager *m_ndef;
429 	bool m_is_node_registration_complete;
430 	std::list<NodeResolveInfo *> m_pending_contents;
431 	std::list<std::pair<std::string, std::vector<content_t> *> > m_pending_content_vecs;
432 };
433 
434 class INodeDefManager
435 {
436 public:
INodeDefManager()437 	INodeDefManager(){}
~INodeDefManager()438 	virtual ~INodeDefManager(){}
439 	// Get node definition
440 	virtual const ContentFeatures& get(content_t c) const=0;
441 	virtual const ContentFeatures& get(const MapNode &n) const=0;
442 	virtual bool getId(const std::string &name, content_t &result) const=0;
443 	virtual content_t getId(const std::string &name) const=0;
444 	// Allows "group:name" in addition to regular node names
445 	virtual void getIds(const std::string &name, std::unordered_set<content_t> &result)
446 			const=0;
447 	virtual void getIds(const std::string &name, FMBitset &result) const=0;
448 	virtual const ContentFeatures& get(const std::string &name) const=0;
449 
450 	virtual void serialize(std::ostream &os, u16 protocol_version)=0;
451 
452 	virtual NodeResolver *getResolver()=0;
453 };
454 
455 class IWritableNodeDefManager : public INodeDefManager
456 {
457 public:
IWritableNodeDefManager()458 	IWritableNodeDefManager(){}
~IWritableNodeDefManager()459 	virtual ~IWritableNodeDefManager(){}
460 	virtual IWritableNodeDefManager* clone()=0;
461 	// Get node definition
462 	virtual const ContentFeatures& get(content_t c) const=0;
463 	virtual const ContentFeatures& get(const MapNode &n) const=0;
464 	virtual bool getId(const std::string &name, content_t &result) const=0;
465 	// If not found, returns CONTENT_IGNORE
466 	virtual content_t getId(const std::string &name) const=0;
467 	// Allows "group:name" in addition to regular node names
468 	virtual void getIds(const std::string &name, std::unordered_set<content_t> &result)
469 			const=0;
470 	// If not found, returns the features of CONTENT_UNKNOWN
471 	virtual const ContentFeatures& get(const std::string &name) const=0;
472 
473 	// Register node definition by name (allocate an id)
474 	// If returns CONTENT_IGNORE, could not allocate id
475 	virtual content_t set(const std::string &name,
476 			const ContentFeatures &def)=0;
477 	// If returns CONTENT_IGNORE, could not allocate id
478 	virtual content_t allocateDummy(const std::string &name)=0;
479 
480 	/*
481 		Update item alias mapping.
482 		Call after updating item definitions.
483 	*/
484 	virtual void updateAliases(IItemDefManager *idef)=0;
485 
486 	/*
487 		Update tile textures to latest return values of TextueSource.
488 	*/
489 	virtual void updateTextures(IGameDef *gamedef)=0;
490 
491 	virtual void serialize(std::ostream &os, u16 protocol_version)=0;
492 	virtual void deSerialize(std::istream &is)=0;
493 
494 	virtual NodeResolver *getResolver()=0;
495 };
496 
497 IWritableNodeDefManager *createNodeDefManager();
498 
499 #endif
500 
501