/// <summary> /// 检查移动是否合法 /// </summary> /// <param name="mActor"></param> /// <param name="to"></param> /// <returns></returns> public virtual bool MoveStepIsInRange(Actor mActor, MoveArg to) { if (mActor.ActorType == ActorType.PC) { TimeSpan span = DateTime.Now - mActor.moveCheckStamp; if (span.TotalMilliseconds > 50) { double maximal; if (span.TotalMilliseconds > 1000) { maximal = mActor.Speed * 2f; } else { maximal = mActor.Speed * (span.TotalMilliseconds / 1000) * 2f; } // Disabled, until we have something better if (System.Math.Abs(mActor.X - to.X) > maximal) { return(false); } if (System.Math.Abs(mActor.Y - to.Y) > maximal) { return(false); } //we don't check for z , yet, to allow falling from great hight //if (System.Math.Abs(mActor.z - to[2]) > mActor.maxMoveRange) return false; } } return(true); }
/// <summary> /// 移动Actor /// </summary> /// <param name="mActor"></param> /// <param name="arg"></param> /// <param name="sendToSelf"></param> public void MoveActor(Actor mActor, MoveArg arg, bool sendToSelf) { try { bool knockBack = false; // check wheter the destination is in range, if not kick the client /*if (!this.MoveStepIsInRange(mActor, arg)) * { * knockBack = true; * sendToSelf = true; * }*/ if (mActor.EventHandler == null) { return; } OnMoveActor(mActor, arg, knockBack); //scroll through all actors that "could" see the mActor at "from" //or are going "to see" mActor, or are still seeing mActor if (!knockBack) { for (short deltaY = -1; deltaY <= 1; deltaY++) { for (short deltaX = -1; deltaX <= 1; deltaX++) { int region = mActor.Region + (deltaX * 10000) + deltaY; if (!this.actorsByRegion.TryGetValue(region, out ConcurrentDictionary <ulong, Actor> actors)) { continue; } foreach (KeyValuePair <ulong, Actor> pair in actors) { Actor actor = pair.Value; try { if (actor == null) { continue; } if (actor.EventHandler == null) { DeleteActor(actor); continue; } if (actor.ActorID == mActor.ActorID && !sendToSelf) { continue; } // A) INFORM OTHER ACTORS //actor "could" see mActor at its "from" position if (this.ACanSeeB(actor, mActor)) { //actor will still be able to see mActor if (this.ACanSeeB(actor, mActor, arg.X, arg.Y)) { if (arg.MoveType == MoveType.Start) { actor.EventHandler.OnActorStartsMoving(mActor, arg); } else { actor.EventHandler.OnActorStopsMoving(mActor, arg); } } //actor won't be able to see mActor anymore else { actor.EventHandler.OnActorDisappears(mActor); } } //actor "could not" see mActor, but will be able to see him now else if (this.ACanSeeB(actor, mActor, arg.X, arg.Y)) { actor.EventHandler.OnActorAppears(mActor); //send move / move stop if (arg.MoveType == MoveType.Start) { actor.EventHandler.OnActorStartsMoving(mActor, arg); } else { actor.EventHandler.OnActorStopsMoving(mActor, arg); } } // B) INFORM mActor //mActor "could" see actor on its "from" position if (this.ACanSeeB(mActor, actor)) { //mActor won't be able to see actor anymore if (!this.ACanSeeB(mActor, arg.X, arg.Y, actor)) { mActor.EventHandler.OnActorDisappears(actor); } //mAactor will still be able to see actor else { } } else if (this.ACanSeeB(mActor, arg.X, arg.Y, actor)) { //mActor "could not" see actor, but will be able to see him now //send pcinfo mActor.EventHandler.OnActorAppears(actor); } } catch (Exception ex) { Logger.Log.Error(ex); } } } } } else { mActor.EventHandler.OnActorStopsMoving(mActor, arg); } //lock (mActor) { mActor.X = arg.X; mActor.Y = arg.Y; mActor.Z = arg.Z; mActor.Dir = arg.Dir; //mActor.Speed = arg.Speed; } //update the region of the actor int newRegion = this.GetRegion(arg.X, arg.Y); if (mActor.Region != newRegion) { if (this.actorsByRegion.TryGetValue(mActor.Region, out ConcurrentDictionary <ulong, Actor> list)) { list.TryRemove(mActor.ActorID, out Actor removed); } //turn off all the ai if the old region has no player on it mActor.Region = newRegion; if (!this.actorsByRegion.TryGetValue(newRegion, out list)) { list = new ConcurrentDictionary <ulong, Actor>(); this.actorsByRegion[newRegion] = list; } list[mActor.ActorID] = mActor; } } catch (Exception ex) { Logger.Log.Error(ex); } }
public abstract void OnMoveActor(Actor mActor, MoveArg arg, bool knockBack);
/// <summary> /// 移动Actor /// </summary> /// <param name="mActor"></param> /// <param name="arg"></param> public void MoveActor(Actor mActor, MoveArg arg) { MoveActor(mActor, arg, false); }