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) {