From 6644e2142505bc818e11a4d020b09e0f5e7b1ea9 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 12 Nov 2017 23:00:14 +1100 Subject: [PATCH] Initial support for per axis entity models. --- MCGalaxy/Bots/BotsFile.cs | 2 +- MCGalaxy/Bots/PlayerBot.cs | 2 +- MCGalaxy/Chat/Colors.cs | 18 +++------------ MCGalaxy/Commands/CommandPerms.cs | 9 -------- MCGalaxy/CorePlugin/MiscHandlers.cs | 2 +- MCGalaxy/Entity/Entities.cs | 27 ++++++++++++++++++----- MCGalaxy/Entity/Entity.cs | 3 ++- MCGalaxy/Levels/Level.Fields.cs | 6 ----- MCGalaxy/Levels/Level.cs | 6 ----- MCGalaxy/Player/Player.Login.cs | 29 ++++++++++++++---------- MCGalaxy/Server/Server.Fields.cs | 2 +- MCGalaxy/Server/Server.Init.cs | 1 + MCGalaxy/util/FastList.cs | 34 ----------------------------- MCGalaxy/util/Math/AABB.cs | 29 ++++++++++++++---------- 14 files changed, 67 insertions(+), 103 deletions(-) diff --git a/MCGalaxy/Bots/BotsFile.cs b/MCGalaxy/Bots/BotsFile.cs index 0d2a221ef..1ce345922 100644 --- a/MCGalaxy/Bots/BotsFile.cs +++ b/MCGalaxy/Bots/BotsFile.cs @@ -44,7 +44,7 @@ namespace MCGalaxy.Bots { PlayerBot bot = new PlayerBot(props.Name, lvl); props.ApplyTo(bot); - bot.ModelBB = AABB.ModelAABB(bot.Model, lvl); + bot.ModelBB = AABB.ModelAABB(bot, lvl); LoadAi(props, bot); PlayerBot.Add(bot, false); } diff --git a/MCGalaxy/Bots/PlayerBot.cs b/MCGalaxy/Bots/PlayerBot.cs index 2671404d1..93706f4ac 100644 --- a/MCGalaxy/Bots/PlayerBot.cs +++ b/MCGalaxy/Bots/PlayerBot.cs @@ -49,7 +49,7 @@ namespace MCGalaxy { public PlayerBot(string n, Level lvl) { name = n; DisplayName = n; SkinName = n; color = "&1"; - ModelBB = AABB.ModelAABB(Model, lvl); + ModelBB = AABB.ModelAABB(this, lvl); level = lvl; hasExtPositions = true; BotsScheduler.Activate(); diff --git a/MCGalaxy/Chat/Colors.cs b/MCGalaxy/Chat/Colors.cs index a4a8fb6fb..d072c0856 100644 --- a/MCGalaxy/Chat/Colors.cs +++ b/MCGalaxy/Chat/Colors.cs @@ -55,13 +55,10 @@ namespace MCGalaxy { /// NOTE: This returns false for A to F, be warned! public static bool IsDefined(char c) { return c <= '\xff' && List[c].Fallback != '\0'; } - /// Returns whether c is a color code in 0-9, a-f, or A-F. public static bool IsStandard(char c) { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); } - - /// Gets the default color description for the given color code. public static ColorDesc DefaultCol(char code) { switch (code) { case '0': return new ColorDesc('0', "Black"); @@ -86,8 +83,7 @@ namespace MCGalaxy { col.Code = code; return col; } - - /// Updates the colors list array, sends change to all players, then saves color list. + public static void Update(ColorDesc col) { List[col.Code] = col; Player[] players = PlayerInfo.Online.Items; @@ -98,7 +94,6 @@ namespace MCGalaxy { SaveList(); } - /// Finds the color code which has the given name, or empty string if not found. public static string Parse(string name) { for (int i = 0; i < List.Length; i++) { if (List[i].Undefined) continue; @@ -107,14 +102,12 @@ namespace MCGalaxy { } return ""; } - - /// Gets the name of the given color code. + public static string Name(string color) { if (color.Length != 2 || color[0] != '&') return ""; return Name(color[1]); } - /// Gets the name of the given color code. public static string Name(char code) { if (code >= 'A' && code <= 'F') code += ' '; return IsDefined(code) ? List[code].Name : ""; @@ -136,7 +129,6 @@ namespace MCGalaxy { }; static readonly Regex IrcTwoColorCode = new Regex("(\x03\\d{1,2}),\\d{1,2}"); - /// Converts IRC color codes into normal color codes. public static string ConvertIRCToMC(string input) { if (input == null) throw new ArgumentNullException("input"); // get rid of background color component of some IRC color codes. @@ -155,7 +147,6 @@ namespace MCGalaxy { return sb.ToString(); } - /// Escapes then converts color codes into IRC color codes. public static string ConvertMCToIRC(string input) { if (input == null) throw new ArgumentNullException("input"); input = Escape(input); @@ -235,7 +226,6 @@ namespace MCGalaxy { } } - /// Removes all percentage and actual color codes from the given string. public static string Strip(string value) { if (value.IndexOf('%') == -1 && value.IndexOf('&') == -1) return value; char[] output = new char[value.Length]; @@ -279,9 +269,8 @@ namespace MCGalaxy { } } } - - /// Saves the list of all colors. + internal static void SaveList() { using (StreamWriter w = new StreamWriter(Paths.CustomColorsFile)) { foreach (ColorDesc col in List) { @@ -293,7 +282,6 @@ namespace MCGalaxy { } } - /// Loads the list of all colors. internal static void LoadList() { if (!File.Exists(Paths.CustomColorsFile)) return; string[] lines = File.ReadAllLines(Paths.CustomColorsFile); diff --git a/MCGalaxy/Commands/CommandPerms.cs b/MCGalaxy/Commands/CommandPerms.cs index 41710c11a..53e3c52f9 100644 --- a/MCGalaxy/Commands/CommandPerms.cs +++ b/MCGalaxy/Commands/CommandPerms.cs @@ -21,15 +21,6 @@ using System.IO; using System.Text; using MCGalaxy.Commands; -namespace MCGalaxy { - - public class GrpCommands { - - [Obsolete("Use CommandPerms.Load()")] - public static void fillRanks() { CommandPerms.Load(); } - } -} - namespace MCGalaxy.Commands { /// Represents which ranks are allowed (and which are disallowed) to use a command. diff --git a/MCGalaxy/CorePlugin/MiscHandlers.cs b/MCGalaxy/CorePlugin/MiscHandlers.cs index 6d4a9a299..f62bd362b 100644 --- a/MCGalaxy/CorePlugin/MiscHandlers.cs +++ b/MCGalaxy/CorePlugin/MiscHandlers.cs @@ -43,7 +43,7 @@ namespace MCGalaxy.Core { p.prevMsg = ""; p.showMBs = false; p.showPortals = false; - p.ModelBB = AABB.ModelAABB(p.Model, level); // in case had been using a level-only custom block for their model + p.ModelBB = AABB.ModelAABB(p, level); // in case had been using a level-only custom block for their model if (!Hacks.CanUseHacks(p, level) && p.isFlying) { Player.Message(p, "You cannot use /fly on this map."); diff --git a/MCGalaxy/Entity/Entities.cs b/MCGalaxy/Entity/Entities.cs index eb7e4c791..ed7310bcf 100644 --- a/MCGalaxy/Entity/Entities.cs +++ b/MCGalaxy/Entity/Entities.cs @@ -89,7 +89,7 @@ namespace MCGalaxy { string skin = p.SkinName, model = p.Model; OnEntitySpawnedEvent.Call(p, ref name, ref skin, ref model, dst); - SpawnRaw(dst, id, skin, name, model, p.Pos, p.Rot); + SpawnRaw(dst, id, p, skin, name, model); if (!ServerConfig.TablistGlobal) TabList.Add(dst, p, id); } @@ -130,15 +130,16 @@ namespace MCGalaxy { string model = Chat.Format(b.Model, dst, true, false); OnEntitySpawnedEvent.Call(b, ref name, ref skin, ref model, dst); - SpawnRaw(dst, b.id, skin, name, model, b.Pos, b.Rot); + SpawnRaw(dst, b.id, b, skin, name, model); if (ServerConfig.TablistBots) TabList.Add(dst, b); } - static void SpawnRaw(Player dst, byte id, string skin, string name, - string model, Position pos, Orientation rot) { + static void SpawnRaw(Player dst, byte id, Entity entity, + string skin, string name, string model) { + Position pos = entity.Pos; Orientation rot = entity.Rot; // NOTE: Fix for standard clients if (id == Entities.SelfID) pos.Y -= 22; - name = Colors.Cleanup(name, dst.hasTextColors); + name = Colors.Cleanup(name, dst.hasTextColors); if (dst.Supports(CpeExt.ExtPlayerList, 2)) { dst.Send(Packet.ExtAddEntity2(id, skin, name, pos, rot, dst.hasCP437, dst.hasExtPositions)); @@ -153,6 +154,7 @@ namespace MCGalaxy { if (dst.Supports(CpeExt.EntityProperty)) { dst.Send(Packet.EntityProperty(id, EntityProp.RotX, Orientation.PackedToDegrees(rot.RotX))); dst.Send(Packet.EntityProperty(id, EntityProp.RotZ, Orientation.PackedToDegrees(rot.RotZ))); + SendModelScales(dst, id, entity); } } @@ -183,7 +185,7 @@ namespace MCGalaxy { Player[] players = PlayerInfo.Online.Items; entity.Model = model; Level lvl = entity.Level; - entity.ModelBB = AABB.ModelAABB(model, lvl); + entity.ModelBB = AABB.ModelAABB(entity, lvl); foreach (Player pl in players) { if (pl.level != lvl || !pl.Supports(CpeExt.ChangeModel)) continue; @@ -192,9 +194,22 @@ namespace MCGalaxy { byte id = (pl == entity) ? Entities.SelfID : entity.EntityID; string modelSend = Chat.Format(model, pl, true, false); SendModel(pl, id, modelSend); + SendModelScales(pl, id, entity); } } + static void SendModelScales(Player pl, byte id, Entity entity) { + if (!pl.Supports(CpeExt.EntityProperty)) return; + SendModelScale(pl, id, EntityProp.ScaleX, entity.ScaleX); + SendModelScale(pl, id, EntityProp.ScaleY, entity.ScaleY); + SendModelScale(pl, id, EntityProp.ScaleZ, entity.ScaleZ); + } + + static void SendModelScale(Player pl, byte id, EntityProp axis, float value) { + if (value == 0) return; + pl.Send(Packet.EntityProperty(id, axis, (int)(value * 1000))); + } + static void SendModel(Player pl, byte id, string model) { byte block; // Fallback block models for clients that don't support block definitions diff --git a/MCGalaxy/Entity/Entity.cs b/MCGalaxy/Entity/Entity.cs index b6741d52c..8c8543d3b 100644 --- a/MCGalaxy/Entity/Entity.cs +++ b/MCGalaxy/Entity/Entity.cs @@ -33,7 +33,8 @@ namespace MCGalaxy { public string Model = "humanoid"; public AABB ModelBB; - public string SkinName; + public string SkinName; + public float ScaleX, ScaleY, ScaleZ; public Orientation Rot { get { return Orientation.Unpack(_rot); } diff --git a/MCGalaxy/Levels/Level.Fields.cs b/MCGalaxy/Levels/Level.Fields.cs index 3c9ae89cb..18cbe7ea6 100644 --- a/MCGalaxy/Levels/Level.Fields.cs +++ b/MCGalaxy/Levels/Level.Fields.cs @@ -54,12 +54,6 @@ namespace MCGalaxy { internal AABB[] blockAABBs = new AABB[Block.Count * 2]; public ushort Width, Height, Length; - // NOTE: These are for legacy code only, you should use upper case Width/Height/Length - // as these correctly map Y to being Height - [Obsolete] public ushort width; - [Obsolete] public ushort height; - [Obsolete] public ushort depth; - [Obsolete] public ushort length; public bool IsMuseum; public int ReloadThreshold { diff --git a/MCGalaxy/Levels/Level.cs b/MCGalaxy/Levels/Level.cs index 464836386..3b1e0de55 100644 --- a/MCGalaxy/Levels/Level.cs +++ b/MCGalaxy/Levels/Level.cs @@ -45,12 +45,6 @@ namespace MCGalaxy { if (Width < 16) Width = 16; if (Height < 16) Height = 16; if (Length < 16) Length = 16; - - #pragma warning disable 0612 - width = Width; - length = Height; - height = Length; depth = Length; - #pragma warning restore 0612 for (int i = 0; i < CustomBlockDefs.Length; i++) CustomBlockDefs[i] = BlockDefinition.GlobalDefs[i]; diff --git a/MCGalaxy/Player/Player.Login.cs b/MCGalaxy/Player/Player.Login.cs index 466a1d9b1..3cac578f5 100644 --- a/MCGalaxy/Player/Player.Login.cs +++ b/MCGalaxy/Player/Player.Login.cs @@ -193,21 +193,28 @@ namespace MCGalaxy { void LoadCpeData() { string skin = Server.skins.FindData(name); - if (skin != null) SkinName = skin; - + if (skin != null) SkinName = skin; string model = Server.models.FindData(name); if (model != null) Model = model; - ModelBB = AABB.ModelAABB(Model, level); - + + string modelScales = Server.modelScales.FindData(name); + if (modelScales != null) { + string[] bits = modelScales.SplitSpaces(3); + Utils.TryParseDecimal(bits[0], out ScaleX); + Utils.TryParseDecimal(bits[1], out ScaleY); + Utils.TryParseDecimal(bits[2], out ScaleZ); + } + string rotations = Server.rotations.FindData(name); - if (rotations == null) return; - string[] rotParts = rotations.SplitSpaces(2); - if (rotParts.Length != 2) return; + if (rotations != null) { + string[] bits = rotations.SplitSpaces(2); + Orientation rot = Rot; + byte.TryParse(bits[0], out rot.RotX); + byte.TryParse(bits[1], out rot.RotZ); + Rot = rot; + } - Orientation rot = Rot; - byte.TryParse(rotParts[0], out rot.RotX); - byte.TryParse(rotParts[1], out rot.RotZ); - Rot = rot; + ModelBB = AABB.ModelAABB(this, level); } void GetPlayerStats() { diff --git a/MCGalaxy/Server/Server.Fields.cs b/MCGalaxy/Server/Server.Fields.cs index 9ab9e6257..c8a309226 100644 --- a/MCGalaxy/Server/Server.Fields.cs +++ b/MCGalaxy/Server/Server.Fields.cs @@ -60,7 +60,7 @@ namespace MCGalaxy { public static PlayerList bannedIP, whiteList, ircControllers, invalidIds; public static PlayerList ignored, hidden, agreed, vip, noEmotes, lockdown; - public static PlayerExtList models, skins, reach, rotations; + public static PlayerExtList models, skins, reach, rotations, modelScales; public static PlayerExtList frozen, muted, jailed, tempBans, tempRanks; public static readonly List Devs = new List(), Mods = new List(); diff --git a/MCGalaxy/Server/Server.Init.cs b/MCGalaxy/Server/Server.Init.cs index 345305b53..956fed561 100644 --- a/MCGalaxy/Server/Server.Init.cs +++ b/MCGalaxy/Server/Server.Init.cs @@ -69,6 +69,7 @@ namespace MCGalaxy { reach = PlayerExtList.Load("extra/reach.txt"); invalidIds = PlayerList.Load("extra/invalidids.txt"); rotations = PlayerExtList.Load("extra/rotations.txt"); + modelScales = PlayerExtList.Load("extra/modelscales.txt"); muted = PlayerExtList.Load("ranks/muted.txt"); frozen = PlayerExtList.Load("ranks/frozen.txt"); diff --git a/MCGalaxy/util/FastList.cs b/MCGalaxy/util/FastList.cs index de59ede30..16854c0b5 100644 --- a/MCGalaxy/util/FastList.cs +++ b/MCGalaxy/util/FastList.cs @@ -38,31 +38,6 @@ namespace MCGalaxy.Util { Count = 0; } - public bool Exists(Predicate condition) { - for (int i = 0; i < Count; i++) { - if (condition(Items[i])) return true; - } - return false; - } - - public int IndexOf(Predicate condition) { - for (int i = 0; i < Count; i++) { - if (condition(Items[i])) return i; - } - return -1; - } - - public bool Remove(T item) { - int index = Array.IndexOf(Items, item, 0, Count); - if (index < 0) return false; - - Count--; - if (index < Count) - Array.Copy(Items, index + 1, Items, index, Count - index); - Items[Count] = default(T); - return true; - } - public void RemoveAt(int index) { Count--; if (index < Count) @@ -70,15 +45,6 @@ namespace MCGalaxy.Util { Items[Count] = default(T); } - public void RemoveAll(Predicate condition) { - int j = 0; - for (int i = 0; i < Count; i++) { - if (condition(Items[i])) continue; - Items[j] = Items[i]; j++; - } - Count = j; - } - void EnsureCapacity(int threshold) { if (Items.Length >= threshold) return; int newSize = Items.Length * 2; diff --git a/MCGalaxy/util/Math/AABB.cs b/MCGalaxy/util/Math/AABB.cs index 94be79a60..827f1b03f 100644 --- a/MCGalaxy/util/Math/AABB.cs +++ b/MCGalaxy/util/Math/AABB.cs @@ -88,34 +88,41 @@ namespace MCGalaxy.Maths { return false; } - public override string ToString() { - return Min + " : " + Max; - } + public override string ToString() { return Min + " : " + Max; } - public static AABB ModelAABB(string model, Level lvl) { + public static AABB ModelAABB(Entity entity, Level lvl) { + string model = entity.Model; int sep = model.IndexOf('|'); string scaleStr = sep == -1 ? null : model.Substring(sep + 1); model = sep == -1 ? model : model.Substring(0, sep); - AABB baseBB; + AABB bb; byte raw; if (byte.TryParse(model, out raw)) { ExtBlock block = ExtBlock.FromRaw(raw); - baseBB = Block.BlockAABB(block, lvl); - baseBB = baseBB.Offset(-16, 0, -16); // centre around [-16, 16] instead of [0, 32] + bb = Block.BlockAABB(block, lvl); + bb = bb.Offset(-16, 0, -16); // centre around [-16, 16] instead of [0, 32] } else { - baseBB = AABB.Make(new Vec3S32(0, 0, 0), BaseSize(model)); + bb = AABB.Make(new Vec3S32(0, 0, 0), BaseSize(model)); } - baseBB = baseBB.Expand(-1); // adjust the model AABB inwards slightly + bb = bb.Expand(-1); // adjust the model AABB inwards slightly float scale; - if (!Utils.TryParseDecimal(scaleStr, out scale)) return baseBB; + if (!Utils.TryParseDecimal(scaleStr, out scale)) return bb; if (scale < 0.25f) scale = 0.25f; float maxScale = model.CaselessEq("chibi") ? 3 : 2; if (scale > maxScale) scale = maxScale; - return new AABB(baseBB.Min * scale, baseBB.Max * scale); + float scaleX = scale, scaleY = scale, scaleZ = scale; + if (entity.ScaleX != 0) scaleX = entity.ScaleX; + if (entity.ScaleY != 0) scaleY = entity.ScaleY; + if (entity.ScaleZ != 0) scaleZ = entity.ScaleZ; + + bb.Min.X = (int)(bb.Min.X * scaleX); bb.Max.X = (int)(bb.Max.X * scaleX); + bb.Min.Y = (int)(bb.Min.Y * scaleY); bb.Max.Y = (int)(bb.Max.Y * scaleY); + bb.Min.Z = (int)(bb.Min.Z * scaleZ); bb.Max.Z = (int)(bb.Max.Z * scaleZ); + return bb; } static Vec3S32 BaseSize(string model) {