This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
Drew DeVault 362c852f51 Many improvements to server stability+performance
Sorry for the vague commit message. There were a lot of changes. Here's
a list of most of them:

- Lighting updates are timeboxed each frame
- The next environment frame is queued sooner if the current one took
  longer (as soon as immediately)
- Issues with the physics engines and mobs using it were (mostly) fixed,
  mobs no longer freak out and get stuck on physics objects
- Mob AI/pathfinding is done more intelligently
- The player can no longer spawn in an ocean or a desert biome
- Some deadlocks in Region were fixed (more remain to be fixed)

The current performance bottlenecks are lighting (still) and propegating
initial chunk loads to blocks that need to schedule things (such as
grass blocks). I think the main culprit in the latter case is grass
blocks and water blocks. The former can be improved by adding a block
cache to World, but that'll take some custom work. This step is just
gonna be slow no matter what, we might have to split it across several
frames but it's never going to be great.

There still seems to be a deadlock somewhere in all of this mess, in the
world code. I'll find it later.
2017-05-22 19:51:23 -04:00

148 lines
4.2 KiB
C#

using System;
using TrueCraft.API.Networking;
using TrueCraft.Core.Networking.Packets;
using TrueCraft.API.Entities;
using TrueCraft.API;
using TrueCraft.API.Server;
using System.Linq;
using TrueCraft.API.AI;
using TrueCraft.Core.AI;
using TrueCraft.API.Physics;
namespace TrueCraft.Core.Entities
{
public abstract class MobEntity : LivingEntity, IAABBEntity, IMobEntity
{
protected MobEntity()
{
Speed = 4;
CurrentState = new WanderState();
}
public event EventHandler PathComplete;
public override IPacket SpawnPacket
{
get
{
return new SpawnMobPacket(EntityID, MobType,
MathHelper.CreateAbsoluteInt(Position.X),
MathHelper.CreateAbsoluteInt(Position.Y),
MathHelper.CreateAbsoluteInt(Position.Z),
MathHelper.CreateRotationByte(Yaw),
MathHelper.CreateRotationByte(Pitch),
Metadata);
}
}
public abstract sbyte MobType { get; }
public virtual bool Friendly { get { return true; } }
public virtual void TerrainCollision(Vector3 collisionPoint, Vector3 collisionDirection)
{
// This space intentionally left blank
}
public BoundingBox BoundingBox
{
get
{
return new BoundingBox(Position, Position + Size);
}
}
public virtual bool BeginUpdate()
{
EnablePropertyChange = false;
return true;
}
public virtual void EndUpdate(Vector3 newPosition)
{
EnablePropertyChange = true;
Position = newPosition;
}
public float AccelerationDueToGravity
{
get
{
return 1.6f;
}
}
public float Drag
{
get
{
return 0.40f;
}
}
public float TerminalVelocity
{
get
{
return 78.4f;
}
}
public PathResult CurrentPath { get; set; }
/// <summary>
/// Mob's current speed in m/s.
/// </summary>
public virtual double Speed { get; set; }
public IMobState CurrentState { get; set; }
public void Face(Vector3 target)
{
var diff = target - Position;
Yaw = (float)MathHelper.RadiansToDegrees(-(Math.Atan2(diff.X, diff.Z) - Math.PI) + Math.PI); // "Flip" over the 180 mark
}
public bool AdvancePath(TimeSpan time, bool faceRoute = true)
{
var modifier = time.TotalSeconds * Speed;
if (CurrentPath != null)
{
// Advance along path
var target = (Vector3)CurrentPath.Waypoints[CurrentPath.Index];
target += new Vector3(Size.Width / 2, 0, Size.Depth / 2); // Center it
target.Y = Position.Y; // TODO: Find better way of doing this
if (faceRoute)
Face(target);
var lookAt = Vector3.Forwards.Transform(Matrix.CreateRotationY(MathHelper.ToRadians(-(Yaw - 180) + 180)));
lookAt *= modifier;
Velocity = new Vector3(lookAt.X, Velocity.Y, lookAt.Z);
if (Position.DistanceTo(target) < Velocity.Distance)
{
Position = target;
Velocity = Vector3.Zero;
CurrentPath.Index++;
if (CurrentPath.Index >= CurrentPath.Waypoints.Count)
{
CurrentPath = null;
if (PathComplete != null)
PathComplete(this, null);
return true;
}
}
}
return false;
}
public override void Update(IEntityManager entityManager)
{
if (CurrentState != null)
CurrentState.Update(this, entityManager);
else
AdvancePath(entityManager.TimeSinceLastUpdate);
base.Update(entityManager);
}
}
}