public static void EncryptionKeyResponse(RemoteClient client, MinecraftServer server, IPacket _packet) { var packet = (EncryptionKeyResponsePacket)_packet; var decryptedToken = server.CryptoServiceProvider.Decrypt(packet.VerificationToken, false); for (int i = 0; i < decryptedToken.Length; i++) { if (decryptedToken[i] != client.VerificationToken[i]) { client.Disconnect("Unable to authenticate."); return; } } client.SharedKey = server.CryptoServiceProvider.Decrypt(packet.SharedSecret, false); // Create a hash for session verification AsnKeyBuilder.AsnMessage encodedKey = AsnKeyBuilder.PublicKeyToX509(server.ServerKey); byte[] shaData = Encoding.UTF8.GetBytes(client.ServerId) .Concat(client.SharedKey) .Concat(encodedKey.GetBytes()).ToArray(); string hash = Cryptography.JavaHexDigest(shaData); // Talk to sessionserver.minecraft.net if (server.Settings.OnlineMode) { var webClient = new WebClient(); var webReader = new StreamReader(webClient.OpenRead( new Uri(string.Format(sessionCheckUri, client.Username, hash)))); string response = webReader.ReadToEnd(); webReader.Close(); var json = JToken.Parse(response); if (string.IsNullOrEmpty(response)) { client.Disconnect("Failed to verify username!"); return; } client.UUID = json["id"].Value <string>(); } client.NetworkStream = new AesStream(client.NetworkClient.GetStream(), client.SharedKey); client.NetworkManager.BaseStream = client.NetworkStream; client.EncryptionEnabled = true; var eventArgs = new ConnectionEstablishedEventArgs(client); server.OnConnectionEstablished(eventArgs); if (eventArgs.PermitConnection) { server.LogInPlayer(client); } else { client.Disconnect(eventArgs.DisconnectReason); } }
private void OnDestroy() { if (rc != null) { rc.Disconnect(); } }
public static void LoginStart(RemoteClient client, MinecraftServer server, IPacket _packet) { var packet = (LoginStartPacket)_packet; if (server.Clients.Any(c => c.IsLoggedIn && c.Username == packet.Username)) { client.Disconnect("You're already on this server!"); } else { client.Username = packet.Username; if (server.Settings.OnlineMode) { client.ServerId = CreateId(); } else { client.ServerId = CreateId(); client.UUID = Guid.NewGuid().ToJavaUUID(); } if (server.Settings.EnableEncryption) { client.SendPacket(CreateEncryptionRequest(client, server)); } else { server.LogInPlayer(client); } } }
public static void EncryptionKeyResponse(RemoteClient client, MinecraftServer server, IPacket _packet) { var packet = (EncryptionKeyResponsePacket)_packet; var decryptedToken = server.CryptoServiceProvider.Decrypt(packet.VerificationToken, false); for (int i = 0; i < decryptedToken.Length; i++) { if (decryptedToken[i] != client.VerificationToken[i]) { client.Disconnect("Unable to authenticate."); return; } } client.SharedKey = server.CryptoServiceProvider.Decrypt(packet.SharedSecret, false); client.SendPacket(new EncryptionKeyResponsePacket(new byte[0], new byte[0])); }
public static void EncryptionKeyResponse(RemoteClient client, Proxy proxy, IPacket _packet) { var packet = (EncryptionKeyResponsePacket)_packet; var decryptedToken = proxy.CryptoServiceProvider.Decrypt(packet.VerificationToken, false); for (int i = 0; i < decryptedToken.Length; i++) { if (decryptedToken[i] != client.VerificationToken[i]) { client.Disconnect("Unable to authenticate."); return; } } client.SharedKey = proxy.CryptoServiceProvider.Decrypt(packet.SharedSecret, false); client.SendPacket(new EncryptionKeyResponsePacket(new byte[0], new byte[0])); }
public static void EncryptionKeyResponse(RemoteClient client, MinecraftServer server, IPacket _packet) { var packet = (EncryptionKeyResponsePacket)_packet; var decryptedToken = server.CryptoServiceProvider.Decrypt(packet.VerificationToken, false); for (int i = 0; i < decryptedToken.Length; i++) { if (decryptedToken[i] != client.VerificationToken[i]) { client.Disconnect("Unable to authenticate."); return; } } client.SharedKey = server.CryptoServiceProvider.Decrypt(packet.SharedSecret, false); // Create a hash for session verification AsnKeyBuilder.AsnMessage encodedKey = AsnKeyBuilder.PublicKeyToX509(server.ServerKey); byte[] shaData = Encoding.UTF8.GetBytes(client.ServerId) .Concat(client.SharedKey) .Concat(encodedKey.GetBytes()).ToArray(); string hash = Cryptography.JavaHexDigest(shaData); // Talk to sessionserver.minecraft.net if (server.Settings.OnlineMode) { var webClient = new WebClient(); var webReader = new StreamReader(webClient.OpenRead( new Uri(string.Format(sessionCheckUri, client.Username, hash)))); string response = webReader.ReadToEnd(); webReader.Close(); var json = JToken.Parse(response); if (string.IsNullOrEmpty(response)) { client.Disconnect("Failed to verify username!"); return; } client.UUID = json["id"].Value<string>(); } client.NetworkStream = new AesStream(client.NetworkClient.GetStream(), client.SharedKey); client.NetworkManager.BaseStream = client.NetworkStream; client.EncryptionEnabled = true; var eventArgs = new ConnectionEstablishedEventArgs(client); server.OnConnectionEstablished(eventArgs); if (eventArgs.PermitConnection) server.LogInPlayer(client); else client.Disconnect(eventArgs.DisconnectReason); }
/// <summary> /// Connect to DF, and register basic RPC functions. /// </summary> void Connect() { blockRequest.blocks_needed = BlocksToFetch; networkClient = new RemoteClient(dfNetworkOut); bool success = networkClient.Connect(); if (!success) { networkClient.Disconnect(); networkClient = null; ModalPanel.Instance.Choice( "Armok Vision could not find a running instance of Dwarf Fortress!\n\n" + "Please make sure you have Dwarf Fortress running, with the latest version of DFHack installed.", Connect, QuitGame, "Retry", "Quit"); throw new UnityException("DF Connection Failure"); } BindStaticMethods(); if (dfWorldInfoCall != null) { dfWorldInfoCall.TryExecute(null, out netWorldInfo); if (netWorldInfo == null) { Debug.Log("World not loaded."); } else { Debug.Log("World Mode: " + netWorldInfo.mode); WorldMode = netWorldInfo.mode; } } if (GameSettings.Instance.game.askToUpdatePlugin) { CheckPlugin(); } else { Init(); } }
public static void LoginStart(RemoteClient client, MinecraftServer server, IPacket _packet) { var packet = (LoginStartPacket)_packet; if (server.Clients.Any(c => c.IsLoggedIn && c.Username == packet.Username)) client.Disconnect("You're already on this server!"); else { client.Username = packet.Username; if (server.Settings.OnlineMode) client.ServerId = CreateId(); else { client.ServerId = CreateId(); client.UUID = Guid.NewGuid().ToJavaUUID(); } if (server.Settings.EnableEncryption) client.SendPacket(CreateEncryptionRequest(client, server)); else server.LogInPlayer(client); } }
private void OnGUI() { if (GUILayout.Button("Read Raws")) { var client = new RemoteClient(); if (!client.Connect()) { return; } client.SuspendGame(); var getCreatureRaws = new RemoteFunction <EmptyMessage, CreatureRawList>(client, "GetCreatureRaws", "RemoteFortressReader"); var materialListCall = new RemoteFunction <EmptyMessage, MaterialList>(client, "GetMaterialList", "RemoteFortressReader"); var itemListCall = new RemoteFunction <EmptyMessage, MaterialList>(client, "GetItemList", "RemoteFortressReader"); var unitListCall = new RemoteFunction <EmptyMessage, UnitList>(client, "GetUnitList", "RemoteFortressReader"); client.ResumeGame(); creatureRaws = getCreatureRaws.Execute().creature_raws; var ExistingMatList = AssetDatabase.LoadAssetAtPath <MaterialRaws>("Assets/Resources/MaterialRaws.asset"); var ExistingItemList = AssetDatabase.LoadAssetAtPath <ItemRaws>("Assets/Resources/ItemRaws.asset"); MaterialRaws.Instance.MaterialList = materialListCall.Execute().material_list; ItemRaws.Instance.ItemList = itemListCall.Execute().material_list; units = unitListCall.Execute().creature_list; if (ExistingMatList == null) { AssetDatabase.CreateAsset(MaterialRaws.Instance, "Assets/Resources/MaterialRaws.asset"); } if (ExistingItemList == null) { AssetDatabase.CreateAsset(ItemRaws.Instance, "Assets/Resources/ItemRaws.asset"); } AssetDatabase.SaveAssets(); Debug.Log(string.Format("Pulled {0} creature raws from DF.", creatureRaws.Count)); if (MaterialCollection.Instance == null) { MaterialCollector.BuildMaterialCollection(); } MaterialCollection.Instance.PopulateMatTextures(); client.Disconnect(); //foreach (var raw in creatureRaws) //{ // raw.creature_id = BodyDefinition.GetCorrectedCreatureID(raw); //} RefilterList(); } if (creatureRaws != null) { EditorGUI.BeginChangeCheck(); filter = EditorGUILayout.TextField(filter); filterToken = EditorGUILayout.Toggle("Token", filterToken); filterName = EditorGUILayout.Toggle("Name", filterName); filterDescription = EditorGUILayout.Toggle("Description", filterDescription); filterParts = EditorGUILayout.Toggle("Parts", filterParts); bodyCategoryFilter = (CreatureBody.BodyCategory)EditorGUILayout.EnumPopup(bodyCategoryFilter); if (EditorGUI.EndChangeCheck()) { RefilterList(); } EditorGUILayout.Space(); GUILayout.BeginHorizontal(); if (GUILayout.Button("Sort by name")) { creatureRaws.Sort((x, y) => x.creature_id.CompareTo(y.creature_id)); RefilterList(); } if (GUILayout.Button("Sort by size")) { creatureRaws.Sort((x, y) => x.adultsize.CompareTo(y.adultsize)); RefilterList(); } if (GUILayout.Button("Sort by index")) { creatureRaws.Sort((x, y) => x.index.CompareTo(y.index)); RefilterList(); } GUILayout.EndHorizontal(); showRaces = EditorGUILayout.Foldout(showRaces, "Races"); if (showRaces) { raceScroll = EditorGUILayout.BeginScrollView(raceScroll); foreach (var creature in filteredRaws) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel(string.Format("{0} ({1})", creature.creature_id, creature.name[0])); EditorGUILayout.BeginVertical(); foreach (var caste in creature.caste) { if (GUILayout.Button(string.Format("{0} ({1})", caste.caste_id, caste.caste_name[0]))) { var creatureBase = new GameObject().AddComponent <CreatureBody>(); creatureBase.name = caste.caste_name[0]; creatureBase.race = creature; creatureBase.caste = caste; creatureBase.MakeBody(); Selection.SetActiveObjectWithContext(creatureBase, null); } } EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndScrollView(); if (GUILayout.Button("Dump Part Categories")) { var path = EditorUtility.SaveFilePanel("Save bodypart list", "", "Bodyparts.csv", "csv"); if (!string.IsNullOrEmpty(path)) { Dictionary <string, Dictionary <string, ChildCount> > parts = new Dictionary <string, Dictionary <string, ChildCount> >(); foreach (var creature in filteredRaws) { foreach (var caste in creature.caste) { if (bodyCategoryFilter != CreatureBody.BodyCategory.None && bodyCategoryFilter != CreatureBody.FindBodyCategory(caste)) { continue; } for (int i = 0; i < caste.body_parts.Count; i++) { var part = caste.body_parts[i]; //this is an internal part, and doesn't need modeling. if (part.flags[(int)BodyPartFlags.BodyPartRawFlags.INTERNAL]) { continue; } if (!parts.ContainsKey(part.category)) { parts[part.category] = new Dictionary <string, ChildCount>(); } Dictionary <string, int> childCounts = new Dictionary <string, int>(); foreach (var sub in caste.body_parts) { if (sub.parent != i) { continue; } if (sub.flags[(int)BodyPartFlags.BodyPartRawFlags.INTERNAL]) { continue; } if (!childCounts.ContainsKey(sub.category)) { childCounts[sub.category] = 1; } else { childCounts[sub.category]++; } } foreach (var item in childCounts) { if (!parts[part.category].ContainsKey(item.Key)) { parts[part.category][item.Key] = new ChildCount(); } if (parts[part.category][item.Key].min > item.Value) { parts[part.category][item.Key].min = item.Value; } if (parts[part.category][item.Key].max < item.Value) { parts[part.category][item.Key].max = item.Value; } } } } } using (var writer = new StreamWriter(path)) { foreach (var parent in parts) { writer.Write("\"" + parent.Key + "\","); foreach (var child in parent.Value) { writer.Write(string.Format("\"{0}\",{1},{2},", child.Key, child.Value.min, child.Value.max)); } writer.WriteLine(); } } } } if (GUILayout.Button("Place all races")) { var watch = System.Diagnostics.Stopwatch.StartNew(); CreatureBody prevCreature = null; foreach (var creature in filteredRaws) { var creatureBase = new GameObject().AddComponent <CreatureBody>(); creatureBase.name = creature.caste[0].caste_name[0]; creatureBase.race = creature; creatureBase.caste = creature.caste[0]; creatureBase.MakeBody(); if (prevCreature != null) { creatureBase.transform.position = new Vector3(prevCreature.transform.position.x + prevCreature.bounds.max.x - creatureBase.bounds.min.x, 0, 0); } prevCreature = creatureBase; } watch.Stop(); Debug.Log(string.Format("Took {0}ms to create {1} creatures, averaging {2}ms per creature.", watch.ElapsedMilliseconds, filteredRaws.Count, (float)watch.ElapsedMilliseconds / filteredRaws.Count)); } } showUnits = EditorGUILayout.Foldout(showUnits, "Units"); if (showUnits) { unitScroll = EditorGUILayout.BeginScrollView(unitScroll); foreach (var unit in units) { string name = unit.name; if (string.IsNullOrEmpty(name)) { name = creatureRaws[unit.race.mat_type].caste[unit.race.mat_index].caste_name[0]; } if (!string.IsNullOrEmpty(filter) && (filterParts || filterName)) { bool matched = false; if (filterName) { matched = name.ToUpper().Contains(filter.ToUpper()); } if (filterParts) { foreach (var item in unit.inventory) { if (!ItemRaws.Instance.ContainsKey(item.item.type)) { continue; } matched = ItemRaws.Instance[item.item.type].id.ToUpper().Contains(filter.ToUpper()); if (matched) { break; } } } if (!matched) { continue; } } if (GUILayout.Button(name)) { var creatureBase = new GameObject().AddComponent <CreatureBody>(); creatureBase.name = name; creatureBase.race = creatureRaws[unit.race.mat_type]; creatureBase.caste = creatureRaws[unit.race.mat_type].caste[unit.race.mat_index]; creatureBase.unit = unit; creatureBase.MakeBody(); creatureBase.UpdateUnit(unit); Selection.SetActiveObjectWithContext(creatureBase, null); } } EditorGUILayout.EndScrollView(); if (GUILayout.Button("Place all units")) { var watch = System.Diagnostics.Stopwatch.StartNew(); CreatureBody prevCreature = null; foreach (var unit in units) { string name = unit.name; if (string.IsNullOrEmpty(name)) { name = creatureRaws[unit.race.mat_type].caste[unit.race.mat_index].caste_name[0]; } if (!string.IsNullOrEmpty(filter) && (filterParts || filterName)) { bool matched = false; if (filterToken) { matched = creatureRaws[unit.race.mat_type].creature_id.ToUpper().Contains(filter.ToUpper()); } if (filterName) { matched = name.ToUpper().Contains(filter.ToUpper()); } if (filterParts) { foreach (var item in unit.inventory) { if (!ItemRaws.Instance.ContainsKey(item.item.type)) { continue; } matched = ItemRaws.Instance[item.item.type].id.ToUpper().Contains(filter.ToUpper()); if (matched) { break; } } } if (!matched) { continue; } } var creatureBase = new GameObject().AddComponent <CreatureBody>(); creatureBase.name = name; creatureBase.race = creatureRaws[unit.race.mat_type]; creatureBase.caste = creatureRaws[unit.race.mat_type].caste[unit.race.mat_index]; creatureBase.unit = unit; creatureBase.MakeBody(); creatureBase.UpdateUnit(unit); creatureBase.transform.localRotation = Quaternion.identity; if (prevCreature != null) { creatureBase.transform.position = new Vector3(prevCreature.transform.position.x + prevCreature.bounds.max.x - creatureBase.bounds.min.x, 0, 0); } prevCreature = creatureBase; } watch.Stop(); Debug.Log(string.Format("Took {0}ms to create {1} creatures, averaging {2}ms per creature.", watch.ElapsedMilliseconds, filteredRaws.Count, (float)watch.ElapsedMilliseconds / filteredRaws.Count)); } } } }
private void OnGUI() { if (GUILayout.Button("Read Raws")) { var client = new RemoteClient(); if (!client.Connect()) { return; } var getCreatureRaws = new RemoteFunction <EmptyMessage, CreatureRawList>(client, "GetCreatureRaws", "RemoteFortressReader"); creatureRaws = getCreatureRaws.Execute().creature_raws; Debug.Log(string.Format("Pulled {0} creature raws from DF.", creatureRaws.Count)); client.Disconnect(); creatureRaws.Sort((x, y) => x.creature_id.CompareTo(y.creature_id)); RefilterList(); } if (creatureRaws != null) { EditorGUI.BeginChangeCheck(); filter = EditorGUILayout.TextField(filter); bodyCategoryFilter = (CreatureBody.BodyCategory)EditorGUILayout.EnumPopup(bodyCategoryFilter); if (EditorGUI.EndChangeCheck()) { RefilterList(); } if (GUILayout.Button("Dump Part Categories")) { var path = EditorUtility.SaveFilePanel("Save bodypart list", "", "Bodyparts.csv", "csv"); Dictionary <string, Dictionary <string, ChildCount> > parts = new Dictionary <string, Dictionary <string, ChildCount> >(); foreach (var creature in filteredRaws) { foreach (var caste in creature.caste) { if (bodyCategoryFilter != CreatureBody.BodyCategory.None && bodyCategoryFilter != CreatureBody.FindBodyCategory(caste)) { continue; } for (int i = 0; i < caste.body_parts.Count; i++) { var part = caste.body_parts[i]; //this is an internal part, and doesn't need modeling. if (part.flags[(int)BodyPartFlags.BodyPartRawFlags.INTERNAL]) { continue; } if (!parts.ContainsKey(part.category)) { parts[part.category] = new Dictionary <string, ChildCount>(); } Dictionary <string, int> childCounts = new Dictionary <string, int>(); foreach (var sub in caste.body_parts) { if (sub.parent != i) { continue; } if (sub.flags[(int)BodyPartFlags.BodyPartRawFlags.INTERNAL]) { continue; } if (!childCounts.ContainsKey(sub.category)) { childCounts[sub.category] = 1; } else { childCounts[sub.category]++; } } foreach (var item in childCounts) { if (!parts[part.category].ContainsKey(item.Key)) { parts[part.category][item.Key] = new ChildCount(); } if (parts[part.category][item.Key].min > item.Value) { parts[part.category][item.Key].min = item.Value; } if (parts[part.category][item.Key].max < item.Value) { parts[part.category][item.Key].max = item.Value; } } } } } using (var writer = new StreamWriter(path)) { foreach (var parent in parts) { writer.Write("\"" + parent.Key + "\","); foreach (var child in parent.Value) { writer.Write(string.Format("\"{0}\",{1},{2},", child.Key, child.Value.min, child.Value.max)); } writer.WriteLine(); } } } GUILayout.BeginHorizontal(); if (GUILayout.Button("Sort by name")) { creatureRaws.Sort((x, y) => x.creature_id.CompareTo(y.creature_id)); RefilterList(); } if (GUILayout.Button("Sort by size")) { creatureRaws.Sort((x, y) => x.adultsize.CompareTo(y.adultsize)); RefilterList(); } GUILayout.EndHorizontal(); scrollPosition = GUILayout.BeginScrollView(scrollPosition); foreach (var creature in filteredRaws) { GUILayout.BeginHorizontal(); GUILayout.Label(creature.creature_id); foreach (var caste in creature.caste) { if (GUILayout.Button(caste.caste_id)) { var creatureBase = new GameObject().AddComponent <CreatureBody>(); creatureBase.name = creature.creature_id + "_" + caste.caste_id; creatureBase.race = creature; creatureBase.caste = caste; creatureBase.MakeBody(); Selection.SetActiveObjectWithContext(creatureBase, null); } } GUILayout.EndHorizontal(); } GUILayout.EndScrollView(); if (GUILayout.Button("Place all creatures")) { var watch = System.Diagnostics.Stopwatch.StartNew(); CreatureBody prevCreature = null; foreach (var creature in filteredRaws) { var creatureBase = new GameObject().AddComponent <CreatureBody>(); creatureBase.name = creature.creature_id + "_" + creature.caste[0].caste_id; creatureBase.race = creature; creatureBase.caste = creature.caste[0]; creatureBase.MakeBody(); creatureBase.transform.rotation = Quaternion.LookRotation(Vector3.back); if (prevCreature != null) { creatureBase.transform.position = new Vector3(prevCreature.transform.position.x + prevCreature.bounds.max.x - creatureBase.bounds.min.x, 0, 0); } prevCreature = creatureBase; } watch.Stop(); Debug.Log(string.Format("Took {0}ms to create {1} creatures, averaging {2}ms per creature.", watch.ElapsedMilliseconds, filteredRaws.Count, (float)watch.ElapsedMilliseconds / filteredRaws.Count)); } } }
public bool HandlePacket(IPacket packet) { Console.WriteLine(packet.GetPacketID + " <- " + packet.GetType().ToString()); if (packet.PacketGood == false) { _client.Disconnect(); return(false); } if (packet is Handshake) { if (((Handshake)packet).ProtocolVersion != Version) { Trace.WriteLine(string.Format("Protocol versiom mismatch! Check handling for {0}", this.GetType().ToString())); _client.Disconnect(); return(false); } if (((Handshake)packet).NextState == NextState.Status) { _client.State = ClientState.Status; } else if (((Handshake)packet).NextState == NextState.Login) { _client.State = ClientState.Login; } else { _client.Disconnect(); return(false); } return(true); } if (packet is StatusRequest) { _client.Data.StatusRequest = true; _client.Data.StatusRespond = false; return(true); } if (packet is StatusPing) { _client.Data.StatusPingPayload = ((StatusPing)packet).StatusPingPayload; _client.Data.StatusPing = true; } if (packet is LoginStart) { _client.Data.Username = ((LoginStart)packet).Name; _client.Data.LoginRespondRequired = true; return(true); } if (packet is LoginEncryptionResponse) { _client.Data.LoginSecret = ((LoginEncryptionResponse)packet).Secret; _client.Data.LoginVerifyToken = ((LoginEncryptionResponse)packet).Token; _client.Data.LoginEncryptionResponseRequired = true; return(true); } return(_handlePacket(packet)); }
public static void ClientStatus(RemoteClient client, MinecraftServer server, IPacket _packet) { var packet = (ClientStatusPacket)_packet; if (packet.Status == ClientStatusPacket.ClientStatus.InitialSpawn) { // Create a hash for session verification AsnKeyBuilder.AsnMessage encodedKey = AsnKeyBuilder.PublicKeyToX509(server.ServerKey); byte[] shaData = Encoding.UTF8.GetBytes(client.AuthenticationHash) .Concat(client.SharedKey) .Concat(encodedKey.GetBytes()).ToArray(); string hash = Cryptography.JavaHexDigest(shaData); // Talk to session.minecraft.net if (server.Settings.OnlineMode) { var webClient = new WebClient(); var webReader = new StreamReader(webClient.OpenRead( new Uri(string.Format(sessionCheckUri, client.Username, hash)))); string response = webReader.ReadToEnd(); webReader.Close(); if (response != "YES") { client.Disconnect("Failed to verify username!"); return; } } var eventArgs = new ConnectionEstablishedEventArgs(client); server.OnConnectionEstablished(eventArgs); if (eventArgs.PermitConnection) server.LogInPlayer(client); else client.Disconnect(eventArgs.DisconnectReason); } else if (packet.Status == ClientStatusPacket.ClientStatus.Respawn) { var world = client.Entity.World; client.Entity.Position = new Vector3( client.Entity.SpawnPoint.X, // FIXME: This seems to drop the player camera from half the height of a login spawn client.Entity.SpawnPoint.Y, client.Entity.SpawnPoint.Z); client.Entity.Health = client.Entity.MaxHealth; client.Entity.Food = 20; client.Entity.FoodSaturation = 20; server.EntityManager.SpawnEntity(world, client.Entity); client.SendPacket(new UpdateHealthPacket(client.Entity.Health, client.Entity.Food, client.Entity.FoodSaturation)); client.SendPacket(new RespawnPacket(Dimension.Overworld, server.Settings.Difficulty, client.GameMode, World.Height, world.WorldGenerator.GeneratorName)); client.SendPacket(new PlayerPositionAndLookPacket(client.Entity.Position.X, client.Entity.Position.Y, client.Entity.Position.Z, client.Entity.Position.Y + PlayerEntity.Height, client.Entity.Yaw, client.Entity.Pitch, true)); } }