void Upload(Player p, string modelName, string url) { var bytes = HttpUtil.DownloadData(url, p); if (bytes != null) { string json = System.Text.Encoding.UTF8.GetString(bytes); // try parsing now so that we throw and don't save the invalid file // and notify the user of the error if (!BlockBench.IsValid(json, p, modelName)) { return; } // override filename because file might not exist yet var storedModel = new StoredCustomModel(modelName, true); storedModel.WriteBBFile(json); if (!storedModel.Exists()) { // create a default ccmodel file if doesn't exist storedModel.WriteToFile(); } CheckUpdateAll(storedModel); p.Message( "%TCustom Model %S{0} %Tupdated!", modelName ); } }
static void OnPlayerCommand(Player p, string cmd, string args, CommandData data) { if (cmd.CaselessEq("skin") && Hacks.CanUseHacks(p)) { var splitArgs = args.Trim().Length == 0 ? new string[] { } : args.SplitSpaces(); if (splitArgs.Length == 0) { // check if we should use default skin var storedModel = new StoredCustomModel(p.Model); if (storedModel.Exists()) { storedModel.LoadFromFile(); if ( !storedModel.usesHumanSkin && storedModel.defaultSkin != null ) { Debug("Setting {0} to defaultSkin {1}", p.name, storedModel.defaultSkin); Command.Find("Skin").Use( p, "-own " + storedModel.defaultSkin, data ); p.cancelcommand = true; } } else if (splitArgs.Length > 0) { var last = splitArgs[splitArgs.Length - 1]; MemoizedGetSkinType.Invalidate(last); } } } }
List <string> GetModels(string playerName, Player p) { var folderPath = playerName == null ? PublicModelsDirectory : StoredCustomModel.GetFolderPath(playerName); if (playerName != null && !Directory.Exists(folderPath)) { p.Message("%WPlayer %S{0} %Whas not created any models.", GetNameWithoutPlus(playerName)); return(null); } var modelNames = new List <string>(); foreach (var entry in new DirectoryInfo(folderPath).GetFiles()) { string fileName = entry.Name; if (Path.GetExtension(fileName).CaselessEq(CCModelExt)) { string name = Path.GetFileNameWithoutExtension(fileName); modelNames.Add(name); } } return(modelNames); }
private string TargetModelName(Player p, CommandData data, string arg, bool checkPerms = true) { string playerNameWithPlus = GetNameWithPlus(p.name); if (arg.CaselessEq("-own")) { arg = playerNameWithPlus; } if (!ValidModelName(p, arg)) { return(null); } if (checkPerms) { string maybePlayerName = StoredCustomModel.GetPlayerName(arg); bool targettingSelf = maybePlayerName != null && maybePlayerName.CaselessEq(playerNameWithPlus); // if you aren't targetting your own models, // and you aren't admin, denied if (!targettingSelf && !CheckExtraPerm(p, data, 1)) { return(null); } } return(Path.GetFileName(arg)); }
void Delete(Player p, string modelName) { StoredCustomModel storedCustomModel = new StoredCustomModel(modelName, true); if (!storedCustomModel.Exists()) { p.Message("%WCustom Model %S{0} %Wnot found!", modelName); return; } storedCustomModel.Delete(); p.Message("%TCustom Model %S{0} %Wdeleted!", modelName); }
static void CheckRemoveModel(Player p, string modelName) { lock (SentCustomModels) { var sentModels = SentCustomModels[p.name]; if (sentModels.Contains(modelName)) { var storedModel = new StoredCustomModel(modelName); if (storedModel.Exists()) { storedModel.Undefine(p); sentModels.Remove(modelName); } } } }
static int CheckFolder(string folderPath) { // make sure all cc files are lowercased foreach (var entry in new DirectoryInfo(folderPath).GetFiles()) { string fileName = entry.Name; if (fileName != fileName.ToLower()) { RenameFile(folderPath, fileName, fileName.ToLower()); } } int count = 0; foreach (var entry in new DirectoryInfo(folderPath).GetFiles()) { string fileName = entry.Name; if (fileName != fileName.ToLower()) { RenameFile(folderPath, fileName, fileName.ToLower()); fileName = fileName.ToLower(); } string modelName = Path.GetFileNameWithoutExtension(fileName); string extension = Path.GetExtension(fileName); if (!extension.CaselessEq(BBModelExt)) { continue; } count += 1; var defaultModel = new StoredCustomModel(modelName, true); if (!defaultModel.Exists()) { defaultModel.WriteToFile(); Logger.Log( LogType.SystemActivity, "CustomModels: Created a new default template for \"{0}\" in {1}", modelName + CCModelExt, folderPath ); } } return(count); }
static void CheckSendModel(Player p, string modelName) { lock (SentCustomModels) { var sentModels = SentCustomModels[p.name]; if (!sentModels.Contains(modelName)) { var storedModel = new StoredCustomModel(modelName); if (storedModel.Exists()) { storedModel.LoadFromFile(); storedModel.Define(p); sentModels.Add(modelName); } } } }
public void LoadFromFile() { string path = GetCCPath(); string contentsCC = File.ReadAllText(path); StoredCustomModel o = JsonConvert.DeserializeObject <StoredCustomModel>(contentsCC, jsonSettings); this.nameY = o.nameY; this.autoNameY = o.autoNameY; this.eyeY = o.eyeY; this.collisionBounds = o.collisionBounds; this.pickingBoundsMin = o.pickingBoundsMin; this.pickingBoundsMax = o.pickingBoundsMax; this.bobbing = o.bobbing; this.pushes = o.pushes; this.usesHumanSkin = o.usesHumanSkin; this.calcHumanAnims = o.calcHumanAnims; this.defaultSkin = o.defaultSkin; }
static void UpdateModelForSkinType(Entity e, SkinType skinType) { var storedModel = new StoredCustomModel(e.Model); var oldModelName = storedModel.GetFullNameWithScale(); storedModel.ApplySkinType(skinType); var newModelName = storedModel.GetFullNameWithScale(); if (!oldModelName.CaselessEq(newModelName)) { Debug("UPDATE MODEL {0} -> {1}", oldModelName, newModelName); e.UpdateModel(newModelName); } else { Debug("already {0}", newModelName); } }
void Wear(Player p, string modelName, CommandData data) { // check if we should use default skin var storedCustomModel = new StoredCustomModel(modelName); if (!storedCustomModel.Exists()) { p.Message("%WCustom Model %S{0} %Wnot found!", modelName); return; } p.HandleCommand("XModel", modelName, data); storedCustomModel.LoadFromFile(); if ( !storedCustomModel.usesHumanSkin && storedCustomModel.defaultSkin != null ) { p.HandleCommand("Skin", "-own " + storedCustomModel.defaultSkin, data); } }
public override void Help(Player p, string message) { if (message.Trim() != "") { var args = new List <string>(message.SplitSpaces()); if (args.Count >= 1) { string subCommand = args.PopFront(); if (subCommand.CaselessEq("config") || subCommand.CaselessEq("edit")) { var defaultStoredCustomModel = new StoredCustomModel("default"); foreach (var entry in ModifiableFields) { var fieldName = entry.Key; var modelField = entry.Value; if (!modelField.CanEdit(p)) { continue; } p.Message( "%Tconfig {0} {1}", fieldName, "[" + modelField.types.Join("] [") + "]" ); p.Message( "%H {0} %S(Default %T{1}%S)", modelField.desc, modelField.get.Invoke(defaultStoredCustomModel) ); } return; } } } Help(p); }
void SitCute(Player p, CommandData data) { var storedModel = new StoredCustomModel(p.Model); if (!storedModel.Exists()) { p.Message("%WYour current model isn't a Custom Model!"); return; } // allow going from sit -> sitcute storedModel.RemoveModifier("sit"); if (storedModel.modifiers.Contains("sitcute")) { storedModel.RemoveModifier("sitcute"); } else { storedModel.AddModifier("sitcute"); } p.HandleCommand("XModel", storedModel.GetFullNameWithScale(), data); }
void Goto(Player p, string playerName = null, ushort page = 0) { bool all = false; if (playerName != null) { playerName = playerName.ToLower(); if (playerName == "all") { all = true; } else if (playerName == "public") { playerName = null; } else { playerName = StoredCustomModel.GetPlayerName(playerName) ?? StoredCustomModel.GetPlayerName(playerName + "+"); } } List <string> modelNames; if (all) { var dict = GetAllModels(p); modelNames = dict // public ones first .OrderByDescending(pair => pair.Key == "Public") // then by player name A-Z .ThenBy(pair => pair.Key) .Select(pair => pair.Value) .SelectMany(x => x) .ToList(); } else { modelNames = GetModels(playerName, p); } if (modelNames == null) { return; } // - 1 for our self player var partitionSize = Packet.MaxCustomModels - 1; var partitions = modelNames.Partition(partitionSize).ToList(); if (page >= partitions.Count) { p.Message( "%WPage doesn't exist" ); return; } var total = modelNames.Count; modelNames = partitions[page]; p.Message( "%HViewing %T{0} %Hmodels{1}", total, partitions.Count > 1 ? string.Format( " %S(page %T{0}%S/%T{1}%S)", page + 1, partitions.Count ) : "" ); if (partitions.Count > 1 && page < (partitions.Count - 1)) { p.Message( "%SUse \"%H/cm goto {0} {1}%S\" to go to the next page", playerName, page + 2 ); } var mapName = string.Format( "&f{0} Custom Models{1}", all ? "All" : ( playerName == null ? "Public" : GetNameWithoutPlus(playerName) + "'s" ), page != 0 ? string.Format(" ({0})", page + 1) : "" ); ushort spacing = 4; ushort width = (ushort)( // edges (spacing * 2) + // grass blocks modelNames.Count + // inbetween blocks ((modelNames.Count - 1) * (spacing - 1)) ); ushort height = 1; ushort length = 16; byte[] blocks = new byte[width * height * length]; Level lvl = new Level(mapName, width, height, length, blocks); for (int i = 0; i < blocks.Length; i++) { blocks[i] = 1; } lvl.SaveChanges = false; lvl.ChangedSinceBackup = false; lvl.IsMuseum = true; lvl.BuildAccess.Min = LevelPermission.Nobody; lvl.Config.Physics = 0; lvl.spawnx = spacing; lvl.spawny = 2; lvl.Config.HorizonBlock = 1; lvl.Config.EdgeLevel = 1; lvl.Config.CloudsHeight = -0xFFFFFF; lvl.Config.SidesOffset = 0; lvl.Config.Buildable = false; lvl.Config.Deletable = false; for (ushort i = 0; i < modelNames.Count; i++) { ushort x = (ushort)(spacing + (i * spacing)); ushort y = 0; ushort z = spacing; blocks[lvl.PosToInt(x, y, z)] = 2; var modelName = modelNames[i]; var storedModel = new StoredCustomModel(modelName); if (storedModel.Exists()) { storedModel.LoadFromFile(); } var skinName = p.SkinName; if ( !storedModel.usesHumanSkin && storedModel.defaultSkin != null ) { skinName = storedModel.defaultSkin; } // hack because clients strip + at the end var botName = "&f" + (modelName.EndsWith("+") ? modelName + "&0+" : modelName); var bot = new PlayerBot(botName, lvl) { id = (byte)i, Model = modelName, SkinName = skinName, }; bot.SetInitialPos(Position.FromFeetBlockCoords(x, y + 1, z)); bot.SetYawPitch(Orientation.DegreesToPacked(180), Orientation.DegreesToPacked(0)); bot.ClickedOnText = "/CustomModel wear " + modelName; _ = lvl.Bots.Add(bot); } if (!PlayerActions.ChangeMap(p, lvl)) { return; } }
void List(Player p, string playerName = null, string query = null) { bool all = false; if (playerName != null) { playerName = playerName.ToLower(); if (playerName == "all" || playerName == "count") { all = true; } else if (playerName == "public") { playerName = null; } else { playerName = StoredCustomModel.GetPlayerName(playerName) ?? StoredCustomModel.GetPlayerName(playerName + "+"); } } if (query != null) { query = query.ToLower(); } if (all) { var dict = GetAllModels(p); if (dict == null) { return; } if (query == null) { p.Message("%TAll %SCustom Models"); foreach (var pair in dict.OrderByDescending(pair => pair.Value.Count)) { p.Message(" %T{0,3}%S: %T{1}", pair.Value.Count, pair.Key); } } else { var modelNames = new List <string>(); foreach (var pair in dict) { modelNames.AddRange( pair.Value.Where( (name) => name.Contains(query) ) ); } p.Message( "%SSearching %TAll %SCustom Models: %T{0}", modelNames.Join("%S, %T") ); } } else { var modelNames = GetModels(playerName, p); if (modelNames == null) { return; } if (query == null) { p.Message( "%T{0} %SCustom Models: %T{1}", playerName == null ? "Public" : GetNameWithoutPlus(playerName) + "%S's", modelNames.Join("%S, %T") ); } else { p.Message( "%SSearching %T{0} %SCustom Models: %T{1}", playerName == null ? "Public" : GetNameWithoutPlus(playerName) + "%S's", modelNames.Where( (name) => name.Contains(query) ).Join("%S, %T") ); } } }
public static bool IsValid(string json, Player p, string modelName) { var jsonRoot = Parse(json); var parts = jsonRoot.ToParts(); if (!jsonRoot.IsValid(p)) { return(false); } if (parts.Length > Packet.MaxCustomModelParts) { p.Message( "%WNumber of model parts ({0}) exceeds max of {1}!", parts.Length, Packet.MaxCustomModelParts ); return(false); } // only do size check if they can't upload global models if (!CommandExtraPerms.Find("CustomModel", 1).UsableBy(p.Rank)) { for (int i = 0; i < parts.Length; i++) { // Models can be 1 block bigger if they aren't a purely personal model bool purePersonal = new StoredCustomModel(modelName).IsPersonalPrimary(); float graceLength = purePersonal ? 8.0f : 16.0f; if ( !SizeAllowed(parts[i].min, graceLength) || !SizeAllowed(parts[i].max, graceLength) ) { p.Message( "%WThe %b{0} cube in your list %Wis out of bounds.", ListicleNumber(i + 1) ); p.Message( "%WYour {0} may not be larger than %b{1}%W pixels tall or %b{2}%W pixels wide.", purePersonal ? "personal model" : "model", maxHeight + graceLength, maxWidth + (graceLength * 2), graceLength ); if (purePersonal) { p.Message("These limits only apply to your personal \"%b{0}%S\" model.", modelName); p.Message("Models you upload with other names (e.g, /cm {0}bike upload) can be slightly larger.", modelName); } return(false); } } } for (int i = 0; i < parts.Length; i++) { var part = parts[i]; if (part.anims.Length > Packet.MaxCustomModelAnims) { p.Message( "%WThe %b{0} cube in your list %Whas more than %b{1} %Wanimations.", ListicleNumber(i + 1), Packet.MaxCustomModelAnims ); break; } } return(true); }
static void CheckUpdateAll(StoredCustomModel storedCustomModel) { // re-define the model and do ChangeModel for each entity currently using this model // remove this model from everyone's sent list foreach (Player p in PlayerInfo.Online.Items) { lock (SentCustomModels) { var sentModels = SentCustomModels[p.name]; foreach (var modelName in sentModels.ToArray()) { if (storedCustomModel.GetModelFileName().CaselessEq(new StoredCustomModel(modelName).GetModelFileName())) { Debug("CheckUpdateAll remove {0} from {1}", modelName, p.name); CheckRemoveModel(p, modelName); } } } } // add this model back to players who see entities using it foreach (Player p in PlayerInfo.Online.Items) { CheckAddRemove(p, p.level); } void checkEntity(Entity e) { if (new StoredCustomModel(e.Model).Exists()) { e.UpdateModel(e.Model); } } // do ChangeModel on every entity with this model // so that we update the model on the client var loadedLevels = new Dictionary <string, Level>(StringComparer.OrdinalIgnoreCase); foreach (Player p in PlayerInfo.Online.Items) { checkEntity(p); if (p.Extras.TryGet("TempBot_BotList", out object obj)) { if (obj != null) { List <PlayerBot> botList = (List <PlayerBot>)obj; foreach (var bot in botList) { checkEntity(bot); } } } if (!loadedLevels.ContainsKey(p.level.name)) { loadedLevels.Add(p.level.name, p.level); } } foreach (var entry in loadedLevels) { var level = entry.Value; foreach (PlayerBot e in level.Bots.Items) { checkEntity(e); } } }
// Called when model is being sent to a player. static void OnSendingModel(Entity e, ref string modelName, Player dst) { if (e.Model.StartsWith("$")) { // don't run if $model return; } Debug("OnSendingModel {0}: {1}", dst.name, modelName); var storedModel = new StoredCustomModel(modelName); if (storedModel.Exists() && storedModel.UsesHumanParts()) { // if this is a custom model and it uses human parts, // check if we need to skin transform var skinName = e.SkinName; if (MemoizedGetSkinType.GetCached(skinName, out SkinType skinType)) { var oldModelName = storedModel.GetFullNameWithScale(); storedModel.ApplySkinType(skinType); var newModelName = storedModel.GetFullNameWithScale(); if (!oldModelName.CaselessEq(newModelName)) { Debug("OVERRIDE MODEL {0} -> {1}", oldModelName, newModelName); modelName = newModelName; e.SetModel(newModelName); } else { Debug("already {0}", newModelName); } } else { // spawn long task lock (GetSkinTypeTasks) { GetSkinTypeTasks.AddOrUpdate( e, (e2) => { return(SpawnGetSkinType(e2)); }, (e2, oldValue) => { Debug("cancelling {0}", e2.SkinName); oldValue.cancelSource.Cancel(); return(SpawnGetSkinType(e2)); } ); } } } // make sure the model is already defined for player // before we send the ChangeModel packet // // also check if we should remove unused old model CheckAddRemove(dst, dst.level); // // check if we should use default skin // if ( // e == dst && // ( // // unset skin // dst.SkinName == dst.truename || // // or some other unsaved skin // !Server.skins.Contains(dst.name) // ) && // storedModel.Exists() // ) { // } }
void Config(Player p, string modelName, List <string> args) { StoredCustomModel storedCustomModel = new StoredCustomModel(modelName, true); if (!storedCustomModel.Exists()) { p.Message("%WCustom Model %S{0} %Wnot found!", modelName); return; } storedCustomModel.LoadFromFile(); if (args.Count == 0) { // /CustomModel [name] config foreach (var entry in ModifiableFields) { var fieldName = entry.Key; var modelField = entry.Value; if (!modelField.CanEdit(p, modelName)) { continue; } p.Message( "{0} = %T{1}", fieldName, modelField.get.Invoke(storedCustomModel) ); } return; } if (args.Count >= 1) { // /CustomModel [name] config [field] // or // /CustomModel [name] config [field] [value] var fieldName = args.PopFront(); if (!ModifiableFields.ContainsKey(fieldName)) { p.Message( "%WNo such field %S{0}!", fieldName ); return; } var modelField = ModifiableFields[fieldName]; if (args.Count == 0) { // /CustomModel [name] config [field] p.Message( "{0} = %T{1}", fieldName, modelField.get.Invoke(storedCustomModel) ); return; } else { // /CustomModel config [field] [value]... var values = args.ToArray(); if (values.Length != modelField.types.Length) { p.Message( "%WNot enough values for setting field %S{0}", fieldName ); } else { if (!modelField.CanEdit(p, modelName)) { p.Message("%WYou can't edit this field on a primary personal model!"); return; } if (modelField.set.Invoke(storedCustomModel, p, values)) { // field was set, update file! p.Message("%TField %S{0} %Tset!", fieldName); storedCustomModel.WriteToFile(); CheckUpdateAll(storedCustomModel); } } } } }