/// <summary> /// (Re)generates the relative heightmap for this room. Neccessary after furniture updates. /// </summary> public void RegenerateRelativeHeightmap(bool Broadcast = false) { lock (mItems) { mGuestsCanPlaceStickies = false; mFurniMap = new uint[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY]; mStackHeight = new double[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY]; mStackTopItemHeight = new double[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY]; mUserMovementNodes = new UserMovementNode[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY]; mTileEffects = new RoomTileEffect[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY]; mRedirectGrid = new Vector2[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY]; for (int y = 0; y < mCachedModel.Heightmap.SizeY; y++) { for (int x = 0; x < mCachedModel.Heightmap.SizeX; x++) { mStackHeight [x, y] = mCachedModel.Heightmap.FloorHeight [x, y]; mStackTopItemHeight [x, y] = 0; mUserMovementNodes [x, y] = UserMovementNode.Walkable; mTileEffects [x, y] = new RoomTileEffect(); mRedirectGrid [x, y] = null; } } bool[,] AnyItemInStack = new bool[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY]; foreach (Item Item in mItems.Values) { if (Item.Definition.StackingBehavior == ItemStackingBehavior.Ignore) { continue; } double TotalItemStackHeight = Item.RoomPosition.Z + Math.Round(Item.Definition.Height, 1); List <Vector2> AffectedTiles = CalculateAffectedTiles(Item, Item.RoomPosition.GetVector2(), Item.RoomRotation); RoomTileEffect Effect = new RoomTileEffect(); UserMovementNode MovementNode = UserMovementNode.Blocked; switch (Item.Definition.Behavior) { case ItemBehavior.Seat: case ItemBehavior.LoveShuffler: Effect = new RoomTileEffect(RoomTileEffectType.Sit, Item.RoomRotation, new Vector2(Item.RoomPosition.X, Item.RoomPosition.Y), Item.Definition.Height, 0, Item.DefinitionId); MovementNode = UserMovementNode.WalkableEndOfRoute; break; case ItemBehavior.Bed: Effect = new RoomTileEffect(RoomTileEffectType.Lay, Item.RoomRotation, new Vector2(Item.RoomPosition.X, Item.RoomPosition.Y), Item.Definition.Height, 0, Item.DefinitionId); MovementNode = UserMovementNode.WalkableEndOfRoute; break; case ItemBehavior.Gate: MovementNode = Item.Flags == "1" ? UserMovementNode.Walkable : UserMovementNode.Blocked; break; case ItemBehavior.AvatarEffectGenerator: Effect = new RoomTileEffect(RoomTileEffectType.Effect, 0, Item.RoomPosition.GetVector2(), 0, Item.Definition.BehaviorData, Item.DefinitionId); break; case ItemBehavior.StickyPole: mGuestsCanPlaceStickies = true; break; } foreach (Vector2 Tile in AffectedTiles) { if (TotalItemStackHeight >= mStackHeight [Tile.X, Tile.Y]) { if (Item.Definition.Walkable == ItemWalkableMode.Always) { MovementNode = UserMovementNode.Walkable; } else if (Item.Definition.Walkable == ItemWalkableMode.Limited) { MovementNode = (AnyItemInStack [Tile.X, Tile.Y] && mUserMovementNodes [Tile.X, Tile.Y] != UserMovementNode.Walkable) ? UserMovementNode.Blocked : UserMovementNode.Walkable; } mStackHeight [Tile.X, Tile.Y] = TotalItemStackHeight; mStackTopItemHeight [Tile.X, Tile.Y] = Item.Definition.Height; mUserMovementNodes [Tile.X, Tile.Y] = MovementNode; mTileEffects [Tile.X, Tile.Y] = Effect; mFurniMap [Tile.X, Tile.Y] = Item.Id; if (Item.Definition.Behavior == ItemBehavior.Bed) { if (Item.RoomRotation == 2 || Item.RoomRotation == 6) { mRedirectGrid [Tile.X, Tile.Y] = new Vector2(Item.RoomPosition.X, Tile.Y); } if (Item.RoomRotation == 0 || Item.RoomRotation == 4) { mRedirectGrid [Tile.X, Tile.Y] = new Vector2(Tile.X, Item.RoomPosition.Y); } } else { mRedirectGrid [Tile.X, Tile.Y] = null; } AnyItemInStack [Tile.X, Tile.Y] = true; } } } foreach (StaticObject Object in mStaticObjects) { mStackHeight [Object.Position.X, Object.Position.Y] = mCachedModel.Heightmap.FloorHeight [Object.Position.X, Object.Position.Y] + 1.0; mStackTopItemHeight [Object.Position.X, Object.Position.Y] = 1.0; mUserMovementNodes [Object.Position.X, Object.Position.Y] = (Object.IsSeat ? UserMovementNode.WalkableEndOfRoute : UserMovementNode.Blocked); if (Object.IsSeat) { mTileEffects [Object.Position.X, Object.Position.Y] = new RoomTileEffect(RoomTileEffectType.Sit, Object.Rotation, Object.Position, 1.0); } } lock (mTileStates) { StringBuilder RelativeHeightmap = new StringBuilder(); mTileStates = new TileState[mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY]; for (int y = 0; y < mCachedModel.Heightmap.SizeY; y++) { for (int x = 0; x < mCachedModel.Heightmap.SizeX; x++) { if (mInfo.Type == RoomType.Flat && mCachedModel.DoorPosition.X == x && mCachedModel.DoorPosition.Y == y) { mTileStates [x, y] = TileState.Door; RelativeHeightmap.Append(mCachedModel.DoorPosition.Z); continue; } if (mCachedModel.Heightmap.TileStates [x, y] == TileState.Blocked) { mTileStates [x, y] = TileState.Blocked; RelativeHeightmap.Append('x'); continue; } mTileStates [x, y] = TileState.Open; RelativeHeightmap.Append(mCachedModel.Heightmap.FloorHeight [x, y]); } RelativeHeightmap.Append(Convert.ToChar(13)); } lock (mRelativeHeightmap) { string NewRelativeMap = RelativeHeightmap.ToString(); if (NewRelativeMap != mRelativeHeightmap) { mRelativeHeightmap = RelativeHeightmap.ToString(); if (Broadcast) { BroadcastMessage(RoomRelativeHeightmapComposer.Compose(mRelativeHeightmap)); } } } } } }
public void SendObjects(Session Session) { Session.SendData(RoomItemHeightmapComposer.Compose(Model.Heightmap.ToString())); Session.SendData(RoomRelativeHeightmapComposer.Compose(RelativeHeightmap)); List <RoomActor> ActorObjects = new List <RoomActor>(); Dictionary <uint, int> DancingActors = new Dictionary <uint, int>(); Dictionary <uint, int> CarryingActors = new Dictionary <uint, int>(); Dictionary <uint, int> EffectActors = new Dictionary <uint, int>(); List <uint> SleepingActors = new List <uint>(); lock (mActorSyncRoot) { foreach (RoomActor Actor in mActors.Values) { ActorObjects.Add(Actor); if (Actor.DanceId > 0) { DancingActors.Add(Actor.Id, Actor.DanceId); } if (Actor.CarryItemId > 0) { CarryingActors.Add(Actor.Id, Actor.CarryItemId); } if (Actor.AvatarEffectId > 0) { EffectActors.Add(Actor.Id, Actor.AvatarEffectId); } if (Actor.IsSleeping) { SleepingActors.Add(Actor.Id); } } } Session.SendData(RoomUserObjectListComposer.Compose(ActorObjects)); Session.SendData(RoomStaticObjectsComposer.Compose(mStaticObjects)); Session.SendData(RoomFloorObjectsComposer.Compose(GetFloorItems())); Session.SendData(RoomWallObjectsComposer.Compose(GetWallItems())); Session.SendData(RoomUserStatusListComposer.Compose(ActorObjects)); foreach (KeyValuePair <uint, int> DancingActor in DancingActors) { Session.SendData(RoomUserDanceComposer.Compose(DancingActor.Key, DancingActor.Value)); } foreach (KeyValuePair <uint, int> CarryingActor in CarryingActors) { Session.SendData(RoomUserCarryComposer.Compose(CarryingActor.Key, CarryingActor.Value)); } foreach (KeyValuePair <uint, int> EffectActor in EffectActors) { Session.SendData(RoomUserEffectComposer.Compose(EffectActor.Key, EffectActor.Value)); } foreach (uint SleepingActor in SleepingActors) { Session.SendData(RoomUserSleepComposer.Compose(SleepingActor, true)); } }