public MinecraftPacket(MinecraftClient client) { Client = client; PacketAttribute attribute = GetType().GetCustomAttribute <PacketAttribute>(false); Id = attribute.Id; Data = new MinecraftStream((RecyclableMemoryStream)RMSManager.Get().GetStream(GetType().FullName)); }
public MinecraftPacket(MinecraftClient client, Stream stream) { Client = client; Data = new MinecraftStream((RecyclableMemoryStream)RMSManager.Get().GetStream(GetType().FullName)); Length = Client.CompressionEnabled ? (int)stream.Length : new VarInt(stream).Value; long _pos = stream.Position; Id = new VarInt(stream).Value; byte[] data = new byte[Length - (stream.Position - _pos)]; stream.Read(data, 0, data.Length); Data.Write(data); Data.Seek(0, SeekOrigin.Begin); }
public MinecraftServer(IPAddress address, int port) : base(address, port) { using (Stream stream = RMSManager.Get().GetStream(Properties.Resources.dimension_codec)) { DimensionCodec = new NBTFile().Read(stream); } using (Stream stream = RMSManager.Get().GetStream(Properties.Resources.overworld)) { OverworldDimension = new NBTFile().Read(stream); } using (Stream stream = RMSManager.Get().GetStream(Properties.Resources.nether)) { NetherDimension = new NBTFile().Read(stream); } using (Stream stream = RMSManager.Get().GetStream(Properties.Resources.the_end)) { TheEndDimension = new NBTFile().Read(stream); } Configuration = new ServerConfiguration { ViewDistance = 12, CompressionThreshold = 128, OnlineMode = false }; Http = new System.Net.Http.HttpClient(); #region encryption RsaKeyPairGenerator rsa = new(); rsa.Init(new KeyGenerationParameters(new SecureRandom(), 1024)); KeyPair = rsa.GenerateKeyPair(); Decryptor = new Pkcs1Encoding(new RsaEngine()); Decryptor.Init(false, KeyPair.Private); Encryptor = new Pkcs1Encoding(new RsaEngine()); Encryptor.Init(true, KeyPair.Public); #endregion World = new World(this, "world", new FlatWorldGenerator()); }
public static void Run(string[] args) { if (!Directory.Exists(outputDirectory)) { Directory.CreateDirectory(outputDirectory); } Dictionary <string, string> generatedItems = new(); MemoryStream compressedStream = RMSManager.Get().GetStream(Properties.Resources.items); GZipStream zipStream = new(compressedStream, CompressionMode.Decompress); MemoryStream resultStream = RMSManager.Get().GetStream(); zipStream.CopyTo(resultStream); dynamic items = JSON.DeserializeDynamic(Encoding.UTF8.GetString(resultStream.ToArray())); foreach (dynamic it in items) { string id = it.Key; dynamic item = it.Value; int protocolId = item.id; int maxStackSize = item.max_stack_size; string clsName = id.Replace("minecraft:", "").ToPascalCase(); // air is unneeded if (id == "minecraft:air") { continue; } Console.WriteLine("Generating " + id); string i; if (item.ContainsKey("block")) { i = string.Format(blockTemplate, clsName, id, protocolId, maxStackSize, item.block); } else if (item.ContainsKey("food_properties")) { i = string.Format(foodTemplate, clsName, id, protocolId, maxStackSize, item.food_properties.nutrition, item.food_properties.saturation_modifier, item.food_properties.can_always_eat); } else if (id.Contains("sword")) { i = string.Format(swordTemplate, clsName, id, protocolId, maxStackSize, item.uses, item.speed, item.attack_damage, item.attack_damage_bonus); } else if (id.Contains("pickaxe")) { StringBuilder arr = new("new int[] { "); foreach (int block in item.diggable_blocks) { arr.Append(block); arr.Append(", "); } arr.Length -= 2; arr.Append(" }"); i = string.Format(pickaxeTemplate, clsName, id, protocolId, maxStackSize, item.uses, item.speed, item.attack_damage, item.attack_damage_bonus, arr.ToString()); } else if (id.Contains("axe")) { StringBuilder arr = new("new int[] { "); foreach (int block in item.diggable_blocks) { arr.Append(block); arr.Append(", "); } arr.Length -= 2; arr.Append(" }"); StringBuilder arr0 = new("new string[] { "); foreach (string material in item.effective_materials) { arr0.Append('"'); arr0.Append(material); arr0.Append('"'); arr0.Append(", "); } arr0.Length -= 2; arr0.Append(" }"); i = string.Format(axeTemplate, clsName, id, protocolId, maxStackSize, item.uses, item.speed, item.attack_damage, item.attack_damage_bonus, arr.ToString(), arr0.ToString(), "null"); // TODO how are we supposed to pass a dictionary to an attribute? } else if (id.Contains("hoe")) { StringBuilder arr = new("new int[] { "); foreach (int block in item.diggable_blocks) { arr.Append(block); arr.Append(", "); } arr.Length -= 2; arr.Append(" }"); i = string.Format(hoeTemplate, clsName, id, protocolId, maxStackSize, item.uses, item.speed, item.attack_damage, item.attack_damage_bonus, arr.ToString(), "null"); } else if (id.Contains("shovel")) { StringBuilder arr = new("new int[] { "); foreach (int block in item.diggable_blocks) { arr.Append(block); arr.Append(", "); } arr.Length -= 2; arr.Append(" }"); i = string.Format(shovelTemplate, clsName, id, protocolId, maxStackSize, item.uses, item.speed, item.attack_damage, item.attack_damage_bonus, arr.ToString(), "null"); } else { i = string.Format(itemTemplate, clsName, id, protocolId, maxStackSize); } generatedItems.Add($"Item{clsName}.cs", i); } Console.WriteLine("Saving blocks..."); foreach (KeyValuePair <string, string> entry in generatedItems) { File.WriteAllText(Path.Combine(outputDirectory, entry.Key), entry.Value); } }
public static void Run(string[] args) { if (!Directory.Exists(outputDirectory)) { Directory.CreateDirectory(outputDirectory); } Dictionary <string, string> generatedBlocks = new(); ushort maxStateId = 0; MemoryStream compressedStream = RMSManager.Get().GetStream(Properties.Resources.blocks); GZipStream zipStream = new(compressedStream, CompressionMode.Decompress); MemoryStream resultStream = RMSManager.Get().GetStream(); zipStream.CopyTo(resultStream); dynamic blocks = JSON.DeserializeDynamic(Encoding.UTF8.GetString(resultStream.ToArray())); compressedStream = RMSManager.Get().GetStream(Properties.Resources.blockstates); zipStream = new GZipStream(compressedStream, CompressionMode.Decompress); resultStream = RMSManager.Get().GetStream(); zipStream.CopyTo(resultStream); dynamic blockstates = JSON.DeserializeDynamic(Encoding.UTF8.GetString(resultStream.ToArray())); int bitsPerBlock = 0; foreach (dynamic block in blocks) { string namedId = block.Key; // air is unneeded if (namedId == "minecraft:air") { continue; } Console.WriteLine("Generating " + namedId); dynamic block1 = blockstates[0].blocks.block[namedId.Replace("minecraft:", "")]; if (block1 == null) { Console.WriteLine("eh?? " + namedId); continue; } bool propertiesDone = false; int protocolId = block1.numeric_id; int minState = block1.min_state_id; int maxState = block1.max_state_id; int defaultState = 0; if (maxState > maxStateId) { maxStateId = (ushort)maxState; } Dictionary <string, string> properties = new(); StringBuilder stateGet = new(); StringBuilder stateSet = new(); StringBuilder parameters = new(); StringBuilder setters = new(); bool hasProperties = false; foreach (dynamic state in block.Value.states) { StringBuilder checks = new(); if (state.properties != null) { hasProperties = true; foreach (dynamic property in state.properties) { checks.Append(((string)property.Key).ToPascalCase()); checks.Append(" == "); if (property.Value == "true" || property.Value == "false") { checks.Append((string)property.Value); if (!propertiesDone) { properties.Add((string)property.Key, string.Format(propertyTemplate, "bool", ((string)property.Key).ToPascalCase())); parameters.Append(string.Format(parameterTemplate, "bool", property.Key)); setters.Append(string.Format(setterTemplate, ((string)property.Key).ToPascalCase(), property.Key)); } } else if (((string)property.Value).All(char.IsDigit)) { checks.Append((string)property.Value); if (!propertiesDone) { properties.Add((string)property.Key, string.Format(propertyTemplate, "int", ((string)property.Key).ToPascalCase())); parameters.Append(string.Format(parameterTemplate, "int", property.Key)); setters.Append(string.Format(setterTemplate, ((string)property.Key).ToPascalCase(), property.Key)); } } else if (decimal.TryParse((string)property.Value, out _)) { checks.Append((string)property.Value); if (!propertiesDone) { properties.Add((string)property.Key, string.Format(propertyTemplate, "float", ((string)property.Key).ToPascalCase())); parameters.Append(string.Format(parameterTemplate, "float", property.Key)); setters.Append(string.Format(setterTemplate, ((string)property.Key).ToPascalCase(), property.Key)); } } else { //checks.Append('"'); checks.Append(property.Value); //checks.Append('"'); if (!propertiesDone) { properties.Add((string)property.Key, string.Format(propertyTemplate, "string", ((string)property.Key).ToPascalCase())); parameters.Append(string.Format(parameterTemplate, "string", property.Key)); setters.Append(string.Format(setterTemplate, ((string)property.Key).ToPascalCase(), property.Key)); } } checks.Append(" && "); } } if (state.@default != null) { defaultState = state.id; foreach (string key in properties.Keys.ToList()) { if (state.properties[key] == "true" || state.properties[key] == "false") { properties[key] += (string)state.properties[key] + ";"; } else if (((string)state.properties[key]).All(char.IsDigit)) { properties[key] += (string)state.properties[key] + ";"; } else if (decimal.TryParse((string)state.properties[key], out _)) { properties[key] += (string)state.properties[key] + ";"; } else { properties[key] += "\"" + (string)state.properties[key] + "\";"; } } } if (!propertiesDone) { propertiesDone = true; } if (hasProperties) { string checks1 = checks.ToString(); checks1 = checks1.Substring(0, checks1.Length - 4); stateGet.Append(string.Format(ifTemplate, checks1, "return " + state.id + ";")); checks1 = checks1.Replace("==", "="); checks1 = checks1.Replace(" && ", ";\n"); checks1 += ";"; stateSet.Append(string.Format(ifTemplate, "value == " + state.id, checks1)); } } StringBuilder propertiesStr = new(); foreach (KeyValuePair <string, string> entry in properties) { propertiesStr.Append(entry.Value); propertiesStr.Append('\n'); } if (hasProperties) { parameters.Length -= 2; } string b = string.Format(hasProperties ? blockTemplate : blockTemplate0, namedId.Replace("minecraft:", "").ToPascalCase(), namedId, minState, maxState, defaultState, stateGet, stateSet, propertiesStr, parameters, setters, protocolId); generatedBlocks.Add("Block" + namedId.Replace("minecraft:", "").ToPascalCase() + ".cs", b); } Console.WriteLine("Saving blocks..."); foreach (KeyValuePair <string, string> generated in generatedBlocks) { File.WriteAllText(Path.Combine(outputDirectory, generated.Key), generated.Value); } bitsPerBlock = (int)Math.Ceiling(Math.Log2(maxStateId)); Console.WriteLine("Bits per block: " + bitsPerBlock); }
public byte[] ToArray() { using (MemoryStream temp = RMSManager.Get().GetStream()) { if (!Client.CompressionEnabled) { VarInt varInt = new(Id); if (Length <= 0) { varInt.Write(temp); Data.BaseStream.WriteTo(temp); Length = (int)temp.Length; temp.Position = 0; temp.SetLength(0); } varInt.Value = Length; varInt.Write(temp); varInt.Value = Id; varInt.Write(temp); Data.BaseStream.WriteTo(temp); } else { byte[] output; int dataLength; using (MemoryStream input = RMSManager.Get().GetStream()) { new VarInt(Id).Write(input); Data.BaseStream.WriteTo(input); dataLength = (int)input.Position; if (dataLength >= Nylium.Server.Configuration.CompressionThreshold) { CompressionUtils.ZLibCompress(input.ToArray(), out output); } else { dataLength = 0; output = input.ToArray(); } } new VarInt(dataLength).Write(temp); int dataLengthLength = (int)temp.Position; temp.Position = 0; temp.SetLength(0); new VarInt(output.Length + dataLengthLength).Write(temp); new VarInt(dataLength).Write(temp); temp.Write(output); } return(Client.EncryptionEnabled ? Client.Encryptor.ProcessBytes(temp.ToArray(), 0, (int)temp.Length) : temp.ToArray()); } }
public static MinecraftPacket CreateClientPacket(MinecraftClient client, MemoryStream stream, ProtocolState state) { int id = -1; if (client.EncryptionEnabled) { byte[] decrypted = client.Decryptor.ProcessBytes(stream.ToArray(), 0, (int)stream.Length); stream.Position = 0; stream.SetLength(0); stream.Write(decrypted); stream.Position = 0; } if (!client.CompressionEnabled) { VarInt varInt = new(); varInt.Read(stream); varInt.Read(stream); id = varInt.Value; stream.Position = 0; } else { int packetLength = new VarInt(stream).Value; long _pos = stream.Position; int length = new VarInt(stream).Value; if (length == 0) // packet is uncompressed { id = new VarInt(stream).Value; byte[] data = new byte[packetLength - 1]; stream.Read(data, 0, data.Length); stream.Position = 0; stream.SetLength(0); new VarInt(id).Write(stream); stream.Write(data); stream.Position = 0; } else { byte[] compressedData = new byte[packetLength - _pos]; stream.Read(compressedData, 0, compressedData.Length); CompressionUtils.ZLibDecompress(compressedData, out byte[] data); using (MemoryStream output = RMSManager.Get().GetStream(data)) { _pos = output.Position; id = new VarInt(output).Value; } stream.Position = 0; stream.SetLength(0); stream.Write(data); stream.Position = 0; } } Func <MinecraftClient, Stream, MinecraftPacket> ctor; switch (state) { case ProtocolState.Handshaking: ctor = clientPacketConstructors[0][id]; return(ctor?.Invoke(client, stream)); case ProtocolState.Status: ctor = clientPacketConstructors[1][id]; return(ctor?.Invoke(client, stream)); case ProtocolState.Login: ctor = clientPacketConstructors[2][id]; return(ctor?.Invoke(client, stream)); case ProtocolState.Play: ctor = clientPacketConstructors[3][id]; return(ctor?.Invoke(client, stream)); } return(null); }