mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-23 04:32:50 -04:00
Initial support for per axis entity models.
This commit is contained in:
parent
3bc2064378
commit
6644e21425
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -55,13 +55,10 @@ namespace MCGalaxy {
|
||||
/// <remarks> NOTE: This returns false for A to F, be warned! </remarks>
|
||||
public static bool IsDefined(char c) { return c <= '\xff' && List[c].Fallback != '\0'; }
|
||||
|
||||
/// <summary> Returns whether c is a color code in 0-9, a-f, or A-F. </summary>
|
||||
public static bool IsStandard(char c) {
|
||||
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Gets the default color description for the given color code. </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary> Updates the colors list array, sends change to all players, then saves color list. </summary>
|
||||
|
||||
public static void Update(ColorDesc col) {
|
||||
List[col.Code] = col;
|
||||
Player[] players = PlayerInfo.Online.Items;
|
||||
@ -98,7 +94,6 @@ namespace MCGalaxy {
|
||||
SaveList();
|
||||
}
|
||||
|
||||
/// <summary> Finds the color code which has the given name, or empty string if not found. </summary>
|
||||
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 "";
|
||||
}
|
||||
|
||||
/// <summary> Gets the name of the given color code. </summary>
|
||||
|
||||
public static string Name(string color) {
|
||||
if (color.Length != 2 || color[0] != '&') return "";
|
||||
return Name(color[1]);
|
||||
}
|
||||
|
||||
/// <summary> Gets the name of the given color code. </summary>
|
||||
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}");
|
||||
|
||||
/// <summary> Converts IRC color codes into normal color codes. </summary>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary> Escapes then converts color codes into IRC color codes. </summary>
|
||||
public static string ConvertMCToIRC(string input) {
|
||||
if (input == null) throw new ArgumentNullException("input");
|
||||
input = Escape(input);
|
||||
@ -235,7 +226,6 @@ namespace MCGalaxy {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Removes all percentage and actual color codes from the given string. </summary>
|
||||
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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Saves the list of all colors. </summary>
|
||||
|
||||
internal static void SaveList() {
|
||||
using (StreamWriter w = new StreamWriter(Paths.CustomColorsFile)) {
|
||||
foreach (ColorDesc col in List) {
|
||||
@ -293,7 +282,6 @@ namespace MCGalaxy {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Loads the list of all colors. </summary>
|
||||
internal static void LoadList() {
|
||||
if (!File.Exists(Paths.CustomColorsFile)) return;
|
||||
string[] lines = File.ReadAllLines(Paths.CustomColorsFile);
|
||||
|
@ -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 {
|
||||
|
||||
/// <summary> Represents which ranks are allowed (and which are disallowed) to use a command. </summary>
|
||||
|
@ -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.");
|
||||
|
@ -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
|
||||
|
@ -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); }
|
||||
|
@ -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 {
|
||||
|
@ -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];
|
||||
|
@ -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() {
|
||||
|
@ -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<string> Devs = new List<string>(), Mods = new List<string>();
|
||||
|
@ -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");
|
||||
|
@ -38,31 +38,6 @@ namespace MCGalaxy.Util {
|
||||
Count = 0;
|
||||
}
|
||||
|
||||
public bool Exists(Predicate<T> condition) {
|
||||
for (int i = 0; i < Count; i++) {
|
||||
if (condition(Items[i])) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int IndexOf(Predicate<T> 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<T>(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<T> 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;
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user