1 /*
2  * Copyright (c) 2017-2018 sel-project
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  *
22  */
23 /**
24  * Copyright: 2017-2018 sel-project
25  * License: MIT
26  * Authors: Kripth
27  * Source: $(HTTP github.com/sel-project/selery/source/selery/entity/entity.d, selery/entity/entity.d)
28  */
29 module selery.entity.entity;
30 
31 import core.atomic : atomicOp;
32 
33 import std.algorithm : clamp;
34 import std.bitmanip : bigEndianToNative, nativeToBigEndian;
35 import std.conv : to;
36 import std.file : exists, read, write;
37 import std.math;
38 import std.random : uniform01;
39 import std.string : split, replace;
40 import std.traits : isArray, isAbstractClass;
41 import std.typecons : Tuple;
42 import std.uuid : UUID;
43 
44 import selery.about;
45 import selery.block.block : Block, blockInto;
46 import selery.command.command : Position;
47 import selery.entity.metadata : Metadata;
48 import selery.event.event : EventListener;
49 import selery.event.world.damage;
50 import selery.event.world.world : WorldEvent;
51 import selery.item.slot : Slot;
52 import selery.math.vector;
53 import selery.node.server : NodeServer;
54 import selery.player.player : Player;
55 import selery.util.util : safe, call;
56 import selery.world.world : World;
57 
58 static import sul.entities;
59 public import sul.entities : Entities;
60 
61 /**
62  * Base abstract class for every entity.
63  */
64 abstract class Entity : EventListener!WorldEvent {
65 
66 	private static uint count = -1;
67 
68 	public static @safe @nogc uint reserveLocalId() {
69 		return count += 2; // always an odd number (starting from 1)
70 	}
71 
72 	protected uint _id;
73 	protected UUID n_uuid;
74 
75 	protected World n_world;
76 
77 	private Entity[size_t] n_watchlist;
78 	private Entity[size_t] n_viewers; //edited by other entities
79 
80 	public bool ticking = true;
81 	private tick_t n_ticks = 0;
82 
83 	protected bool n_alive = true;
84 
85 	public EntityPosition oldposition;
86 	protected EntityPosition m_position;
87 	protected EntityPosition m_last;
88 	protected EntityPosition m_motion;
89 	protected float m_yaw = 0;
90 	protected float m_body_yaw = 0;
91 	protected float m_pitch = 0;
92 	public bool moved = false;
93 	public bool motionmoved = false;
94 
95 	private bool n_falling= false;
96 	protected bool n_on_ground;
97 	private float highestPoint;
98 	protected Entity last_puncher;
99 
100 	protected double n_eye_height;
101 
102 	private Entity m_vehicle;
103 	private Entity m_passenger;
104 
105 	protected EntityAxis n_box;
106 
107 	public Metadata metadata;
108 
109 	protected uint n_data;
110 
111 	protected float acceleration = 0;		// blocks/tick
112 	protected float drag = 0;				// percentage (0-1)
113 	protected float terminal_velocity = 0;	// blocks/tick
114 
115 	public this() {
116 		// unusable entity
117 		this._id = 0;
118 	}
119 
120 	public this(World world, EntityPosition position) {
121 		//assert(world !is null, "World can't be null");
122 		this._id = reserveLocalId();
123 		this.n_world = world;
124 		this.n_uuid = cast()this.server.nextUUID;
125 		this.m_position = this.m_last = this.oldposition = position;
126 		this.m_motion = EntityPosition(0, 0, 0);
127 		this.highestPoint = this.position.y;
128 		//TODO entity dimensions in space
129 		this.n_eye_height = 0;
130 		this.n_box = new EntityAxis(0, 0, this.position);
131 		this.metadata = new Metadata(); //TODO custom
132 	}
133 
134 	public final pure nothrow @property @safe @nogc uint id() {
135 		return this._id;
136 	}
137 
138 	public pure nothrow @property @safe @nogc sul.entities.Entity data() {
139 		return sul.entities.Entity.init;
140 	}
141 
142 	/**
143 	 * Gets the entity's type in a string format.
144 	 * Example:
145 	 * ---
146 	 * assert(creeper.type == "creeper");
147 	 * assert(witherSkull.type == "wither_skull");
148 	 * ---
149 	 */
150 	public pure nothrow @property @safe string type() {
151 		return this.data.name.replace(" ", "_");
152 	}
153 
154 	/**
155 	 * Indicates whether the entity exists in Minecraft.
156 	 */
157 	public pure nothrow @property @safe @nogc bool java() {
158 		return this.data.java.exists;
159 	}
160 
161 	public pure nothrow @property @safe @nogc ubyte javaId() {
162 		return this.data.java.id;
163 	}
164 
165 	/**
166 	 * Indicates whether the entity exists in Minecraft.
167 	 */
168 	public pure nothrow @property @safe @nogc bool bedrock() {
169 		return this.data.bedrock.exists;
170 	}
171 
172 	public pure nothrow @property @safe @nogc ubyte bedrockId() {
173 		return this.data.bedrock.id;
174 	}
175 
176 	/**
177 	 * Gets the item's width.
178 	 * Returns: a number higher than 0 or double.nan if the entity has no size
179 	 */
180 	public pure nothrow @property @safe @nogc double width() {
181 		return this.data.width;
182 	}
183 
184 	/**
185 	 * Gets the item's height.
186 	 * Returns: a number higher than 0 or double.nan if the entity has no size
187 	 */
188 	public pure nothrow @property @safe @nogc double height() {
189 		return this.data.height;
190 	}
191 
192 	/**
193 	 * Indicates whether the entity is an object. If not the entity is
194 	 * a mob (living entity).
195 	 */
196 	public pure nothrow @property @safe @nogc bool object() {
197 		return this.data.object;
198 	}
199 
200 	/**
201 	 * If the entity is an object gets the object's extra data used
202 	 * in Minecraft's SpawnObject packet.
203 	 */
204 	public final pure nothrow @property @safe @nogc int objectData() {
205 		return this.n_data;
206 	}
207 
208 	/**
209 	 * Gets the unique identifier (UUID).
210 	 * It's usually randomly generated when the entity is
211 	 * created and it can only be changed by the child classes.
212 	 */
213 	public final pure nothrow @property @safe @nogc UUID uuid() {
214 		return this.n_uuid;
215 	}
216 
217 	/**
218 	 * Gets the world the entity has been spawned into.
219 	 * Non-player entities should always have the same world for
220 	 * their whole life-cycle.
221 	 */
222 	public pure nothrow @property @safe @nogc World world() {
223 		return this.n_world;
224 	}
225 
226 	public pure nothrow @property @safe @nogc shared(NodeServer) server() {
227 		return this.world.server;
228 	}
229 
230 	// ticks the entity
231 	public void tick() {
232 		this.n_ticks++;
233 		if(this.vehicle !is null && this.vehicle.dead) this.vehicle = null;
234 		if(this.passenger !is null && this.passenger.dead) this.passenger = null;
235 		if(this.metadata.changed) {
236 			this.metadata.changed = false;
237 			this.broadcastMetadata();
238 		}
239 	}
240 	
241 	/**
242 	 * Gets the amount of ticks for this entity.
243 	 * The ticks doesn't indicates the life-time of the entity, but
244 	 * how many times it has been ticked by its world.
245 	 */
246 	public final pure nothrow @property @safe @nogc tick_t ticks() {
247 		return this.n_ticks;
248 	}
249 
250 	public @property @trusted bool onFire() {
251 		return this.metadata.get!("onFire", bool)();
252 	}
253 
254 	public @property @trusted bool onFire(bool flag) {
255 		return this.metadata.set!"onFire"(flag);
256 	}
257 
258 	public @property @trusted bool sneaking() {
259 		return this.metadata.get!("sneaking", bool)();
260 	}
261 
262 	public @property @trusted bool sneaking(bool flag) {
263 		return this.metadata.set!"sneaking"(flag);
264 	}
265 
266 	public @property @trusted bool sprinting() {
267 		return this.metadata.get!("sprinting", bool)();
268 	}
269 
270 	public @property @trusted bool sprinting(bool flag) {
271 		return this.metadata.set!"sprinting"(flag);
272 	}
273 
274 	public @property @trusted bool usingItem() {
275 		return this.metadata.get!("usingItem", bool)();
276 	}
277 
278 	public @property @trusted bool actionFlag(bool flag) {
279 		return this.metadata.set!"usingItem"(flag);
280 	}
281 
282 	public @property @trusted bool invisible() {
283 		return this.metadata.get!("invisible", bool)();
284 	}
285 
286 	public @property @trusted bool invisible(bool flag) {
287 		return this.metadata.set!"invisible"(flag);
288 	}
289 
290 	public @property @trusted string nametag() {
291 		return this.metadata.get!("nametag", string)();
292 	}
293 
294 	public @property @trusted string nametag(string nametag) {
295 		this.metadata.set!"nametag"(nametag);
296 		this.metadata.set!"customName"(nametag);
297 		return this.nametag;
298 	}
299 
300 	public @property @trusted bool showNametag() {
301 		return this.metadata.get!("showNametag", bool)();
302 	}
303 
304 	public @property @trusted bool showNametag(bool flag) {
305 		this.metadata.set!"showNametag"(flag);
306 		this.metadata.set!"alwaysShowNametag"(flag);
307 		return flag;
308 	}
309 
310 	public @property @trusted bool noai() {
311 		return this.metadata.get!("noAi", bool)();
312 	}
313 
314 	public @property @trusted bool noai(bool noai) {
315 		return this.metadata.set!"noAi"(noai);
316 	}
317 
318 	/**
319 	 * Indicates which entities this one should and should not see.
320 	 * By default only the entities indicated as true by this function
321 	 * will be shown through the <a href="#Entity.show">show</a> function
322 	 * and added to the watchlist.
323 	 * For example, an arrow can see a painting, so Arrow.shouldSee(painting)
324 	 * will be true, but a painting shouldn't see an arrow, so Painting.shouldSee(arrow)
325 	 * will be false.
326 	 * This increases the performances as there are less controls, casts and operation
327 	 * on arrays in big worlds or chunks of worlds with an high concetration of entities.
328 	 */
329 	public @safe bool shouldSee(Entity entity) {
330 		return true;
331 	}
332 
333 	/**
334 	 * Adds an entity to the ones this entity can see.
335 	 * Params:
336 	 * 		entity = the entity that will be showed to this entity
337 	 * Returns: true if the entity has been added to the visible entities, false otherwise
338 	 * Example:
339 	 * ---
340 	 * foreach(Player player ; world.players) {
341 	 *    player.show(entity);
342 	 *    entity.show(player);
343 	 * }
344 	 * ---
345 	 */
346 	public @safe bool show(Entity entity) {
347 		if(entity.id !in this.n_watchlist && entity.id != this.id) {
348 			this.n_watchlist[entity.id] = entity;
349 			entity.n_viewers[this.id] = this;
350 			return true;
351 		}
352 		return false;
353 	}
354 
355 	/**
356 	 * Checks wether this entity can see or not another entity.
357 	 * Example:
358 	 * ---
359 	 * if(!player.sees(arrow)) {
360 	 *    player.show(arrow);
361 	 * }
362 	 * ---
363 	 */
364 	public @safe @nogc bool sees(Entity entity) {
365 		return entity.id in this.n_watchlist ? true : false;
366 	}
367 
368 	/**
369 	 * Hides an entity from this entity, if this entity can see it.
370 	 * Params:
371 	 * 		entity = the entity to be hidden
372 	 * Returns: true if the entity has been hidden, false otherwise
373 	 * Example:
374 	 * ---
375 	 * foreach(Living living ; entity.watchlist!Living) {
376 	 *    entity.hide(living);
377 	 *    living.hide(entity);
378 	 * }
379 	 * ---
380 	 */
381 	public @safe bool hide(Entity entity) {
382 		if(entity.id in this.n_watchlist) {
383 			this.n_watchlist.remove(entity.id);
384 			entity.n_viewers.remove(this.id);
385 			return true;
386 		}
387 		return false;
388 	}
389 
390 	/**
391 	 * Gets a list of the entities that this entity can see.
392 	 * Example:
393 	 * ---
394 	 * // every entity
395 	 * auto entities = entity.watchlist;
396 	 * 
397 	 * // every player
398 	 * auto players = entity.watchlist!Player;
399 	 * ---
400 	 */
401 	public final @property @trusted T[] watchlist(T:Entity=Entity)() {
402 		static if(is(T == Entity)) {
403 			return this.n_watchlist.values;
404 		} else {
405 			T[] ret;
406 			foreach(ref Entity entity ; this.n_watchlist) {
407 				if(cast(T)entity) ret ~= cast(T)entity;
408 			}
409 			return ret;
410 		}
411 	}
412 
413 	/**
414 	 * Gets a list of the entities that can see this entity.
415 	 * See_Also: watchlist for the examples on the usage
416 	 */
417 	public final @property @trusted T[] viewers(T:Entity=Entity)() {
418 		static if(is(T == Entity)) {
419 			return this.n_viewers.values;
420 		} else {
421 			T[] ret;
422 			foreach(ref Entity entity ; this.n_viewers) {
423 				if(cast(T)entity) ret ~= cast(T)entity;
424 			}
425 			return ret;
426 		}
427 	}
428 
429 	/**
430 	 * Despawns this entity, calling the event in the world.
431 	 */
432 	protected void despawn() {
433 		this.world.despawn(this);
434 	}
435 
436 	public @safe @nogc void setAsDespawned() {
437 		this.n_alive = false;
438 	}
439 
440 	/**
441 	 * Checks the dead/alive status of the entity.
442 	 * Example:
443 	 * ---
444 	 * assert(entity.alive ^ entity.dead);
445 	 * ---
446 	 */
447 	public @property @safe bool alive() {
448 		return this.n_alive;
449 	}
450 
451 	/// ditto
452 	public @property @safe bool dead() {
453 		return !this.n_alive;
454 	}
455 
456 	/**
457 	 * Gets the 16x16 chunk the entity is in.
458 	 * A bigger chunk can be obtained by right-shifting the vector
459 	 * by the required amount.
460 	 * Example:
461 	 * ---
462 	 * auto chunk = entity.chunk;
463 	 * auto chunk128 = entity.chunk >> 3;
464 	 * ---
465 	 */
466 	public final @property @safe ChunkPosition chunk() {
467 		return cast(ChunkPosition)this.position >> 4;
468 	}
469 	
470 	/**
471 	 * Gets the entity's position.
472 	 */
473 	public pure nothrow @property @safe @nogc EntityPosition position() {
474 		return this.m_position;
475 	}
476 
477 	/**
478 	 * Gets the entity's motion.
479 	 */
480 	public pure nothrow @property @safe @nogc EntityPosition motion() {
481 		return this.m_motion;
482 	}
483 
484 	/**
485 	 * Sets the entity's motion.
486 	 */
487 	public @property @safe EntityPosition motion(EntityPosition motion) {
488 		this.motionmoved = true;
489 		return this.m_motion = motion;
490 	}
491 
492 	/**
493 	 * Checks whether or not an entity has motion.
494 	 * A motionless entity has every value of the motion's vector
495 	 * equal to 0.
496 	 */
497 	public @property @safe bool motionless() {
498 		return this.motion == 0;
499 	}
500 
501 	/**
502 	 * Sets the entity as motionless.
503 	 * This is equivalent to motion = EntityPosition(0).
504 	 */
505 	public @property @safe bool motionless(bool motionless) {
506 		if(motionless) this.motion = EntityPosition(0, 0, 0);
507 		return this.motionless;
508 	}
509 	
510 	/**
511 	 * Gets the motion as pc's velocity, ready to be encoded
512 	 * in a packet.
513 	 * Due to this encoding limitation, the entity's motion should
514 	 * never be higher than 4.096 (2^15 / 8000).
515 	 * If it is, it will be clamped.
516 	 */
517 	public @property @safe Vector3!short velocity() {
518 		auto ret = this.motion * 8000;
519 		return Vector3!short(clamp(ret.x, short.min, short.max), clamp(ret.y, short.min, short.max), clamp(ret.z, short.min, short.max));
520 	}
521 
522 	/**
523 	 * Gets the entity's looking direction (right-left).
524 	 * The value should always be in range 0..360.
525 	 */
526 	public final pure nothrow @property @safe @nogc float yaw() {
527 		return this.m_yaw;
528 	}
529 
530 	/**
531 	 * Gets the yaw as an unsigned byte for encoding reasons.
532 	 * To obtain a valid value the yaw should be in its valid range
533 	 * from 0 to 360.
534 	 */
535 	public final @property @safe ubyte angleYaw() {
536 		return safe!ubyte(this.yaw / 360 * 256);
537 	}
538 
539 	/**
540 	 * Gets the entity's body facing direction. This variable
541 	 * may not affect all the entities.
542 	 */
543 	public pure nothrow @property @safe @nogc float bodyYaw() {
544 		return this.m_body_yaw;
545 	}
546 	
547 	public final @property @safe ubyte angleBodyYaw() {
548 		return safe!ubyte(this.bodyYaw / 360 * 256);
549 	}
550 
551 	/**
552 	 * Gets the entity's looking direction (up-down).
553 	 * The value should be in range -90..90 (90 included).
554 	 */
555 	public final pure nothrow @property @safe @nogc float pitch() {
556 		return this.m_pitch;
557 	}
558 
559 	/**
560 	 * Gets the pitch as a byte for encoding reasons.
561 	 * To btain a valid value the pitch should be in its valid range
562 	 * from -90 to 90.
563 	 */
564 	public final @property @safe byte anglePitch() {
565 		return safe!byte(this.pitch / 90 * 64);
566 	}
567 
568 	/**
569 	 * Boolean value indicating whether or not the player is touching
570 	 * the ground or is in it.
571 	 * This value is true even if the player is in a liquid (like water).
572 	 */
573 	public final pure nothrow @property @safe @nogc bool onGround() {
574 		return this.n_on_ground;
575 	}
576 
577 	/**
578 	 * Gets the player's looking direction calculated from yaw and pitch.
579 	 * The return value is in range 0..1 and it should be multiplied to
580 	 * obtain the desired value.
581 	 */
582 	public final @property @safe EntityPosition direction() {
583 		float y = -sin(this.pitch * PI / 180f);
584 		float xz = cos(this.pitch * PI / 180f);
585 		float x = -xz * sin(this.yaw * PI / 180f);
586 		float z = xz * cos(this.yaw * PI / 180f);
587 		return EntityPosition(x, y, z);
588 	}
589 
590 	/**
591 	 * Moves the entity.
592 	 */
593 	public @safe void move(EntityPosition position) {
594 		if(this.position != position) {
595 			this.n_box.update(position);
596 		}
597 		this.m_position = position;
598 		this.moved = true;
599 	}
600 
601 	public void move(EntityPosition position, float yaw, float pitch) {
602 		this.m_yaw = yaw;
603 		this.m_pitch = pitch;
604 		this.move(position);
605 	}
606 
607 	public void move(EntityPosition position, float yaw, float bodyYaw, float pitch) {
608 		this.m_body_yaw = bodyYaw;
609 		this.move(position, yaw, pitch);
610 	}
611 
612 	/**
613 	 * Teleports the entity.
614 	 */
615 	public void teleport(EntityPosition position) {
616 		this.n_box.update(position);
617 		this.m_position = position;
618 		this.moved = true;
619 	}
620 
621 	/// ditto
622 	public void teleport(EntityPosition position, float yaw, float pitch) {
623 		this.m_yaw = yaw;
624 		this.m_pitch = pitch;
625 		this.teleport(position);
626 	}
627 
628 	/// ditto
629 	public void teleport(EntityPosition position, float yaw, float bodyYaw, float pitch) {
630 		this.m_body_yaw = bodyYaw;
631 		this.teleport(position, yaw, pitch);
632 	}
633 
634 	/// ditto
635 	public void teleport(World world, EntityPosition position) {
636 		//TODO
637 	}
638 
639 	/// ditto
640 	public void teleport(World world, EntityPosition position, float yaw, float pitch) {
641 		this.m_yaw = yaw;
642 		this.m_pitch = pitch;
643 		this.teleport(world, position);
644 	}
645 
646 	/// ditto
647 	public void teleport(World world, EntityPosition position, float yaw, float bodyYaw, float pitch) {
648 		this.m_body_yaw = bodyYaw;
649 		this.teleport(world, position, yaw, pitch);
650 	}
651 	
652 	/// ditto
653 	public void teleport(Position position) {
654 		this.teleport(position.from(this.position));
655 	}
656 	
657 	/// ditto
658 	public void teleport(Position position, float yaw, float pitch) {
659 		this.teleport(position.from(this.position), yaw, pitch);
660 	}
661 	
662 	/// ditto
663 	public void teleport(Position position, float yaw, float bodyYaw, float pitch) {
664 		this.teleport(position.from(this.position), yaw, bodyYaw, pitch);
665 	}
666 	
667 	/// ditto
668 	public void teleport(World world, Position position) {
669 		this.teleport(world, position.from(this.position));
670 	}
671 	
672 	/// ditto
673 	public void teleport(World world, Position position, float yaw, float pitch) {
674 		this.teleport(world, position.from(this.position), yaw, pitch);
675 	}
676 
677 	/// ditto
678 	public void teleport(World world, Position position, float yaw, float bodyYaw, float pitch) {
679 		this.teleport(world, position.from(this.position), yaw, bodyYaw, pitch);
680 	}
681 
682 	/**
683 	 * Gets entity's sizes.
684 	 */
685 	public final pure nothrow @property @safe @nogc double eyeHeight() {
686 		return this.n_eye_height;
687 	}
688 
689 	/**
690 	 * Does the onGround updates.
691 	 */
692 	protected void updateGroundStatus() {
693 		if(this.position.y >= this.m_last.y) {
694 			// going up
695 			this.highestPoint = this.position.y;
696 			this.n_falling = false;
697 			if(this.position.y != this.m_last.y) this.n_on_ground = false;
698 		} else {
699 			// free falling (check collision with the terrain)
700 			this.n_falling = true;
701 			this.n_on_ground = false;
702 			auto min = this.n_box.minimum;
703 			auto max = this.n_box.maximum;
704 			foreach(int x ; min.x.blockInto..max.x.blockInto+1) {
705 				foreach(int z ; min.z.blockInto..max.z.blockInto+1) {
706 					BlockPosition position = BlockPosition(x, to!int(this.position.y) - (to!int(this.position.y) == this.position.y ? 1 : 0), z);
707 					auto block = this.world[position];
708 					if(block.hasBoundingBox) {
709 						block.box.update(position.entityPosition);
710 						if(block.box.intersects(this.n_box)) {
711 							this.n_on_ground = true;
712 							this.doFallDamage(this.highestPoint - this.position.y, block.fallDamageModifier);
713 							this.highestPoint = this.position.y;
714 							this.last_puncher = null;
715 							goto BreakAll;
716 						}
717 					}
718 				}
719 			}
720 		}
721 		BreakAll:
722 		this.m_last = this.position;
723 	}
724 
725 	protected @trusted void doFallDamage(float distance, float modifier=1) {
726 		int damage = to!int(round((distance - 3) * modifier));
727 		if(damage > 0) {
728 			if(this.last_puncher is null) {
729 				this.attack(new EntityFallDamageEvent(this, damage));
730 			} else {
731 				this.attack(new EntityDoomedToFallEvent(this, this.last_puncher, damage));
732 			}
733 		}
734 	}
735 	
736 	/**
737 	 * Boolean value indicating whether or not the entity
738 	 * is falling.
739 	 */
740 	public final pure nothrow @property @safe @nogc bool falling() {
741 		return !this.onGround && this.n_falling;
742 	}
743 
744 	/**
745 	 * Does physic movements using the entity's parameters.
746 	 */
747 	protected @safe void doPhysic() {
748 
749 		// update the motion
750 		if(this.acceleration != 0) this.motion = this.motion - [0, this.acceleration, 0];
751 		if(this.motion.y.abs > this.terminal_velocity) this.m_motion = EntityPosition(this.m_motion.x, this.motion.y > 0 ? this.terminal_velocity : -this.terminal_velocity, this.m_motion.z);
752 		
753 		// move
754 		this.move(this.position + this.motion/*, atan2(this.motion.x, this.motion.z) * 180f / PI, atan2(this.motion.y, sqrt(this.motion.x * this.motion.x + this.motion.z * this.motion.z)) * 180f / PI*/);
755 		
756 		// apply the drag force
757 		if(this.drag != 0) this.motion = this.motion * (1f - this.drag);
758 
759 	}
760 
761 	/**
762 	 * Checks collisions with the entities in the watchlist
763 	 * and calls onCollideWithEntity on collision.
764 	 */
765 	protected void checkCollisionsWithEntities() {
766 		foreach(ref Entity entity ; this.viewers) {
767 			if(entity.box.intersects(this.n_box) && this.onCollideWithEntity(entity)) return;
768 		}
769 	}
770 	
771 	/**
772 	 * Function called from checkCollisionWithEntities when
773 	 * this entity collides with another entity.
774 	 * Returns: false if the calling function should check for more collisions, true otherwise.
775 	 */
776 	protected bool onCollideWithEntity(Entity entity) {
777 		return false;
778 	}
779 
780 	protected void checkCollisionsWithBlocks() {
781 		auto min = this.n_box.minimum;
782 		auto max = this.n_box.maximum;
783 		foreach(int x ; min.x.blockInto..max.x.blockInto+1) {
784 			foreach(int y ; min.y.blockInto..max.y.blockInto+1) {
785 				foreach(int z ; min.z.blockInto..max.z.blockInto+1) {
786 					auto position = BlockPosition(x, y, z);
787 					auto block = this.world[position];
788 					if(block.hasBoundingBox) {
789 						block.box.update(position.entityPosition);
790 						if(block.box.intersects(this.n_box) && this.onCollideWithBlock(block, position, 0)) return;
791 					}
792 				}
793 			}
794 		}
795 	}
796 
797 	protected bool onCollideWithBlock(Block block, BlockPosition position, uint face) {
798 		return false;
799 	}
800 	
801 	/**
802 	 * Updates the size of the entity and its bounding box.
803 	 */
804 	public @safe void setSize(float width, float height) {
805 		this.n_box.update(width, height);
806 	}
807 	
808 	/**
809 	 * Gets the entity's bounding box.
810 	 */
811 	public final @property @safe @nogc EntityAxis box() {
812 		return this.n_box;
813 	}
814 	/++
815 	/**
816 	 * Gets the entity's width.
817 	 */
818 	public final @property @safe @nogc float width() {
819 		return this.box.width;
820 	}
821 
822 	/**
823 	 * Gets the entity's height.
824 	 */
825 	public final @property @safe @nogc float height() {
826 		return this.box.height;
827 	}
828 	++/
829 	
830 	public final pure nothrow @property @safe @nogc float scale() {
831 		return 1f;
832 	}
833 	
834 	public final @property float scale(float scale) {
835 		version(Minecraft) {
836 			// throw exception
837 		}
838 		version(Pocket) {
839 			
840 		}
841 		return 1f;
842 	}
843 	
844 	/** Gets the entity's vechicle. */
845 	public @property @safe @nogc Entity vehicle() {
846 		return this.m_vehicle;
847 	}
848 
849 	/** Sets the entity's vehicle. */
850 	protected @property @safe Entity vehicle(Entity vehicle) {
851 		return this.m_vehicle = vehicle;
852 	}
853 
854 	/** Gets the entity's passenger. */
855 	public @property @safe Entity passenger() {
856 		return this.m_passenger;
857 	}
858 
859 	/**
860 	 * Sets the entity's passenger.
861 	 * The vehicle of the passenger is set automatically.
862 	 * Example:
863 	 * ---
864 	 * Player player = "steve".player;
865 	 * Boat boat = world.spawn!Boat;
866 	 * 
867 	 * boat.passenger = player;
868 	 * assert(player.vehicle == boat);
869 	 * ---
870 	 */
871 	public @property Entity passenger(Entity passenger) {
872 		if(passenger !is null) {
873 			passenger.vehicle = this;
874 			this.viewers!Player.call!"sendPassenger"(cast(ubyte)3u, passenger.id, this.id);
875 		} else if(this.passenger !is null) {
876 			this.passenger.vehicle = null;
877 			this.viewers!Player.call!"sendPassenger"(cast(ubyte)0u, this.passenger.id, this.id);
878 		}
879 		this.m_passenger = passenger;
880 		return this.m_passenger;
881 	}
882 
883 	/**
884 	 * Attacks an entity and returns the event used.
885 	 */
886 	public T attack(T:EntityDamageEvent)(T event) if(is(T == class) && !isAbstractClass!T) {
887 		if(this.validateAttack(event)) {
888 			this.world.callEvent(event);
889 			if(!event.cancelled) this.attackImpl(event);
890 		} else {
891 			event.cancel();
892 		}
893 		return event;
894 	}
895 
896 	protected bool validateAttack(EntityDamageEvent event) {
897 		return false;
898 	}
899 
900 	protected void attackImpl(EntityDamageEvent event) {
901 
902 	}
903 
904 	/**
905 	 * Send the metadata to the viewers
906 	 */
907 	protected void broadcastMetadata() {
908 		Player[] players = this.viewers!Player;
909 		if(players.length > 0) {
910 			foreach(ref Player player ; players) {
911 				player.sendMetadata(this);
912 			}
913 		}
914 	}
915 
916 	/**
917 	 * Drop an item from this entity
918 	 */
919 	public void drop(Slot slot) {
920 		float f0 = uniform01!float(this.world.random) * PI * 2f;
921 		float f1 = uniform01!float(this.world.random) * .02f;
922 		this.world.drop(slot, this.position + [0, this.eyeHeight - .3, 0], this.direction * .3f + [cos(f0) * f1, (uniform01!float(this.world.random) - uniform01!float(this.world.random)) * .1f + .1f, sin(f0) * f1]);
923 	}
924 
925 	public @property @safe string name() {
926 		return typeid(this).to!string.split(".")[$-1];
927 	}
928 
929 	public @property @safe string displayName() {
930 		return this.name;
931 	}
932 
933 	public override @safe bool opEquals(Object o) {
934 		return cast(Entity)o && (cast(Entity)o).id == this.id;
935 	}
936 
937 	public override @safe string toString() {
938 		return typeid(this).to!string ~ "(" ~ to!string(this.id) ~ ")";
939 	}
940 
941 }
942 
943 enum Rotation : float {
944 
945 	KEEP = float.nan,
946 
947 	// yaw
948 	WEST = 0,
949 	NORTH = 90,
950 	EAST = 180,
951 	SOUTH = 270,
952 
953 	// pitch
954 	DOWN = 90,
955 	FRONT = 0,
956 	UP = -90,
957 
958 }
959 
960 /**
961  * A template for entities with changes on variables.
962  * Example:
963  * ---
964  * // an entity on fire by default
965  * alias OnFire(T) = Changed!(T, "this.onFire = true;");
966  * Creeper creeper = world.spawn!(OnFire!Creeper);
967  * assert(creeper.onFire);
968  * 
969  * // multiple changes can be used togheter
970  * new OnFire!(Unticked!(Noai!Creeper))();
971  * ---
972  */
973 template VariableChanged(T:Entity, string changes) {
974 
975 	class VariableChanged : T {
976 
977 		public @safe this(E...)(E args) {
978 			super(args);
979 			mixin(changes);
980 		}
981 
982 	}
983 
984 	//alias VariableChanged = X;
985 
986 }
987 
988 /**
989  * An entity without ticking.
990  */
991 alias Unticked(T:Entity) = VariableChanged!(T, "this.ticking = false;");
992 
993 /**
994  * An Entity without AI.
995  */
996 alias Noai(T:Entity) = VariableChanged!(T, "this.noai = true");
997 
998 /**
999  * An entity without ticking and AI.
1000  */
1001 alias UntickedNoai(T:Entity) = VariableChanged!(T, "this.ticking = false;this.noai = true;");
1002 
1003 /**
1004  * A template for entities with changing on functions.
1005  */
1006 template FunctionChanged(T:Entity, string changes) {
1007 
1008 	class FunctionChanged : T {
1009 
1010 		mixin(changes);
1011 
1012 	}
1013 
1014 }
1015 
1016 /**
1017  * An entity without physic.
1018  */
1019 alias NoPhysic(T:Entity) = FunctionChanged!(T, "protected override void doPhysic(){}");
1020 
1021 /**
1022  * An entity that doesn't take fall damage.
1023  */
1024 alias NoFallDamage(T:Entity) = FunctionChanged!(T, "protected override void doFallDamage(float distance){}");