using System; using System.Collections.Generic; using System.Linq; using System.Text; using Chop.Rooms; using Chop.User; using System.Data; using Chop.Database; using Chop.Game.User; using System.Threading; using Chop.Game.Rooms.Games; namespace Chop.Game.Rooms { public class Room : NavigatorRoom, IDisposable { public Dictionary mUsers; public RoomTemplate mTemplate; public IHIPathfinder mPathfinder; public Thread Runner; public byte[,] mDynamicHeightmap; public SquareState[,] mSquareMap; public RoomTrigger[,] mTriggers; public Lobby mLobby; private bool disposed = false; public override int Visitors { get { return mUsers.Count; } } public Room() { mUsers = new Dictionary(); } public static Room Load(int pID) { Room room = new Room(); using (DatabaseClient dbClient = Core.DatabaseManager.GetClient()) { dbClient.AddParamWithValue("id", pID); room.Parse(dbClient.ReadDataRow("SELECT * FROM rooms WHERE id = @id")); } room.mTemplate = Core.RoomTemplateManager.GetTemplate(room.mModel); return room; } public virtual void Init() { mPathfinder = new IHIPathfinder(); mDynamicHeightmap = mTemplate.mDynamicHeightmap; mTriggers = new RoomTrigger[mDynamicHeightmap.GetLength(0), mDynamicHeightmap.GetLength(1)]; mSquareMap = mTemplate.mSquares; foreach (RoomTrigger trigger in Core.RoomTemplateManager.GetTriggers(mModel)) mTriggers[trigger.mX, trigger.mY] = trigger; mPathfinder.ApplyCollisionMap(mDynamicHeightmap, mTemplate.mDynamicHeight, mSquareMap); Runner = new Thread(new ThreadStart(Run)); Runner.Start(); if (mTemplate.ModelName.StartsWith("bb_lobby_")) // lobby! mLobby = new Lobby(this); if (mTemplate.Publicroom_items != string.Empty) { mPathfinder.MinJump = 0.5F; mPathfinder.MaxJump = 0; } } #region Dispose public virtual void Destroy() { Core.RoomManager.RemoveRoom(this); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. if (!this.disposed) { // If disposing equals true, dispose all managed // and unmanaged resources. if (disposing) { // Dispose managed resources. mUsers = null; mLobby = null; mTemplate = null; Runner = null; } // Note disposing has been done. disposed = true; } } ~Room() { Dispose(false); } #endregion public virtual void Run() { int sSleepTime = Core.Config.GetInt("game.room.run.sleep"); while (!disposed) { Response Response = new Response(34); // "@b" try { foreach (RoomUser sUser in mUsers.Values) { if (!sUser.mIsWalking && !sUser.mStatusUpdated) // No update continue; if (sUser.mStatusUpdated && !sUser.mIsWalking) { sUser.mStatusUpdated = false; Response.AppendString(sUser.ToStatusString(), 13); continue; } byte[] sNextPosition = mPathfinder.Path(sUser.mX, sUser.mY, sUser.mWalkingX, sUser.mWalkingY); //byte[] sNextPosition = AWAPathfinder.GetNext(sUser.mX, sUser.mY, sUser.mWalkingX, sUser.mWalkingY, mSquareMap); if (sNextPosition.Length == 0) { sUser.mIsWalking = false; sUser.RemoveStatus("mv", false); if (mSquareMap[sUser.mX, sUser.mY] == SquareState.Chair) sUser.AddStatus("sit", mTemplate.mDynamicHeight[sUser.mX, sUser.mY], false); else if (mSquareMap[sUser.mX, sUser.mY] == SquareState.Bed) sUser.AddStatus("lay", mTemplate.mDynamicHeight[sUser.mX, sUser.mY], false); CheckTrigger(sUser); Response.AppendString(sUser.ToStatusString(), 13); continue; } if (mSquareMap[sNextPosition[0], sNextPosition[1]] == SquareState.Closed) System.Console.WriteLine("Pathfinder sucks :("); // Set some variables mDynamicHeightmap[sUser.mX, sUser.mY] = 1; // old open mDynamicHeightmap[sNextPosition[0], sNextPosition[1]] = 0; // new closed sUser.mBodyRotation = Rotation.Calculate(sUser.mX, sUser.mY, sNextPosition[0], sNextPosition[1]); sUser.mHeadRotation = sUser.mBodyRotation; // Send movement-packet sUser.RemoveStatus("sit", false); sUser.RemoveStatus("lay", false); sUser.AddStatus("mv", sNextPosition[0] + "," + sNextPosition[1] + "," + mTemplate.mDynamicHeight[sNextPosition[0], sNextPosition[1]], false); Response.AppendString(sUser.ToStatusString(), 13); // Set position sUser.mX = sNextPosition[0]; sUser.mY = sNextPosition[1]; sUser.mHeight = mTemplate.mDynamicHeight[sNextPosition[0], sNextPosition[1]]; } } catch (InvalidOperationException) { } // Not really dangerous catch (Exception x) { System.Console.WriteLine(x); } if (Response.HasContent()) SendMessage(Response); Thread.Sleep(sSleepTime); } } public void CheckTrigger(RoomUser pUser) { RoomTrigger trigger = mTriggers[pUser.mX, pUser.mY]; if (trigger == null) return; // Here we make triggers :) if (trigger.mName.StartsWith("curtains")) { pUser.mCanWalk = false; Response message = new Response(96); // "A`" pUser.mClient.SendMessage(message); SendTriggerState(trigger.mName, "close"); } } public void SendTriggerState(string pName, string pState) { Response message = new Response(71); // "AG" message.Append(pName); message.Append(' '); message.Append(pState); SendMessage(message); } public void SendTriggerState(string pName) { Response message = new Response(71); // "AG" message.Append(pName); SendMessage(message); } public Response GetAllStatuses() { Response Response = new Response(34); // "@b" foreach (RoomUser sUser in mUsers.Values) Response.Append(sUser.ToStatusString()); return Response; } public Response GetAllDetails() { Response Response = new Response(28); // "@\" foreach (RoomUser sUser in mUsers.Values) Response.Append(sUser.ToFuseString()); return Response; } public void SendDetails(RoomUser pUser) { if (!ContainsUser(pUser.mClient.mHabbo.mName)) return; Response message = new Response(28); // "@\" message.Append(pUser.ToFuseString()); SendMessage(message); } public void AddUser(RoomUser pRoomUser) { pRoomUser.mClient.mRoom = this; pRoomUser.mDynamicID = GenerateDynamicID(); pRoomUser.mX = mTemplate.Door_x; pRoomUser.mY = mTemplate.Door_y; pRoomUser.mHeight = mTemplate.Door_h; pRoomUser.mBodyRotation = mTemplate.Door_z; pRoomUser.mHeadRotation = mTemplate.Door_z; mUsers.Add(pRoomUser.mDynamicID, pRoomUser); // Send details SendDetails(pRoomUser); //register packets pRoomUser.mClient.RegisterRoom(); pRoomUser.mClient.RegisterCatalogue(); if (Runner == null) // Run void not started yet! Init(); mDynamicHeightmap[pRoomUser.mX, pRoomUser.mY] = 0; // user } public void RemoveUser(RoomUser user) { mDynamicHeightmap[user.mX, user.mY] = 1; // unregister user.mClient.UnRegisterRoom(); user.mClient.UnRegisterCatalogue(); if (mLobby != null && user.mClient.mGame != null && !user.mClient.mGame.mIsStarting) // remove from game user.mClient.mGame.RemoveMember(user.mClient, false, 0); user.mClient.mRoom = null; user.mClient.mRoomUser = null; if (mUsers.Count == 1) // only user left, unload room { Destroy(); return; } mUsers.Remove(user.mDynamicID); Response sMessage = new Response(29); // "@]" sMessage.Append(user.mDynamicID); SendMessage(sMessage); } public int GenerateDynamicID() { int i = 0; while (mUsers.ContainsKey(i)) i++; return i; } public RoomUser GetUser(string pName) { foreach (RoomUser user in mUsers.Values) if (user.mClient.mHabbo.mName == pName) return user; return null; } public RoomUser GetUser(int pDynID) { foreach (RoomUser user in mUsers.Values) if (user.mDynamicID == pDynID) return user; return null; } public bool ContainsUser(string pName) { return GetUser(pName) != null; } public RoomTrigger GetTrigger(byte pX, byte pY) { return mTriggers[pX, pY]; } public void SendMessage(Response pResponse) { foreach (RoomUser sUser in mUsers.Values) sUser.mClient.mHabbo.mClient.SendMessage(pResponse); } public void SendMessage(Response pResponse, byte pMinRank) { foreach (RoomUser sUser in mUsers.Values) if (sUser.mClient.mHabbo.mRank >= pMinRank) sUser.mClient.SendMessage(pResponse); } public void SendMessageToRights(Response pResponse) { foreach (RoomUser sUser in mUsers.Values) if (sUser.mHasRights || sUser.mIsOwner) sUser.mClient.SendMessage(pResponse); } public void Chat(RoomUser pUser, string pMessage) { Response sMessage = new Response(24); // "@X" sMessage.AppendWired(pUser.mDynamicID); sMessage.AppendString(pMessage); // TODO: scramble if far away SendMessage(sMessage); } public void Shout(RoomUser pUser, string pMessage) { Response sMessage = new Response(26); // "@Z" sMessage.AppendWired(pUser.mDynamicID); sMessage.AppendString(pMessage); SendMessage(sMessage); } public void Whisper(RoomUser pUser, string pReceiverName, string pMessage) { if (!ContainsUser(pReceiverName)) return; Response sMessage = new Response(25); // "@Y" sMessage.AppendWired(pUser.mDynamicID); sMessage.AppendString(pMessage); pUser.mClient.SendMessage(sMessage); if (pReceiverName != pUser.mClient.mHabbo.mName) // avoid sending double chat message GetUser(pReceiverName).mClient.SendMessage(sMessage); } } }