/// <summary> Renames the given map and associated metadata. Does not unload. </summary> /// <remarks> Backups are NOT renamed. </remarks> public static bool Rename(Player p, string src, string dst) { if (LevelInfo.MapExists(dst)) { p.Message("&WLevel \"{0}\" already exists.", dst); return(false); } Level lvl = LevelInfo.FindExact(src); if (lvl == Server.mainLevel) { p.Message("Cannot rename the main level."); return(false); } List <Player> players = null; if (lvl != null) { players = lvl.getPlayers(); } if (lvl != null && !lvl.Unload()) { p.Message("Unable to rename the level, because it could not be unloaded. " + "A game may currently be running on it."); return(false); } File.Move(LevelInfo.MapPath(src), LevelInfo.MapPath(dst)); DoAll(src, dst, action_move); // TODO: Should we move backups still try { //MoveBackups(src, dst); } catch { } RenameDatabaseTables(p, src, dst); BlockDBFile.MoveBackingFile(src, dst); OnLevelRenamedEvent.Call(src, dst); if (players == null) { return(true); } // Move all the old players to the renamed map Load(p, dst, false); foreach (Player pl in players) { PlayerActions.ChangeMap(pl, dst); } return(true); }
static void OnJoinedLevel(Player p, Level prevLevel, Level level, ref bool announce) { Debug( "OnJoinedLevel {0} {1} -> {2}", p.name, prevLevel != null ? prevLevel.name : "null", level.name ); if (prevLevel != null) { // tell other players still on the last map to remove our model // if we were the last one using that model foreach (Player e in prevLevel.getPlayers()) { if (e == p) { continue; } CheckAddRemove(e, prevLevel); } } }
static void OnPlayerDisconnect(Player p, string reason) { Debug("OnPlayerDisconnect {0}", p.name); SentCustomModels.TryRemove(p.name, out _); ModelNameToIdForPlayer.TryRemove(p.name, out _); Level prevLevel = p.level; if (prevLevel != null) { // tell other players still on the last map to remove our model // if we were the last one using that model foreach (Player e in prevLevel.getPlayers()) { if (e == p) { continue; } CheckAddRemove(e, prevLevel); } } }
// sends all missing models in level to player, // and removes all unused models from player static void CheckAddRemove(Player p, Level level) { Debug("CheckAddRemove {0}", p.name); var visibleModels = new HashSet <string>(StringComparer.OrdinalIgnoreCase) { ModelInfo.GetRawModel(p.Model) }; if (!level.IsMuseum) { foreach (Player e in level.getPlayers()) { visibleModels.Add(ModelInfo.GetRawModel(e.Model)); } } else { visibleModels.Add(ModelInfo.GetRawModel(p.Model)); } foreach (PlayerBot e in level.Bots.Items) { visibleModels.Add(ModelInfo.GetRawModel(e.Model)); } if (p.Extras.TryGet("TempBot_BotList", out object obj)) { if (obj != null) { List <PlayerBot> botList = (List <PlayerBot>)obj; foreach (var bot in botList) { visibleModels.Add(ModelInfo.GetRawModel(bot.Model)); } } } // we must remove old models first before new models so that we have enough CM id's, // but removing first will cause a couple ms of humanoid to be shown before the new model arrives // TODO maybe check if we're about to overflow, and flip order? lock (SentCustomModels) { var sentModels = SentCustomModels[p.name]; // clone so we can modify while we iterate foreach (var modelName in sentModels.ToArray()) { // remove models not found in this level if (!visibleModels.Contains(modelName)) { CheckRemoveModel(p, modelName); } } } // send new models not yet in player's list foreach (var modelName in visibleModels) { CheckSendModel(p, modelName); } }