Esempio n. 1
0
        public void RemoveWorldObject(ObjectGuid objectId, bool adjacencyMove)
        {
            WorldObject wo = null;

            Log($"removing {objectId.Full.ToString("X")}");

            lock (objectCacheLocker)
            {
                if (worldObjects.ContainsKey(objectId))
                {
                    wo = worldObjects[objectId];
                    if (!objectId.IsCreature())
                    {
                        worldObjects.Remove(objectId);
                    }
                }
            }

            // suppress broadcasting when it's just an adjacency move.  clients will naturally just stop
            // tracking stuff if they're too far, or the new landblock will broadcast to them if they're
            // close enough.
            // if we are in a container - we need never broadcast a destroy - just remove from landblock above.
            if (!adjacencyMove && id.MapScope == Enum.MapScope.Outdoors && wo != null)
            {
                var args = BroadcastEventArgs.CreateAction(BroadcastAction.Delete, wo);
                Broadcast(args, true, Quadrant.All);
            }
        }
Esempio n. 2
0
        public void AddWorldObject(WorldObject wo)
        {
            List <WorldObject> allObjects;

            Log($"adding {wo.Guid.Full.ToString("X")}");

            lock (objectCacheLocker)
            {
                allObjects = worldObjects.Values.ToList();
                if (!worldObjects.ContainsKey(wo.Guid))
                {
                    worldObjects[wo.Guid] = wo;
                }
            }

            var args = BroadcastEventArgs.CreateAction(BroadcastAction.AddOrUpdate, wo);

            Broadcast(args, true, Quadrant.All);

            // if this is a player, tell them about everything else we have in range of them.
            if (wo is Player)
            {
                List <WorldObject> wolist = null;
                wolist = GetWorldObjectsInRange(wo, maxobjectRange, true);
                AddPlayerTracking(wolist, (wo as Player));
            }
        }
Esempio n. 3
0
        public void AddWorldObject(WorldObject wo)
        {
            List <WorldObject> allObjects;

            Log($"adding {wo.Guid.Full.ToString("X")}");

            lock (objectCacheLocker)
            {
                allObjects = worldObjects.Values.ToList();
                if (!worldObjects.ContainsKey(wo.Guid))
                {
                    worldObjects[wo.Guid] = wo;
                }
            }

            var args = BroadcastEventArgs.CreateAction(BroadcastAction.AddOrUpdate, wo);

            Broadcast(args, true, Quadrant.All);

            // if this is a player, tell them about everything else we have.
            if (wo is Player)
            {
                // send them the initial burst of objects
                Log($"blasting player \"{(wo as Player).Name}\" with {allObjects.Count} objects.");
                Parallel.ForEach(allObjects, (o) =>
                {
                    if (o.Guid.IsCreature())
                    {
                        if ((o as Creature).IsAlive)
                        {
                            (wo as Player).TrackObject(o);
                        }
                    }
                    else
                    {
                        (wo as Player).TrackObject(o);
                    }
                });
            }
        }
