/* Thor Server Project Copyright 2008 Joe Hegarty This file is part of The Thor Server Project. The Thor Server Project is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The Thor Server Project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with The Thor Server Project. If not, see . */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Threading; using ThorServer.Utilities; using ThorServer.Core; using ThorServer.Game.Rooms.Reactors; using ThorServer.Game.Rooms.Interactor; namespace ThorServer.Game.Rooms { public partial class RoomInstance { private int mRoomID; private RoomInfo mRoomInfo; private RoomInteractor mRoomInteractor; private Dictionary mRoomUsers; private Dictionary mMemberSessions; public List mRoomUserIDs; public Dictionary mDoorEntries; public int UserCount { get { return mRoomUsers.Count; } } public string UserList { get { StringBuilder sb = new StringBuilder(); foreach (RoomUser roomUser in mRoomUsers.Values) { sb.Append(roomUser.UserInfo.sUsername); sb.Append(Convert.ToChar(2)); } return sb.ToString(); } } public RoomInstance(int roomID) { mRoomID = roomID; mRoomInfo = InstanceManager.Game.Rooms.GetRoom(roomID); LoadReactor(mRoomInfo.ReactorType); mMemberSessions = new Dictionary(); mRoomUsers = new Dictionary(); mRoomUserIDs = new List(); mRoomInteractor = new RoomInteractor(mRoomID, this); mDoorEntries = new Dictionary(); if (RoomInfo.ReactorType == "LidoReactor" || RoomInfo.ReactorType == "RooftopReactor") Interactor.mHasPoolCam = true; } public bool BroadcastRingingUser(string userName) { mMessage.Init(91); // A[ mMessage.appendString(userName); return RoomRightsBroadcast(mMessage); } public void DestroyRoom() { mRoomInteractor.DestroyInteractor(); mRoomInteractor = null; } private RoomCommonReactor LoadReactor(string reactorName) { RoomCommonReactor reactor = (RoomCommonReactor)Activator.CreateInstance(null, "ThorServer.Game.Rooms.Reactors." + reactorName).Unwrap(); reactor.RegisterInstance(this); return reactor; } public Dictionary Users { get { return mRoomUsers; } } public RoomUser GetUser(long sessionID) { if (mRoomUsers.ContainsKey(sessionID)) { return mRoomUsers[sessionID]; } else { return null; } } public RoomUser GetUser(string username) { Dictionary.Enumerator myEnum = mRoomUsers.GetEnumerator(); while (myEnum.MoveNext()) { if (myEnum.Current.Value.UserInfo.sUsername == username) { return myEnum.Current.Value; } } return null; } public RoomUser GetUser(int x, int y) { Dictionary.Enumerator myEnum = mRoomUsers.GetEnumerator(); while (myEnum.MoveNext()) { if (myEnum.Current.Value.CurrentX == x && myEnum.Current.Value.CurrentY == y) { return myEnum.Current.Value; } } return null; } public RoomUser GetUser(int roomUserId) { Dictionary.Enumerator myEnum = mRoomUsers.GetEnumerator(); while (myEnum.MoveNext()) { if (myEnum.Current.Value.RoomUserID == roomUserId) { return myEnum.Current.Value; } } return null; } private int AllocateID() { int i = 0; while (true) { if (!mRoomUserIDs.Contains(i)) { mRoomUserIDs.Add(i); return i; } i++; } } public bool AddUser(long sessionID) { RoomCommonReactor reactor = LoadReactor(RoomInfo.ReactorType); int listenerId = InstanceManager.Sessions.GetSession(sessionID).AddListener(reactor.GetType(), reactor); mMemberSessions.Add(sessionID, listenerId); InstanceManager.Sessions.GetSession(sessionID).mRoomID = mRoomID; Logging.LogEvent("User " + sessionID.ToString() + " entered room " + mRoomID.ToString(), Logging.LogLevel.Debug); return true; } public void RemoveUser(long sessionID) { InstanceManager.Sessions.GetSession(sessionID).mRoomID = 0; if (mMemberSessions.ContainsKey(sessionID)) { InstanceManager.Sessions.GetSession(sessionID).RemoveListener(mMemberSessions[sessionID]); mMemberSessions.Remove(sessionID); } if (mRoomUsers.ContainsKey(sessionID)) { mRoomInteractor.RemoveTileStatus(mRoomUsers[sessionID], mRoomUsers[sessionID].CurrentX, mRoomUsers[sessionID].CurrentY); mRoomInteractor.FreeTile(mRoomUsers[sessionID].CurrentX, mRoomUsers[sessionID].CurrentY); mMessage.Init(29); //@] mMessage.appendInt(mRoomUsers[sessionID].RoomUserID); RoomBroadcast(mMessage); mRoomUserIDs.Remove(mRoomUsers[sessionID].RoomUserID); mRoomUsers.Remove(sessionID); } Logging.LogEvent("User " + sessionID.ToString() + " left room " + mRoomID.ToString(), Logging.LogLevel.Debug); InstanceManager.Game.Rooms.UpdateUsers(mRoomInfo.RoomID, mRoomUsers.Count); if (UserCount == 0) { InstanceManager.Game.Rooms.DestroyRoomInstance(mRoomID); } } public void ActivateUser(long sessionID) { RoomUser newUser = new RoomUser(); newUser.RoomUserID = AllocateID(); newUser.SessionID = sessionID; if (!mDoorEntries.ContainsKey(sessionID)) { newUser.CurrentX = mRoomInfo.StartX; newUser.CurrentY = mRoomInfo.StartY; newUser.CurrentZ = mRoomInfo.StartZ; } else { Furni.FurniInfo teleporter = InstanceManager.Game.Furni.GetFurni(mDoorEntries[sessionID]); newUser.CurrentX = teleporter.PosX; newUser.CurrentY = teleporter.PosY; newUser.CurrentZ = teleporter.PosZ; } mRoomUsers.Add(sessionID, newUser); AnnounceUser(sessionID); if (mDoorEntries.ContainsKey(sessionID)) { Furni.FurniInfo teleporter = InstanceManager.Game.Furni.GetFurni(mDoorEntries[sessionID]); mMessage.Init(92); //A\ mMessage.appendInt(teleporter.FurniID); mMessage.appendString("/"); mMessage.appendString(newUser.UserInfo.sUsername); mMessage.appendString("/"); mMessage.appendString(teleporter.FurniSprite); RoomBroadcast(mMessage); mDoorEntries.Remove(sessionID); } CalculateRights(ref newUser, sessionID); //Send all the user statuses foreach (RoomUser roomUser in mRoomUsers.Values) { SendUserStatus(roomUser.SessionID, true, newUser.SessionID); } InstanceManager.Game.Rooms.UpdateUsers(mRoomInfo.RoomID, mRoomUsers.Count); } public void CalculateRights(ref RoomUser newUser, long sessionID) { newUser.HasAdmin = false; newUser.HasRights = false; if (newUser.SpecialStates.ContainsKey("flatctrl")) { newUser.SpecialStates.Remove("flatctrl"); } if (newUser.UserInfo.userId == RoomInfo.RoomOwner) { newUser.HasAdmin = true; newUser.HasRights = true; } if (InstanceManager.Game.Roles.HasRight(newUser.UserInfo.iRole, "fuse_any_room_controller")) { newUser.HasAdmin = true; newUser.HasRights = true; } if (InstanceManager.Game.Roles.HasRight(newUser.UserInfo.iRole, "fuse_any_room_rights")) newUser.HasRights = true; if (InstanceManager.Game.Rooms.HasRights(mRoomInfo.RoomID, newUser.UserInfo.userId)) newUser.HasRights = true; //Owner Check if (newUser.HasAdmin || newUser.HasRights) { mMessage.Init(42); //@j SendMessage(mMessage, sessionID); if (newUser.HasAdmin) { mMessage.Init(47); //@o SendMessage(mMessage, sessionID); } newUser.SpecialStates.Add("flatctrl", new RoomUser.RoomUserStatus("flatctrl", true, "useradmin", 0, 0, 0, null, true)); } if (!newUser.HasRights) { if (mRoomInfo.SuperUsers > 0) newUser.HasRights = true; // Superusers if (newUser.HasRights && !newUser.HasAdmin) { mMessage.Init(42); //@j SendMessage(mMessage, sessionID); newUser.SpecialStates.Add("flatctrl", new RoomUser.RoomUserStatus("flatctrl", true, "onlyfurniture", 0, 0, 0, null, true)); } } newUser.MustUpdate = true; } public RoomInfo RoomInfo { get { return mRoomInfo; } set { mRoomInfo = value; } } public bool RoomRightsBroadcast(ClientMessage message) { Logging.LogEvent("Rights broadcasting to room " + mRoomID.ToString() + ": " + message.ToString(), Logging.LogLevel.Debug); return RoomRightsBroadcast(message.ToString()); } public bool RoomRightsBroadcast(string message) { bool doneOne = false; foreach (int sessionId in mMemberSessions.Keys) { if (mRoomUsers[sessionId].HasRights || mRoomUsers[sessionId].HasAdmin) { InstanceManager.Sessions.GetSession(sessionId).SendMessage(message, false); doneOne = true; } } return doneOne; } public delegate void RoomDelayBroadcastDelegate(ClientMessage message, int milli); public void RoomDelayBroadcast(ClientMessage message, int milli) { Thread.Sleep(milli); RoomBroadcast(message); } public void RoomBroadcast(ClientMessage message) { Logging.LogEvent("Broadcasting to room " + mRoomID.ToString() + ": " + message.ToString(), Logging.LogLevel.Debug); RoomBroadcast(message.ToString()); } public void RoomBroadcast(string message) { foreach (int sessionId in mMemberSessions.Keys) { InstanceManager.Sessions.GetSession(sessionId).SendMessage(message, false); } } public void RoomTalkBroadcast(int sourceX, int sourceY, string chat, int roomUser) { Logging.LogEvent("Chatting to room " + mRoomID.ToString() + ": " + chat, Logging.LogLevel.Debug); foreach (int sessionId in mMemberSessions.Keys) { if (mRoomUsers.ContainsKey(sessionId)) { string currentChat = chat; int xDistance = Math.Abs(sourceX - mRoomUsers[sessionId].CurrentX); int yDistance = Math.Abs(sourceY - mRoomUsers[sessionId].CurrentY); if (xDistance >= 6 || yDistance >= 6) //Garble text { for (int i = 0; i < chat.Length; i++) { if (SpecialMath.RandomNumber(0, 10) > 5 && chat[i] != ' ') currentChat = currentChat.Replace(chat[i], '.'); } } if (xDistance < 9 && yDistance < 9) // User can at least partially hear { mMessage.Init(24); //@X mMessage.appendString(ArgumentEncoding.encodeInt(roomUser)); mMessage.appendString(currentChat); mMessage.appendChar(2); InstanceManager.Sessions.GetSession(sessionId).SendMessage(mMessage.ToString(), false); } } } } public void SendMessage(ClientMessage message, long sessionId) { SendMessage(message.ToString(), sessionId); } public void SendMessage(string message, long sessionId) { InstanceManager.Sessions.GetSession(sessionId).SendMessage(message); } public RoomInteractor Interactor { get { return mRoomInteractor; } } } }