public Bricks(float top, float left, BrickColor color) : this() { Top = top; Left = left; Color = color; Blocks = 5; // Height in Color-Property }
/// <summary> /// The constructor of the brick. /// </summary> /// <param name="realativePosition">The relative postion to the center postion of the cluster.</param> /// <param name="isMoving">If the brick is moving or stuck in a layer.</param> /// <param name="brickColor">The color of the brick.</param> public Brick(Point realativePosition, bool isMoving, BrickColor brickColor) { this.realativePosition = realativePosition; this.isCenter = Point.Equals(realativePosition, new Point(0, 0)); this.IsMoving = isMoving; this.brickColor = brickColor; dictionaryDircetion = new Dictionary<Direction, Vector>(); dictionaryDircetion.Add(Direction.DOWN, new Vector(0, 1)); dictionaryDircetion.Add(Direction.LEFT, new Vector(-1, 0)); dictionaryDircetion.Add(Direction.RIGHT, new Vector(1, 0)); }
public void Load(BinaryRobloxFileReader reader) { File = reader.File; ClassIndex = reader.ReadInt32(); Name = reader.ReadString(); try { byte propType = reader.ReadByte(); Type = (PropertyType)propType; } catch (EndOfStreamException) { RobloxFile.LogError($"Got corrupted PROP chunk (@ {this})!"); return; } if (Class == null) { RobloxFile.LogError($"Unknown class index {ClassIndex} (@ {this})!"); return; } var ids = Class.InstanceIds; int instCount = Class.NumInstances; var props = new Property[instCount]; for (int i = 0; i < instCount; i++) { int id = ids[i]; Instance instance = File.Instances[id]; if (instance == null) { RobloxFile.LogError($"PROP: No instance @{id} for property {ClassName}.{Name}"); continue; } var prop = new Property(instance, this); props[i] = prop; instance.AddProperty(ref prop); } // Setup some short-hand functions for actions used during the read procedure. var readInts = new Func <int[]>(() => reader.ReadInts(instCount)); var readFloats = new Func <float[]>(() => reader.ReadFloats(instCount)); var readProperties = new Action <Func <int, object> >(read => { for (int i = 0; i < instCount; i++) { var prop = props[i]; if (prop == null) { continue; } prop.Value = read(i); } }); switch (Type) { case PropertyType.String: { readProperties(i => { string value = reader.ReadString(); // Leave an access point for the original byte sequence, in case this is a BinaryString. // This will allow the developer to read the sequence without any mangling from C# strings. byte[] buffer = reader.GetLastStringBuffer(); props[i].RawBuffer = buffer; // Check if this is going to be casted as a BinaryString. // BinaryStrings should use a type of byte[] instead. switch (Name) { case "Tags": case "AttributesSerialize": { return(buffer); } default: { Property prop = props[i]; Instance instance = prop.Instance; Type instType = instance.GetType(); var member = ImplicitMember.Get(instType, Name); if (member != null) { object result = value; Type memberType = member.MemberType; if (memberType == typeof(byte[])) { result = buffer; } return(result); } return(value); } } }); break; } case PropertyType.Bool: { readProperties(i => reader.ReadBoolean()); break; } case PropertyType.Int: { int[] ints = readInts(); readProperties(i => ints[i]); break; } case PropertyType.Float: { float[] floats = readFloats(); readProperties(i => floats[i]); break; } case PropertyType.Double: { readProperties(i => reader.ReadDouble()); break; } case PropertyType.UDim: { float[] UDim_Scales = readFloats(); int[] UDim_Offsets = readInts(); readProperties(i => { float scale = UDim_Scales[i]; int offset = UDim_Offsets[i]; return(new UDim(scale, offset)); }); break; } case PropertyType.UDim2: { float[] UDim2_Scales_X = readFloats(), UDim2_Scales_Y = readFloats(); int[] UDim2_Offsets_X = readInts(), UDim2_Offsets_Y = readInts(); readProperties(i => { float scaleX = UDim2_Scales_X[i], scaleY = UDim2_Scales_Y[i]; int offsetX = UDim2_Offsets_X[i], offsetY = UDim2_Offsets_Y[i]; return(new UDim2(scaleX, offsetX, scaleY, offsetY)); }); break; } case PropertyType.Ray: { readProperties(i => { float posX = reader.ReadFloat(), posY = reader.ReadFloat(), posZ = reader.ReadFloat(); float dirX = reader.ReadFloat(), dirY = reader.ReadFloat(), dirZ = reader.ReadFloat(); var origin = new Vector3(posX, posY, posZ); var direction = new Vector3(dirX, dirY, dirZ); return(new Ray(origin, direction)); }); break; } case PropertyType.Faces: { readProperties(i => { byte faces = reader.ReadByte(); return((Faces)faces); }); break; } case PropertyType.Axes: { readProperties(i => { byte axes = reader.ReadByte(); return((Axes)axes); }); break; } case PropertyType.BrickColor: { int[] BrickColorIds = readInts(); readProperties(i => { BrickColor color = BrickColorIds[i]; return(color); }); break; } case PropertyType.Color3: { float[] Color3_R = readFloats(), Color3_G = readFloats(), Color3_B = readFloats(); readProperties(i => { float r = Color3_R[i], g = Color3_G[i], b = Color3_B[i]; return(new Color3(r, g, b)); }); break; } case PropertyType.Vector2: { float[] Vector2_X = readFloats(), Vector2_Y = readFloats(); readProperties(i => { float x = Vector2_X[i], y = Vector2_Y[i]; return(new Vector2(x, y)); }); break; } case PropertyType.Vector3: { float[] Vector3_X = readFloats(), Vector3_Y = readFloats(), Vector3_Z = readFloats(); readProperties(i => { float x = Vector3_X[i], y = Vector3_Y[i], z = Vector3_Z[i]; return(new Vector3(x, y, z)); }); break; } case PropertyType.CFrame: case PropertyType.Quaternion: case PropertyType.OptionalCFrame: { float[][] matrices = new float[instCount][]; if (Type == PropertyType.OptionalCFrame) { byte cframeType = (byte)PropertyType.CFrame; byte readType = reader.ReadByte(); if (readType != cframeType) { RobloxFile.LogError($"Unexpected property type in OptionalCFrame (expected {cframeType}, got {readType})"); readProperties(i => null); break; } } for (int i = 0; i < instCount; i++) { byte rawOrientId = reader.ReadByte(); if (rawOrientId > 0) { // Make sure this value is in a safe range. int orientId = (rawOrientId - 1) % 36; NormalId xColumn = (NormalId)(orientId / 6); Vector3 R0 = Vector3.FromNormalId(xColumn); NormalId yColumn = (NormalId)(orientId % 6); Vector3 R1 = Vector3.FromNormalId(yColumn); // Compute R2 using the cross product of R0 and R1. Vector3 R2 = R0.Cross(R1); // Generate the rotation matrix. matrices[i] = new float[9] { R0.X, R0.Y, R0.Z, R1.X, R1.Y, R1.Z, R2.X, R2.Y, R2.Z, }; } else if (Type == PropertyType.Quaternion) { float qx = reader.ReadFloat(), qy = reader.ReadFloat(), qz = reader.ReadFloat(), qw = reader.ReadFloat(); var quaternion = new Quaternion(qx, qy, qz, qw); var rotation = quaternion.ToCFrame(); matrices[i] = rotation.GetComponents(); } else { float[] matrix = new float[9]; for (int m = 0; m < 9; m++) { float value = reader.ReadFloat(); matrix[m] = value; } matrices[i] = matrix; } } float[] CFrame_X = readFloats(), CFrame_Y = readFloats(), CFrame_Z = readFloats(); var CFrames = new CFrame[instCount]; for (int i = 0; i < instCount; i++) { float[] matrix = matrices[i]; float x = CFrame_X[i], y = CFrame_Y[i], z = CFrame_Z[i]; float[] components; if (matrix.Length == 12) { matrix[0] = x; matrix[1] = y; matrix[2] = z; components = matrix; } else { float[] position = new float[3] { x, y, z }; components = position.Concat(matrix).ToArray(); } CFrames[i] = new CFrame(components); } if (Type == PropertyType.OptionalCFrame) { byte boolType = (byte)PropertyType.Bool; byte readType = reader.ReadByte(); if (readType != boolType) { RobloxFile.LogError($"Unexpected property type in OptionalCFrame (expected {boolType}, got {readType})"); readProperties(i => null); break; } for (int i = 0; i < instCount; i++) { CFrame cf = CFrames[i]; bool archivable = reader.ReadBoolean(); if (!archivable) { cf = null; } CFrames[i] = new Optional <CFrame>(cf); } } readProperties(i => CFrames[i]); break; } case PropertyType.Enum: { uint[] enums = reader.ReadUInts(instCount); readProperties(i => { Property prop = props[i]; Instance instance = prop.Instance; Type instType = instance.GetType(); uint value = enums[i]; try { var info = ImplicitMember.Get(instType, Name); if (info == null) { RobloxFile.LogError($"Enum cast failed for {ClassName}.{Name} using value {value}!"); return(value); } return(Enum.Parse(info.MemberType, value.ToInvariantString())); } catch { RobloxFile.LogError($"Enum cast failed for {ClassName}.{Name} using value {value}!"); return(value); } }); break; } case PropertyType.Ref: { var instIds = reader.ReadInstanceIds(instCount); readProperties(i => { int instId = instIds[i]; if (instId >= File.NumInstances) { RobloxFile.LogError($"Got out of bounds referent index in {ClassName}.{Name}!"); return(null); } return(instId >= 0 ? File.Instances[instId] : null); }); break; } case PropertyType.Vector3int16: { readProperties(i => { short x = reader.ReadInt16(), y = reader.ReadInt16(), z = reader.ReadInt16(); return(new Vector3int16(x, y, z)); }); break; } case PropertyType.NumberSequence: { readProperties(i => { int numKeys = reader.ReadInt32(); var keypoints = new NumberSequenceKeypoint[numKeys]; for (int key = 0; key < numKeys; key++) { float Time = reader.ReadFloat(), Value = reader.ReadFloat(), Envelope = reader.ReadFloat(); keypoints[key] = new NumberSequenceKeypoint(Time, Value, Envelope); } return(new NumberSequence(keypoints)); }); break; } case PropertyType.ColorSequence: { readProperties(i => { int numKeys = reader.ReadInt32(); var keypoints = new ColorSequenceKeypoint[numKeys]; for (int key = 0; key < numKeys; key++) { float Time = reader.ReadFloat(), R = reader.ReadFloat(), G = reader.ReadFloat(), B = reader.ReadFloat(); Color3 Value = new Color3(R, G, B); int Envelope = reader.ReadInt32(); keypoints[key] = new ColorSequenceKeypoint(Time, Value, Envelope); } return(new ColorSequence(keypoints)); }); break; } case PropertyType.NumberRange: { readProperties(i => { float min = reader.ReadFloat(); float max = reader.ReadFloat(); return(new NumberRange(min, max)); }); break; } case PropertyType.Rect: { float[] Rect_X0 = readFloats(), Rect_Y0 = readFloats(), Rect_X1 = readFloats(), Rect_Y1 = readFloats(); readProperties(i => { float x0 = Rect_X0[i], y0 = Rect_Y0[i], x1 = Rect_X1[i], y1 = Rect_Y1[i]; return(new Rect(x0, y0, x1, y1)); }); break; } case PropertyType.PhysicalProperties: { readProperties(i => { bool custom = reader.ReadBoolean(); if (custom) { float Density = reader.ReadFloat(), Friction = reader.ReadFloat(), Elasticity = reader.ReadFloat(), FrictionWeight = reader.ReadFloat(), ElasticityWeight = reader.ReadFloat(); return(new PhysicalProperties ( Density, Friction, Elasticity, FrictionWeight, ElasticityWeight )); } return(null); }); break; } case PropertyType.Color3uint8: { byte[] Color3uint8_R = reader.ReadBytes(instCount), Color3uint8_G = reader.ReadBytes(instCount), Color3uint8_B = reader.ReadBytes(instCount); readProperties(i => { byte r = Color3uint8_R[i], g = Color3uint8_G[i], b = Color3uint8_B[i]; Color3uint8 result = Color3.FromRGB(r, g, b); return(result); }); break; } case PropertyType.Int64: { long[] longs = reader.ReadInterleaved(instCount, (buffer, start) => { long result = BitConverter.ToInt64(buffer, start); return((long)((ulong)result >> 1) ^ (-(result & 1))); }); readProperties(i => longs[i]); break; } case PropertyType.SharedString: { uint[] SharedKeys = reader.ReadUInts(instCount); readProperties(i => { uint key = SharedKeys[i]; return(File.SharedStrings[key]); }); break; } case PropertyType.ProtectedString: { readProperties(i => { int length = reader.ReadInt32(); byte[] buffer = reader.ReadBytes(length); return(new ProtectedString(buffer)); }); break; } case PropertyType.UniqueId: { readProperties(i => { var buffer = reader.ReadBytes(16); return(new Guid(buffer)); }); break; } default: { RobloxFile.LogError($"Unhandled property type: {Type} in {this}!"); break; } } reader.Dispose(); }
public static BrickColor GetMixColor(BrickColor bc1, BrickColor bc2) { return(null); }
private static Instance Reflect_XML(XmlNode node, Type objType) { if (!typeof(Instance).IsAssignableFrom(objType)) { throw new Exception("'T' must be an Instance."); } Instance obj = (Instance)Activator.CreateInstance(objType); List <XmlNode> children = new List <XmlNode>(); XmlNode properties = null; foreach (XmlNode child in node.ChildNodes) { if (child.Name == "Properties") { properties = child; } else if (child.Name == "Item") { children.Add(child); } } if (properties != null) { foreach (XmlNode property in properties.ChildNodes) { string propertyName = property.Attributes.GetNamedItem("name").Value; propertyName = propertyName.Replace(" ", "_"); FieldInfo field = objType.GetField(propertyName, fieldInfoFlags); if (field != null && property.FirstChild != null) { string propertyType = property.Name; object value = null; string sValue = property.FirstChild.Value; if (propertyType == "string") { value = sValue; } else if (propertyType == "float") { value = Format.ParseFloat(sValue); } else if (propertyType == "double") { value = Format.ParseDouble(sValue); } else if (propertyType == "int") { value = Format.ParseInt(sValue); } else if (propertyType == "CoordinateFrame") { value = CFrame.FromXml(property); } else if (propertyType == "Vector3") { value = new Vector3(property); } else if (propertyType == "Content") { value = property.InnerText; } if (propertyType == "token") { Type fieldType = field.FieldType; if (fieldType.IsEnum) { int index = int.Parse(sValue); value = Enum.ToObject(fieldType, index); } } else if (propertyType == "Color3uint8") { uint rgb = uint.Parse(sValue); int r = (int)(rgb / 65536) % 256; int g = (int)(rgb / 256) % 256; int b = (int)(rgb % 256); value = Color.FromArgb(r, g, b); } if (value != null) { if (field.FieldType == typeof(BrickColor)) { int brickColorId = (int)value; value = BrickColor.FromNumber(brickColorId); } field.SetValue(obj, value); } } } } foreach (XmlNode child in children) { XmlNode classNameNode = child.Attributes.GetNamedItem("class"); if (classNameNode != null) { Type classType = GetClassType(classNameNode.Value); if (classType != null) { Instance childObj = Reflect_XML(child, classType); childObj.Parent = obj; } } } return(obj); }
public Brick(Position pos, BrickColor bc) { position = pos; brickColor = bc; }
public void Save(BinaryRobloxFileWriter writer) { BinaryRobloxFile file = writer.File; File = file; INST inst = file.Classes[ClassIndex]; var props = new List <Property>(); foreach (int instId in inst.InstanceIds) { Instance instance = file.Instances[instId]; var instProps = instance.Properties; if (!instProps.TryGetValue(Name, out Property prop)) { throw new Exception($"Property {Name} must be defined in {instance.GetFullName()}!"); } else if (prop.Type != Type) { throw new Exception($"Property {Name} is not using the correct type in {instance.GetFullName()}!"); } props.Add(prop); } writer.Write(ClassIndex); writer.WriteString(Name); writer.Write(TypeId); switch (Type) { case PropertyType.String: props.ForEach(prop => { byte[] buffer = prop.HasRawBuffer ? prop.RawBuffer : null; if (buffer == null) { string value = prop.CastValue <string>(); buffer = Encoding.UTF8.GetBytes(value); } writer.Write(buffer.Length); writer.Write(buffer); }); break; case PropertyType.Bool: props.ForEach(prop => { bool value = prop.CastValue <bool>(); writer.Write(value); }); break; case PropertyType.Int: var ints = new List <int>(); props.ForEach(prop => { int value = prop.CastValue <int>(); ints.Add(value); }); writer.WriteInts(ints); break; case PropertyType.Float: var floats = new List <float>(); props.ForEach(prop => { float value = prop.CastValue <float>(); floats.Add(value); }); writer.WriteFloats(floats); break; case PropertyType.Double: props.ForEach(prop => { double value = prop.CastValue <double>(); writer.Write(BinaryRobloxFileWriter.GetBytes(value)); }); break; case PropertyType.UDim: var UDim_Scales = new List <float>(); var UDim_Offsets = new List <int>(); props.ForEach(prop => { UDim value = prop.CastValue <UDim>(); UDim_Scales.Add(value.Scale); UDim_Offsets.Add(value.Offset); }); writer.WriteFloats(UDim_Scales); writer.WriteInts(UDim_Offsets); break; case PropertyType.UDim2: var UDim2_Scales_X = new List <float>(); var UDim2_Scales_Y = new List <float>(); var UDim2_Offsets_X = new List <int>(); var UDim2_Offsets_Y = new List <int>(); props.ForEach(prop => { UDim2 value = prop.CastValue <UDim2>(); UDim2_Scales_X.Add(value.X.Scale); UDim2_Scales_Y.Add(value.Y.Scale); UDim2_Offsets_X.Add(value.X.Offset); UDim2_Offsets_Y.Add(value.Y.Offset); }); writer.WriteFloats(UDim2_Scales_X); writer.WriteFloats(UDim2_Scales_Y); writer.WriteInts(UDim2_Offsets_X); writer.WriteInts(UDim2_Offsets_Y); break; case PropertyType.Ray: props.ForEach(prop => { Ray ray = prop.CastValue <Ray>(); Vector3 pos = ray.Origin; writer.Write(pos.X); writer.Write(pos.Y); writer.Write(pos.Z); Vector3 dir = ray.Direction; writer.Write(dir.X); writer.Write(dir.Y); writer.Write(dir.Z); }); break; case PropertyType.Faces: case PropertyType.Axes: props.ForEach(prop => { byte value = prop.CastValue <byte>(); writer.Write(value); }); break; case PropertyType.BrickColor: var BrickColorIds = new List <int>(); props.ForEach(prop => { BrickColor value = prop.CastValue <BrickColor>(); BrickColorIds.Add(value.Number); }); writer.WriteInts(BrickColorIds); break; case PropertyType.Color3: var Color3_R = new List <float>(); var Color3_G = new List <float>(); var Color3_B = new List <float>(); props.ForEach(prop => { Color3 value = prop.CastValue <Color3>(); Color3_R.Add(value.R); Color3_G.Add(value.G); Color3_B.Add(value.B); }); writer.WriteFloats(Color3_R); writer.WriteFloats(Color3_G); writer.WriteFloats(Color3_B); break; case PropertyType.Vector2: var Vector2_X = new List <float>(); var Vector2_Y = new List <float>(); props.ForEach(prop => { Vector2 value = prop.CastValue <Vector2>(); Vector2_X.Add(value.X); Vector2_Y.Add(value.Y); }); writer.WriteFloats(Vector2_X); writer.WriteFloats(Vector2_Y); break; case PropertyType.Vector3: var Vector3_X = new List <float>(); var Vector3_Y = new List <float>(); var Vector3_Z = new List <float>(); props.ForEach(prop => { Vector3 value = prop.CastValue <Vector3>(); Vector3_X.Add(value.X); Vector3_Y.Add(value.Y); Vector3_Z.Add(value.Z); }); writer.WriteFloats(Vector3_X); writer.WriteFloats(Vector3_Y); writer.WriteFloats(Vector3_Z); break; case PropertyType.CFrame: case PropertyType.Quaternion: var CFrame_X = new List <float>(); var CFrame_Y = new List <float>(); var CFrame_Z = new List <float>(); props.ForEach(prop => { CFrame value = null; if (prop.Value is Quaternion) { Quaternion q = prop.CastValue <Quaternion>(); value = q.ToCFrame(); } else { value = prop.CastValue <CFrame>(); } Vector3 pos = value.Position; CFrame_X.Add(pos.X); CFrame_Y.Add(pos.Y); CFrame_Z.Add(pos.Z); int orientId = value.GetOrientId(); writer.Write((byte)(orientId + 1)); if (orientId == -1) { if (Type == PropertyType.Quaternion) { Quaternion quat = new Quaternion(value); writer.Write(quat.X); writer.Write(quat.Y); writer.Write(quat.Z); writer.Write(quat.W); } else { float[] components = value.GetComponents(); for (int i = 3; i < 12; i++) { float component = components[i]; writer.Write(component); } } } }); writer.WriteFloats(CFrame_X); writer.WriteFloats(CFrame_Y); writer.WriteFloats(CFrame_Z); break; case PropertyType.Enum: var Enums = new List <uint>(); props.ForEach(prop => { if (prop.Value is uint) { uint raw = prop.CastValue <uint>(); Enums.Add(raw); return; } int signed = (int)prop.Value; uint value = (uint)signed; Enums.Add(value); }); writer.WriteInterleaved(Enums); break; case PropertyType.Ref: var InstanceIds = new List <int>(); props.ForEach(prop => { int referent = -1; if (prop.Value != null) { Instance value = prop.CastValue <Instance>(); referent = int.Parse(value.Referent); } InstanceIds.Add(referent); }); writer.WriteInstanceIds(InstanceIds); break; case PropertyType.Vector3int16: props.ForEach(prop => { Vector3int16 value = prop.CastValue <Vector3int16>(); writer.Write(value.X); writer.Write(value.Y); writer.Write(value.Z); }); break; case PropertyType.NumberSequence: props.ForEach(prop => { NumberSequence value = prop.CastValue <NumberSequence>(); var keyPoints = value.Keypoints; writer.Write(keyPoints.Length); foreach (var keyPoint in keyPoints) { writer.Write(keyPoint.Time); writer.Write(keyPoint.Value); writer.Write(keyPoint.Envelope); } }); break; case PropertyType.ColorSequence: props.ForEach(prop => { ColorSequence value = prop.CastValue <ColorSequence>(); var keyPoints = value.Keypoints; writer.Write(keyPoints.Length); foreach (var keyPoint in keyPoints) { Color3 color = keyPoint.Value; writer.Write(keyPoint.Time); writer.Write(color.R); writer.Write(color.G); writer.Write(color.B); writer.Write(keyPoint.Envelope); } }); break; case PropertyType.NumberRange: props.ForEach(prop => { NumberRange value = prop.CastValue <NumberRange>(); writer.Write(value.Min); writer.Write(value.Max); }); break; case PropertyType.Rect: var Rect_X0 = new List <float>(); var Rect_Y0 = new List <float>(); var Rect_X1 = new List <float>(); var Rect_Y1 = new List <float>(); props.ForEach(prop => { Rect value = prop.CastValue <Rect>(); Vector2 min = value.Min; Rect_X0.Add(min.X); Rect_Y0.Add(min.Y); Vector2 max = value.Max; Rect_X1.Add(max.X); Rect_Y1.Add(max.Y); }); writer.WriteFloats(Rect_X0); writer.WriteFloats(Rect_Y0); writer.WriteFloats(Rect_X1); writer.WriteFloats(Rect_Y1); break; case PropertyType.PhysicalProperties: props.ForEach(prop => { bool custom = (prop.Value != null); writer.Write(custom); if (custom) { PhysicalProperties value = prop.CastValue <PhysicalProperties>(); writer.Write(value.Density); writer.Write(value.Friction); writer.Write(value.Elasticity); writer.Write(value.FrictionWeight); writer.Write(value.ElasticityWeight); } }); break; case PropertyType.Color3uint8: var Color3uint8_R = new List <byte>(); var Color3uint8_G = new List <byte>(); var Color3uint8_B = new List <byte>(); props.ForEach(prop => { Color3uint8 value = prop.CastValue <Color3uint8>(); Color3uint8_R.Add(value.R); Color3uint8_G.Add(value.G); Color3uint8_B.Add(value.B); }); byte[] rBuffer = Color3uint8_R.ToArray(); writer.Write(rBuffer); byte[] gBuffer = Color3uint8_G.ToArray(); writer.Write(gBuffer); byte[] bBuffer = Color3uint8_B.ToArray(); writer.Write(bBuffer); break; case PropertyType.Int64: var Int64s = new List <long>(); props.ForEach(prop => { long value = prop.CastValue <long>(); Int64s.Add(value); }); writer.WriteInterleaved(Int64s, value => { // Move the sign bit to the front. return((value << 1) ^ (value >> 63)); }); break; case PropertyType.SharedString: var sharedKeys = new List <uint>(); SSTR sstr = file.SSTR; if (sstr == null) { sstr = new SSTR(); file.SSTR = sstr; } props.ForEach(prop => { var shared = prop.CastValue <SharedString>(); if (shared == null) { byte[] empty = Array.Empty <byte>(); shared = SharedString.FromBuffer(empty); } string key = shared.Key; if (!sstr.Lookup.ContainsKey(key)) { uint id = (uint)(sstr.Lookup.Count); sstr.Strings.Add(id, shared); sstr.Lookup.Add(key, id); } uint hashId = sstr.Lookup[key]; sharedKeys.Add(hashId); }); writer.WriteInterleaved(sharedKeys); break; case PropertyType.ProtectedString: props.ForEach(prop => { var protect = prop.CastValue <ProtectedString>(); byte[] buffer = protect.RawBuffer; writer.Write(buffer.Length); writer.Write(buffer); }); break; default: break; } }
public Brick(Game game, BrickColor color) : base(game) { contentManager = new ContentManager(game.Services); brickColor = color; }
public BlockBase(int[,] bricks, BrickColor color) { _bricks = bricks; Color = color; }
public void Setup(Sprite damagedSprite, BrickColor brickColor, int health = 2) { _brickColor = brickColor; _damagedSprite = damagedSprite; _health = health; }
public static TextureBindings BindTextures(Dictionary <string, ValveMaterial> materials) { Contract.Requires(materials != null); var textures = new TextureBindings(); var images = textures.Images; foreach (string mtlName in materials.Keys) { ValveMaterial material = materials[mtlName]; Asset textureAsset = material.TextureAsset; if (textureAsset == null || textureAsset.Id == 9854798) { var linkedTo = material.LinkedTo; Color3 color; if (linkedTo.BrickColor != null) { BrickColor bc = linkedTo.BrickColor; color = bc.Color; } else if (linkedTo.Color3uint8 != null) { color = linkedTo.Color3uint8; } else { BrickColor def = BrickColor.FromNumber(-1); color = def.Color; } float r = color.R, g = color.G, b = color.B; if (!images.ContainsKey("BrickColor")) { byte[] rawImg = ResourceUtility.GetResource("Images/BlankWhite.png"); using (MemoryStream imgStream = new MemoryStream(rawImg)) { Image image = Image.FromStream(imgStream); textures.BindTexture("BrickColor", image, false); } } material.UseEnvMap = true; material.VertexColor = new Vector3(r, g, b); textures.BindTextureAlias(mtlName, "BrickColor"); } else { byte[] rawImg = textureAsset.GetContent(); using (MemoryStream imgStream = new MemoryStream(rawImg)) { Image image = Image.FromStream(imgStream); textures.BindTexture(mtlName, image); } } } return(textures); }
//------------------------------------------------------- public Brick(ref Grid grid, BrickType typeID, BrickColor colorID, int xOnGrid, int yOnGrid) : base(GetPath(typeID, colorID), grid, 160 + (xOnGrid - 1) * 32, (yOnGrid - 1) * 16, 32, 16) { _typeID = typeID; _colorID = colorID; }
public void Load(BinaryRobloxFileReader reader) { BinaryRobloxFile file = reader.File; ClassIndex = reader.ReadInt32(); Name = reader.ReadString(); byte propType = reader.ReadByte(); Type = (PropertyType)propType; INST inst = file.Classes[ClassIndex]; ClassName = inst.ClassName; Property[] props = new Property[inst.NumInstances]; var ids = inst.InstanceIds; int instCount = inst.NumInstances; for (int i = 0; i < instCount; i++) { int id = ids[i]; Instance instance = file.Instances[id]; Property prop = new Property(instance, this); props[i] = prop; instance.AddProperty(ref prop); } // Setup some short-hand functions for actions used during the read procedure. var readInts = new Func <int[]>(() => reader.ReadInts(instCount)); var readFloats = new Func <float[]>(() => reader.ReadFloats(instCount)); var readProperties = new Action <Func <int, object> >(read => { for (int i = 0; i < instCount; i++) { object result = read(i); props[i].Value = result; } }); switch (Type) { case PropertyType.String: readProperties(i => { string value = reader.ReadString(); // Leave an access point for the original byte sequence, in case this is a BinaryString. // This will allow the developer to read the sequence without any mangling from C# strings. byte[] buffer = reader.GetLastStringBuffer(); props[i].RawBuffer = buffer; // Check if this is going to be casted as a BinaryString. // BinaryStrings should use a type of byte[] instead. if (Name == "AttributesSerialize") { return(buffer); } Property prop = props[i]; Instance instance = prop.Instance; Type instType = instance.GetType(); FieldInfo field = instType.GetField(Name); if (field != null) { object result = value; Type fieldType = field.FieldType; if (fieldType == typeof(byte[])) { result = buffer; } return(result); } else { return(value); } }); break; case PropertyType.Bool: readProperties(i => reader.ReadBoolean()); break; case PropertyType.Int: int[] ints = readInts(); readProperties(i => ints[i]); break; case PropertyType.Float: float[] floats = readFloats(); readProperties(i => floats[i]); break; case PropertyType.Double: readProperties(i => reader.ReadDouble()); break; case PropertyType.UDim: float[] UDim_Scales = readFloats(); int[] UDim_Offsets = readInts(); readProperties(i => { float scale = UDim_Scales[i]; int offset = UDim_Offsets[i]; return(new UDim(scale, offset)); }); break; case PropertyType.UDim2: float[] UDim2_Scales_X = readFloats(), UDim2_Scales_Y = readFloats(); int[] UDim2_Offsets_X = readInts(), UDim2_Offsets_Y = readInts(); readProperties(i => { float scaleX = UDim2_Scales_X[i], scaleY = UDim2_Scales_Y[i]; int offsetX = UDim2_Offsets_X[i], offsetY = UDim2_Offsets_Y[i]; return(new UDim2(scaleX, offsetX, scaleY, offsetY)); }); break; case PropertyType.Ray: readProperties(i => { float posX = reader.ReadFloat(), posY = reader.ReadFloat(), posZ = reader.ReadFloat(); float dirX = reader.ReadFloat(), dirY = reader.ReadFloat(), dirZ = reader.ReadFloat(); Vector3 origin = new Vector3(posX, posY, posZ); Vector3 direction = new Vector3(dirX, dirY, dirZ); return(new Ray(origin, direction)); }); break; case PropertyType.Faces: readProperties(i => { byte faces = reader.ReadByte(); return((Faces)faces); }); break; case PropertyType.Axes: readProperties(i => { byte axes = reader.ReadByte(); return((Axes)axes); }); break; case PropertyType.BrickColor: int[] BrickColorIds = readInts(); readProperties(i => { int number = BrickColorIds[i]; return(BrickColor.FromNumber(number)); }); break; case PropertyType.Color3: float[] Color3_R = readFloats(), Color3_G = readFloats(), Color3_B = readFloats(); readProperties(i => { float r = Color3_R[i], g = Color3_G[i], b = Color3_B[i]; return(new Color3(r, g, b)); }); break; case PropertyType.Vector2: float[] Vector2_X = readFloats(), Vector2_Y = readFloats(); readProperties(i => { float x = Vector2_X[i], y = Vector2_Y[i]; return(new Vector2(x, y)); }); break; case PropertyType.Vector3: float[] Vector3_X = readFloats(), Vector3_Y = readFloats(), Vector3_Z = readFloats(); readProperties(i => { float x = Vector3_X[i], y = Vector3_Y[i], z = Vector3_Z[i]; return(new Vector3(x, y, z)); }); break; case PropertyType.CFrame: case PropertyType.Quaternion: // Temporarily load the rotation matrices into their properties. // We'll update them to CFrames once we iterate over the position data. float[][] matrices = new float[instCount][]; for (int i = 0; i < instCount; i++) { byte rawOrientId = reader.ReadByte(); if (rawOrientId > 0) { // Make sure this value is in a safe range. int orientId = (rawOrientId - 1) % 36; NormalId xColumn = (NormalId)(orientId / 6); Vector3 R0 = Vector3.FromNormalId(xColumn); NormalId yColumn = (NormalId)(orientId % 6); Vector3 R1 = Vector3.FromNormalId(yColumn); // Compute R2 using the cross product of R0 and R1. Vector3 R2 = R0.Cross(R1); // Generate the rotation matrix. matrices[i] = new float[9] { R0.X, R0.Y, R0.Z, R1.X, R1.Y, R1.Z, R2.X, R2.Y, R2.Z, }; } else if (Type == PropertyType.Quaternion) { float qx = reader.ReadFloat(), qy = reader.ReadFloat(), qz = reader.ReadFloat(), qw = reader.ReadFloat(); Quaternion quaternion = new Quaternion(qx, qy, qz, qw); var rotation = quaternion.ToCFrame(); matrices[i] = rotation.GetComponents(); } else { float[] matrix = new float[9]; for (int m = 0; m < 9; m++) { float value = reader.ReadFloat(); matrix[m] = value; } matrices[i] = matrix; } } float[] CFrame_X = readFloats(), CFrame_Y = readFloats(), CFrame_Z = readFloats(); readProperties(i => { float[] matrix = matrices[i]; float x = CFrame_X[i], y = CFrame_Y[i], z = CFrame_Z[i]; float[] components; if (matrix.Length == 12) { matrix[0] = x; matrix[1] = y; matrix[2] = z; components = matrix; } else { float[] position = new float[3] { x, y, z }; components = position.Concat(matrix).ToArray(); } return(new CFrame(components)); }); break; case PropertyType.Enum: uint[] enums = reader.ReadUInts(instCount); readProperties(i => { Property prop = props[i]; Instance instance = prop.Instance; Type instType = instance.GetType(); uint value = enums[i]; try { FieldInfo info = instType.GetField(Name, Property.BindingFlags); return(Enum.Parse(info.FieldType, value.ToInvariantString())); } catch { //Console.WriteLine($"Enum cast failed for {inst.ClassName}.{Name} using value {value}!"); pretty annoying for output return(value); } }); break; case PropertyType.Ref: var instIds = reader.ReadInstanceIds(instCount); readProperties(i => { int instId = instIds[i]; return(instId >= 0 ? file.Instances[instId] : null); }); break; case PropertyType.Vector3int16: readProperties(i => { short x = reader.ReadInt16(), y = reader.ReadInt16(), z = reader.ReadInt16(); return(new Vector3int16(x, y, z)); }); break; case PropertyType.NumberSequence: readProperties(i => { int numKeys = reader.ReadInt32(); var keypoints = new NumberSequenceKeypoint[numKeys]; for (int key = 0; key < numKeys; key++) { float Time = reader.ReadFloat(), Value = reader.ReadFloat(), Envelope = reader.ReadFloat(); keypoints[key] = new NumberSequenceKeypoint(Time, Value, Envelope); } return(new NumberSequence(keypoints)); }); break; case PropertyType.ColorSequence: readProperties(i => { int numKeys = reader.ReadInt32(); var keypoints = new ColorSequenceKeypoint[numKeys]; for (int key = 0; key < numKeys; key++) { float Time = reader.ReadFloat(), R = reader.ReadFloat(), G = reader.ReadFloat(), B = reader.ReadFloat(); Color3 Value = new Color3(R, G, B); int Envelope = reader.ReadInt32(); keypoints[key] = new ColorSequenceKeypoint(Time, Value, Envelope); } return(new ColorSequence(keypoints)); }); break; case PropertyType.NumberRange: readProperties(i => { float min = reader.ReadFloat(); float max = reader.ReadFloat(); return(new NumberRange(min, max)); }); break; case PropertyType.Rect: float[] Rect_X0 = readFloats(), Rect_Y0 = readFloats(), Rect_X1 = readFloats(), Rect_Y1 = readFloats(); readProperties(i => { float x0 = Rect_X0[i], y0 = Rect_Y0[i], x1 = Rect_X1[i], y1 = Rect_Y1[i]; return(new Rect(x0, y0, x1, y1)); }); break; case PropertyType.PhysicalProperties: readProperties(i => { bool custom = reader.ReadBoolean(); if (custom) { float Density = reader.ReadFloat(), Friction = reader.ReadFloat(), Elasticity = reader.ReadFloat(), FrictionWeight = reader.ReadFloat(), ElasticityWeight = reader.ReadFloat(); return(new PhysicalProperties ( Density, Friction, Elasticity, FrictionWeight, ElasticityWeight )); } return(null); }); break; case PropertyType.Color3uint8: byte[] Color3uint8_R = reader.ReadBytes(instCount), Color3uint8_G = reader.ReadBytes(instCount), Color3uint8_B = reader.ReadBytes(instCount); readProperties(i => { byte r = Color3uint8_R[i], g = Color3uint8_G[i], b = Color3uint8_B[i]; Color3uint8 result = Color3.FromRGB(r, g, b); return(result); }); break; case PropertyType.Int64: long[] Int64s = reader.ReadInterleaved(instCount, (buffer, start) => { long result = BitConverter.ToInt64(buffer, start); return((long)((ulong)result >> 1) ^ (-(result & 1))); }); readProperties(i => Int64s[i]); break; case PropertyType.SharedString: uint[] SharedKeys = reader.ReadUInts(instCount); readProperties(i => { uint key = SharedKeys[i]; return(file.SharedStrings[key]); }); break; case PropertyType.ProtectedString: readProperties(i => { int length = reader.ReadInt32(); byte[] buffer = reader.ReadBytes(length); return(new ProtectedString(buffer)); }); break; default: Console.Error.WriteLine("Unhandled property type: {0}!", Type); break; // } reader.Dispose(); }
public static TextureAssembly AssembleTextures(Dictionary <string, Material> materials) { TextureAssembly assembly = new TextureAssembly(); Dictionary <string, Image> images = new Dictionary <string, Image>(); assembly.Images = images; Dictionary <string, string> matLinks = new Dictionary <string, string>(); assembly.MatLinks = matLinks; foreach (string mtlName in materials.Keys) { Material material = materials[mtlName]; Asset textureAsset = material.TextureAsset; if (textureAsset == null) { string bcName = "Institutional white"; int brickColor = material.LinkedTo.BrickColor; if (BrickColors.NumericalSearch.ContainsKey(brickColor)) { BrickColor color = BrickColors.NumericalSearch[brickColor]; float r = color.R / 255.0f; float g = color.G / 255.0f; float b = color.B / 255.0f; material.VertexColor = new Vector3(r, g, b); bcName = color.Name; } else { material.VertexColor = new Vector3(1, 1, 1); } if (!images.ContainsKey("BrickColor")) { byte[] rawImg = ResourceUtility.GetResource("Images/BlankWhite.png"); using (MemoryStream imgStream = new MemoryStream(rawImg)) { Image image = Image.FromStream(imgStream); images.Add("BrickColor", image); } } string matKey = serializeBrickColorMtl(material); material.UseReflectance = true; matLinks.Add(mtlName, matKey); } else { byte[] rawImg = textureAsset.GetContent(); using (MemoryStream imgStream = new MemoryStream(rawImg)) { Image image = Image.FromStream(imgStream); images.Add(mtlName, image); matLinks.Add(mtlName, mtlName); } } } return(assembly); }
public Brick(float top, float left, BrickColor color) : base(top, left) { Color = color; }
public void ReadProperties(RobloxBinaryFile file) { INST type = file.Types[TypeIndex]; FileProperty[] props = new FileProperty[type.NumInstances]; int[] ids = type.InstanceIds; int instCount = type.NumInstances; for (int i = 0; i < instCount; i++) { int id = ids[i]; FileInstance instance = file.Instances[id]; FileProperty prop = new FileProperty(); prop.Instance = instance; prop.Name = Name; prop.Type = Type; props[i] = prop; instance.AddProperty(ref prop); } // Setup some short-hand functions for actions frequently used during the read procedure. var readInts = new Func <int[]>(() => Reader.ReadInts(instCount)); var readFloats = new Func <float[]>(() => Reader.ReadFloats(instCount)); var loadProperties = new Action <Func <int, object> >(read => { for (int i = 0; i < instCount; i++) { object result = read(i); props[i].Value = result; } }); // Read the property data based on the property type. // NOTE: This only reads the property types needed for Rbx2Source. // You can visit the following link for a full implementation: // https://github.com/CloneTrooper1019/Roblox-File-Format/blob/master/BinaryFormat/ChunkTypes/PROP.cs switch (Type) { case PropertyType.String: loadProperties(i => Reader.ReadString()); break; case PropertyType.Bool: loadProperties(i => Reader.ReadBoolean()); break; case PropertyType.Int: int[] ints = readInts(); loadProperties(i => ints[i]); break; case PropertyType.Float: float[] floats = readFloats(); loadProperties(i => floats[i]); break; case PropertyType.Double: loadProperties(i => Reader.ReadDouble()); break; case PropertyType.Vector3: float[] Vector3_X = readFloats(), Vector3_Y = readFloats(), Vector3_Z = readFloats(); loadProperties(i => { float x = Vector3_X[i], y = Vector3_Y[i], z = Vector3_Z[i]; return(new Vector3(x, y, z)); }); break; case PropertyType.BrickColor: int[] brickColorIds = readInts(); loadProperties(i => { int brickColorId = brickColorIds[i]; return(BrickColor.FromNumber(brickColorId)); }); break; case PropertyType.CFrame: case PropertyType.Quaternion: // Temporarily load the rotation matrices into their properties. // We'll update them to CFrames once we iterate over the position data. loadProperties(i => { int normXY = Reader.ReadByte(); if (normXY > 0) { // Make sure this value is in a safe range. normXY = (normXY - 1) % 36; NormalId normX = (NormalId)(normXY / 6); Vector3 R0 = Vector3.FromNormalId(normX); NormalId normY = (NormalId)(normXY % 6); Vector3 R1 = Vector3.FromNormalId(normY); // Compute R2 using the cross product of R0 and R1. Vector3 R2 = R0.Cross(R1); // Generate the rotation matrix and return it. return(new float[9] { R0.X, R0.Y, R0.Z, R1.X, R1.Y, R1.Z, R2.X, R2.Y, R2.Z, }); } else if (Type == PropertyType.Quaternion) { float qx = Reader.ReadFloat(), qy = Reader.ReadFloat(), qz = Reader.ReadFloat(), qw = Reader.ReadFloat(); Quaternion quaternion = new Quaternion(qx, qy, qz, qw); var rotation = quaternion.ToCFrame(); return(rotation.GetComponents()); } else { float[] matrix = new float[9]; for (int m = 0; m < 9; m++) { float value = Reader.ReadFloat(); matrix[m] = value; } return(matrix); } }); float[] CFrame_X = readFloats(), CFrame_Y = readFloats(), CFrame_Z = readFloats(); loadProperties(i => { float[] matrix = props[i].Value as float[]; float x = CFrame_X[i], y = CFrame_Y[i], z = CFrame_Z[i]; float[] position = new float[3] { x, y, z }; float[] components = position .Concat(matrix) .ToArray(); return(new CFrame(components)); }); break; case PropertyType.Enum: uint[] enums = Reader.ReadInterleaved(instCount, BitConverter.ToUInt32); loadProperties(i => enums[i]); break; case PropertyType.Ref: int[] instIds = Reader.ReadInstanceIds(instCount); loadProperties(i => { int instId = instIds[i]; return(instId >= 0 ? file.Instances[instId] : null); }); break; case PropertyType.Color3uint8: byte[] Color3uint8_R = Reader.ReadBytes(instCount), Color3uint8_G = Reader.ReadBytes(instCount), Color3uint8_B = Reader.ReadBytes(instCount); loadProperties(i => { byte r = Color3uint8_R[i], g = Color3uint8_G[i], b = Color3uint8_B[i]; return(Color.FromArgb(r, g, b)); }); break; case PropertyType.Int64: long[] int64s = Reader.ReadInterleaved(instCount, (buffer, start) => { long result = BitConverter.ToInt64(buffer, start); return((long)((ulong)result >> 1) ^ (-(result & 1))); }); loadProperties(i => int64s[i]); break; } Reader.Dispose(); }
public override void Deserialize(Dictionary<string, object> ser) { base.Deserialize(ser); Color = (BrickColor)ser["Color"]; }
public static BrickColor GetMixColor (BrickColor bc1, BrickColor bc2) { return null; }