Esempio n. 4
0
        /// <summary>
        /// main game loop
        /// </summary>
        public void UseTime()
        {
            while (running)
            {
                // here we'd move server objects in motion (subject to landscape) and do physics collision detection

                List <WorldObject> allworldobj    = null;
                List <Player>      allplayers     = null;
                List <Creature>    allcreatures   = null;
                List <WorldObject> movedObjects   = null;
                List <WorldObject> despawnObjects = null;
                List <Creature>    deadCreatures  = null;

                lock (objectCacheLocker)
                {
                    allworldobj = worldObjects.Values.ToList();
                }

                // all players on this land block
                allplayers   = allworldobj.OfType <Player>().ToList();
                allcreatures = allworldobj.OfType <Creature>().ToList();

                despawnObjects = allworldobj.ToList();
                despawnObjects = despawnObjects.Where(x => x.DespawnTime > -1).ToList();

                deadCreatures = allworldobj.OfType <Creature>().ToList();
                deadCreatures = deadCreatures.Where(x => x.IsAlive == false).ToList();

                // flag them as updated now in order to reduce chance of missing an update
                // this is only for moving objects across landblocks.
                movedObjects = allworldobj.ToList();
                movedObjects = movedObjects.Where(p => p.LastUpdatedTicks >= p.LastMovementBroadcastTicks).ToList();
                movedObjects.ForEach(m => m.LastMovementBroadcastTicks = WorldManager.PortalYearTicks);

                if (id.MapScope == Enum.MapScope.Outdoors)
                {
                    // check to see if a player or other mutable object "roamed" to an adjacent landblock
                    var objectsToRelocate = movedObjects.Where(m => m.Location.LandblockId.IsAdjacentTo(id) && m.Location.LandblockId != id).ToList();

                    // so, these objects moved to an adjacent block.  they could have recalled to that block, died and bounced to a lifestone on that block, or
                    // just simply walked accross the border line.  in any case, we won't delete them, we'll just transfer them.  the trick, though, is to
                    // figure out how to treat it in adjacent landblocks.  if the player walks across the southern border, the north adjacency needs to remove
                    // them, but the south is actually getting them.  we need to avoid sending Delete+Create to clients that already know about it, though.

                    objectsToRelocate.ForEach(o => Log($"attempting to relocate object {o.Name} ({o.Guid.Full.ToString("X")})"));

                    // RelocateObject will put them in the right landblock
                    objectsToRelocate.ForEach(o => LandblockManager.RelocateObject(o));

                    // Remove has logic to make sure it doesn't double up the delete+create when "true" is passed.
                    objectsToRelocate.ForEach(o => RemoveWorldObject(o.Guid, true));
                }

                // for all players on landblock.
                Parallel.ForEach(allplayers, player =>
                {
                    // Process Action Queue for player.
                    QueuedGameAction action = player.ActionQueuePop();
                    if (action != null)
                    {
                        HandleGameAction(action, player);
                    }

                    // Process Examination Queue for player
                    QueuedGameAction examination = player.ExaminationQueuePop();
                    if (examination != null)
                    {
                        HandleGameAction(examination, player);
                    }
                });
                UpdateStatus(allplayers.Count);

                double tickTime = WorldManager.PortalYearTicks;
                // per-creature update on landblock.
                Parallel.ForEach(allworldobj, wo =>
                {
                    // Process the creatures
                    wo.Tick(tickTime);
                });

                // broadcast moving objects to the world..
                // players and creatures can move.
                Parallel.ForEach(movedObjects, mo =>
                {
                    // detect all world objects in ghost range
                    List <WorldObject> woproxghost = new List <WorldObject>();
                    woproxghost.AddRange(GetWorldObjectsInRange(mo, maxobjectGhostRange, true));

                    // for all objects in rang of this moving object or in ghost range of moving object update them.
                    Parallel.ForEach(woproxghost, wo =>
                    {
                        if (mo.Guid.IsPlayer())
                        {
                            // if world object is in active zone then.
                            if (wo.Location.SquaredDistanceTo(mo.Location) <= maxobjectRange)
                            {
                                // if world object is in active zone.
                                if (!(mo as Player).GetTrackedObjectGuids().Contains(wo.Guid))
                                {
                                    (mo as Player).TrackObject(wo);
                                }
                            }
                            // if world object is in ghost zone and outside of active zone
                            else
                            if ((mo as Player).GetTrackedObjectGuids().Contains(wo.Guid))
                            {
                                (mo as Player).StopTrackingObject(wo, true);
                            }
                        }
                    });

                    if (mo.Location.LandblockId == id)
                    {
                        // update if it's still here
                        Broadcast(BroadcastEventArgs.CreateAction(BroadcastAction.AddOrUpdate, mo), true, Quadrant.All);
                    }
                    else
                    {
                        // remove and readd if it's not
                        RemoveWorldObject(mo.Guid, false);
                        LandblockManager.AddObject(mo);
                    }
                });

                // despawn objects
                despawnObjects.ForEach(deo =>
                {
                    if (deo.DespawnTime < WorldManager.PortalYearTicks)
                    {
                        RemoveWorldObject(deo.Guid, false);
                    }
                });

                // respawn creatures
                deadCreatures.ForEach(dc =>
                {
                    if (dc.RespawnTime < WorldManager.PortalYearTicks)
                    {
                        dc.IsAlive = true;
                        // HandleParticleEffectEvent(dc, PlayScript.Create);
                        AddWorldObject(dc);
                    }
                });

                Thread.Sleep(1);
            }

            // TODO: release resources
        }
Esempio n. 5
0
        /// <summary>
        /// main game loop
        /// </summary>
        public void UseTime()
        {
            while (running)
            {
                // here we'd move server objects in motion (subject to landscape) and do physics collision detection

                // for now, we'll move players around
                List <WorldObject> movedObjects = null;
                List <Player>      players      = null;

                lock (objectCacheLocker)
                {
                    movedObjects = this.worldObjects.Values.OfType <WorldObject>().ToList();
                    players      = this.worldObjects.Values.OfType <Player>().ToList();
                }

                movedObjects = movedObjects.Where(p => p.LastUpdatedTicks >= p.LastMovementBroadcastTicks).ToList();

                // flag them as updated now in order to reduce chance of missing an update
                movedObjects.ForEach(m => m.LastMovementBroadcastTicks = WorldManager.PortalYearTicks);

                if (this.id.MapScope == Enum.MapScope.Outdoors)
                {
                    // check to see if a player or other mutable object "roamed" to an adjacent landblock
                    var objectsToRelocate = movedObjects.Where(m => m.Location.LandblockId.IsAdjacentTo(this.id) && m.Location.LandblockId != this.id).ToList();

                    // so, these objects moved to an adjacent block.  they could have recalled to that block, died and bounced to a lifestone on that block, or
                    // just simply walked accross the border line.  in any case, we won't delete them, we'll just transfer them.  the trick, though, is to
                    // figure out how to treat it in adjacent landblocks.  if the player walks across the southern border, the north adjacency needs to remove
                    // them, but the south is actually getting them.  we need to avoid sending Delete+Create to clients that already know about it, though.

                    objectsToRelocate.ForEach(o => Log($"attempting to relocate object {o.Name} ({o.Guid.Full.ToString("X")})"));

                    // RelocateObject will put them in the right landblock
                    objectsToRelocate.ForEach(o => LandblockManager.RelocateObject(o));

                    // Remove has logic to make sure it doesn't double up the delete+create when "true" is passed.
                    objectsToRelocate.ForEach(o => RemoveWorldObject(o.Guid, true));
                }

                // broadcast
                Parallel.ForEach(movedObjects, mo =>
                {
                    if (mo.Location.LandblockId == this.id)
                    {
                        // update if it's still here
                        Broadcast(BroadcastEventArgs.CreateAction(BroadcastAction.AddOrUpdate, mo), true, Quadrant.All);
                    }
                    else
                    {
                        // remove and readd if it's not
                        this.RemoveWorldObject(mo.Guid, false);
                        LandblockManager.AddObject(mo);
                    }
                });

                // TODO: figure out if this landblock can be unloaded

                // process player action queues
                foreach (Player p in players)
                {
                    QueuedGameAction action = p.ActionQueuePop();

                    if (action != null)
                    {
                        HandleGameAction(action, p);
                    }
                }

                Thread.Sleep(1);
            }

            // TODO: release resources
        }