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; 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 (!_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) //{ //ResponseBuilder Response = new ResponseBuilder(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; ResponseBuilder message = new ResponseBuilder(96); // "A`" pUser.mClient.SendMessage(message); SendTriggerState(trigger.mName, "close"); } } public void SendTriggerState(string pName, string pState) { ResponseBuilder message = new ResponseBuilder(71); // "AG" message.Append(pName); message.Append(' '); message.Append(pState); SendMessage(message); } public void SendTriggerState(string pName) { ResponseBuilder message = new ResponseBuilder(71); // "AG" message.Append(pName); SendMessage(message); } public ResponseBuilder GetAllStatuses() { ResponseBuilder Response = new ResponseBuilder(34); // "@b" //foreach (RoomUser sUser in mUsers.Values) // Response.Append(sUser.ToStatusString()); return Response; } public ResponseBuilder GetAllDetails() { ResponseBuilder Response = new ResponseBuilder(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; //ResponseBuilder message = new ResponseBuilder(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 (mPathfinder == 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); ResponseBuilder sMessage = new ResponseBuilder(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(ResponseBuilder pResponse) { foreach (RoomUser sUser in mUsers.Values) sUser.mClient.mHabbo.mClient.SendMessage(pResponse); } public void SendMessage(ResponseBuilder pResponse, byte pMinRank) { foreach (RoomUser sUser in mUsers.Values) if (sUser.mClient.mHabbo.mRank >= pMinRank) sUser.mClient.SendMessage(pResponse); } public void SendMessageToRights(ResponseBuilder pResponse) { foreach (RoomUser sUser in mUsers.Values) if (sUser.mHasRights || sUser.mIsOwner) sUser.mClient.SendMessage(pResponse); } public void Chat(RoomUser pUser, string pMessage) { ResponseBuilder sMessage = new ResponseBuilder(24); // "@X" sMessage.AppendInt32(pUser.mDynamicID); sMessage.AppendString(pMessage); // TODO: scramble if far away SendMessage(sMessage); } public void Shout(RoomUser pUser, string pMessage) { ResponseBuilder sMessage = new ResponseBuilder(26); // "@Z" sMessage.AppendInt32(pUser.mDynamicID); sMessage.AppendString(pMessage); SendMessage(sMessage); } public void Whisper(RoomUser pUser, string pReceiverName, string pMessage) { if (!ContainsUser(pReceiverName)) return; ResponseBuilder sMessage = new ResponseBuilder(25); // "@Y" sMessage.AppendInt32(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); } } }