public void ClientRead(IReadMessage incMsg) { cachedServerListInfo = null; ServerName = incMsg.ReadString(); ServerMessageText = incMsg.ReadString(); MaxPlayers = incMsg.ReadByte(); HasPassword = incMsg.ReadBoolean(); IsPublic = incMsg.ReadBoolean(); GameMain.NetLobbyScreen.SetPublic(IsPublic); AllowFileTransfers = incMsg.ReadBoolean(); incMsg.ReadPadBits(); TickRate = incMsg.ReadRangedInteger(1, 60); GameMain.NetworkMember.TickRate = TickRate; ReadExtraCargo(incMsg); Voting.ClientRead(incMsg); bool isAdmin = incMsg.ReadBoolean(); incMsg.ReadPadBits(); if (isAdmin) { ClientAdminRead(incMsg); } }
public bool ReadExtraCargo(IReadMessage msg) { bool changed = false; UInt32 count = msg.ReadUInt32(); if (ExtraCargo == null || count != ExtraCargo.Count) { changed = true; } Dictionary <ItemPrefab, int> extraCargo = new Dictionary <ItemPrefab, int>(); for (int i = 0; i < count; i++) { string prefabIdentifier = msg.ReadString(); string prefabName = msg.ReadString(); byte amount = msg.ReadByte(); var itemPrefab = string.IsNullOrEmpty(prefabIdentifier) ? MapEntityPrefab.Find(prefabName, null, showErrorMessages: false) as ItemPrefab : MapEntityPrefab.Find(prefabName, prefabIdentifier, showErrorMessages: false) as ItemPrefab; if (itemPrefab != null && amount > 0) { if (changed || !ExtraCargo.ContainsKey(itemPrefab) || ExtraCargo[itemPrefab] != amount) { changed = true; } extraCargo.Add(itemPrefab, amount); } } if (changed) { ExtraCargo = extraCargo; } return(changed); }
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime) { for (int i = 0; i < customInterfaceElementList.Count; i++) { if (customInterfaceElementList[i].HasPropertyName) { if (!customInterfaceElementList[i].IsIntegerInput) { TextChanged(customInterfaceElementList[i], msg.ReadString()); } else { int.TryParse(msg.ReadString(), out int value); ValueChanged(customInterfaceElementList[i], value); } } else { bool elementState = msg.ReadBoolean(); if (customInterfaceElementList[i].ContinuousSignal) { ((GUITickBox)uiElements[i]).Selected = elementState; TickBoxToggled(customInterfaceElementList[i], elementState); } else if (elementState) { ButtonClicked(customInterfaceElementList[i]); } } } UpdateSignalsProjSpecific(); }
public void ClientRead(IReadMessage inc) { AllowSubVoting = inc.ReadBoolean(); if (allowSubVoting) { UpdateVoteTexts(null, VoteType.Sub); int votableCount = inc.ReadByte(); for (int i = 0; i < votableCount; i++) { int votes = inc.ReadByte(); string subName = inc.ReadString(); List <Submarine> serversubs = new List <Submarine>(); foreach (GUIComponent item in GameMain.NetLobbyScreen?.SubList?.Content?.Children) { if (item.UserData != null && item.UserData is Submarine) { serversubs.Add(item.UserData as Submarine); } } Submarine sub = serversubs.FirstOrDefault(sm => sm.Name == subName); SetVoteText(GameMain.NetLobbyScreen.SubList, sub, votes); } } AllowModeVoting = inc.ReadBoolean(); if (allowModeVoting) { UpdateVoteTexts(null, VoteType.Mode); int votableCount = inc.ReadByte(); for (int i = 0; i < votableCount; i++) { int votes = inc.ReadByte(); string modeIdentifier = inc.ReadString(); GameModePreset mode = GameModePreset.List.Find(m => m.Identifier == modeIdentifier); SetVoteText(GameMain.NetLobbyScreen.ModeList, mode, votes); } } AllowEndVoting = inc.ReadBoolean(); if (AllowEndVoting) { GameMain.NetworkMember.EndVoteCount = inc.ReadByte(); GameMain.NetworkMember.EndVoteMax = inc.ReadByte(); } AllowVoteKick = inc.ReadBoolean(); GameMain.NetworkMember.ConnectedClients.ForEach(c => c.SetVote(VoteType.StartRound, false)); byte readyClientCount = inc.ReadByte(); for (int i = 0; i < readyClientCount; i++) { byte clientID = inc.ReadByte(); var matchingClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == clientID); matchingClient?.SetVote(VoteType.StartRound, true); } UpdateVoteTexts(GameMain.NetworkMember.ConnectedClients, VoteType.StartRound); inc.ReadPadBits(); }
public void ClientAdminRead(IReadMessage incMsg) { bool hasPermission = incMsg.ReadBoolean(); if (!hasPermission) { incMsg.ReadPadBits(); return; } bool isOwner = incMsg.ReadBoolean(); incMsg.ReadPadBits(); bannedPlayers.Clear(); UInt32 bannedPlayerCount = incMsg.ReadVariableUInt32(); for (int i = 0; i < (int)bannedPlayerCount; i++) { string name = incMsg.ReadString(); UInt16 uniqueIdentifier = incMsg.ReadUInt16(); bool isRangeBan = incMsg.ReadBoolean(); bool includesExpiration = incMsg.ReadBoolean(); incMsg.ReadPadBits(); DateTime?expiration = null; if (includesExpiration) { double hoursFromNow = incMsg.ReadDouble(); expiration = DateTime.Now + TimeSpan.FromHours(hoursFromNow); } string reason = incMsg.ReadString(); string endPoint = ""; UInt64 steamID = 0; if (isOwner) { endPoint = incMsg.ReadString(); steamID = incMsg.ReadUInt64(); } else { endPoint = "Endpoint concealed by host"; steamID = 0; } bannedPlayers.Add(new BannedPlayer(name, uniqueIdentifier, isRangeBan, endPoint, steamID, reason, expiration)); } if (banFrame != null) { var parent = banFrame.Parent; parent.RemoveChild(banFrame); CreateBanFrame(parent); } }
public static CharacterInfo ClientRead(string speciesName, IReadMessage inc) { ushort infoID = inc.ReadUInt16(); string newName = inc.ReadString(); string originalName = inc.ReadString(); int gender = inc.ReadByte(); int race = inc.ReadByte(); int headSpriteID = inc.ReadByte(); int hairIndex = inc.ReadByte(); int beardIndex = inc.ReadByte(); int moustacheIndex = inc.ReadByte(); int faceAttachmentIndex = inc.ReadByte(); string ragdollFile = inc.ReadString(); string jobIdentifier = inc.ReadString(); int variant = inc.ReadByte(); JobPrefab jobPrefab = null; Dictionary <string, float> skillLevels = new Dictionary <string, float>(); if (!string.IsNullOrEmpty(jobIdentifier)) { jobPrefab = JobPrefab.Get(jobIdentifier); byte skillCount = inc.ReadByte(); for (int i = 0; i < skillCount; i++) { string skillIdentifier = inc.ReadString(); float skillLevel = inc.ReadSingle(); skillLevels.Add(skillIdentifier, skillLevel); } } // TODO: animations CharacterInfo ch = new CharacterInfo(speciesName, newName, originalName, jobPrefab, ragdollFile, variant) { ID = infoID, }; ch.RecreateHead(headSpriteID, (Race)race, (Gender)gender, hairIndex, beardIndex, moustacheIndex, faceAttachmentIndex); if (ch.Job != null) { foreach (KeyValuePair <string, float> skill in skillLevels) { Skill matchingSkill = ch.Job.Skills.Find(s => s.Identifier == skill.Key); if (matchingSkill == null) { ch.Job.Skills.Add(new Skill(skill.Key, skill.Value)); continue; } matchingSkill.Level = skill.Value; } ch.Job.Skills.RemoveAll(s => !skillLevels.ContainsKey(s.Identifier)); } return(ch); }
public bool ServerAdminRead(IReadMessage incMsg, Client c) { if (!c.HasPermission(ClientPermissions.ManageSettings)) { bool enabled = incMsg.ReadBoolean(); incMsg.ReadPadBits(); UInt16 removeCount = incMsg.ReadUInt16(); incMsg.BitPosition += removeCount * 4 * 8; UInt16 addCount = incMsg.ReadUInt16(); for (int i = 0; i < addCount; i++) { incMsg.ReadString(); //skip name incMsg.ReadString(); //skip ip } return(false); } else { bool prevEnabled = Enabled; bool enabled = incMsg.ReadBoolean(); incMsg.ReadPadBits(); Enabled = enabled; UInt16 removeCount = incMsg.ReadUInt16(); for (int i = 0; i < removeCount; i++) { UInt16 id = incMsg.ReadUInt16(); WhiteListedPlayer whitelistedPlayer = whitelistedPlayers.Find(p => p.UniqueIdentifier == id); if (whitelistedPlayer != null) { GameServer.Log(GameServer.ClientLogName(c) + " removed " + whitelistedPlayer.Name + " from whitelist (" + whitelistedPlayer.IP + ")", ServerLog.MessageType.ConsoleUsage); RemoveFromWhiteList(whitelistedPlayer); } } UInt16 addCount = incMsg.ReadUInt16(); for (int i = 0; i < addCount; i++) { string name = incMsg.ReadString(); string ip = incMsg.ReadString(); GameServer.Log(GameServer.ClientLogName(c) + " added " + name + " to whitelist (" + ip + ")", ServerLog.MessageType.ConsoleUsage); AddToWhiteList(name, ip); } bool changed = removeCount > 0 || addCount > 0 || prevEnabled != enabled; if (changed) { Save(); } return(changed); } }
public static void ReadPermissions(IReadMessage inc, out ClientPermissions permissions, out List <DebugConsole.Command> permittedCommands) { UInt16 permissionsInt = inc.ReadUInt16(); permissions = ClientPermissions.None; permittedCommands = new List <DebugConsole.Command>(); try { permissions = (ClientPermissions)permissionsInt; } catch (InvalidCastException) { return; } if (permissions.HasFlag(ClientPermissions.ConsoleCommands)) { UInt16 commandCount = inc.ReadUInt16(); for (int i = 0; i < commandCount; i++) { string commandName = inc.ReadString(); var consoleCommand = DebugConsole.Commands.Find(c => c.names.Contains(commandName)); if (consoleCommand != null) { permittedCommands.Add(consoleCommand); } } } }
private void ReadStatus(IReadMessage msg) { bool isDead = msg.ReadBoolean(); if (isDead) { CauseOfDeathType causeOfDeathType = (CauseOfDeathType)msg.ReadRangedInteger(0, Enum.GetValues(typeof(CauseOfDeathType)).Length - 1); AfflictionPrefab causeOfDeathAffliction = null; if (causeOfDeathType == CauseOfDeathType.Affliction) { string afflictionName = msg.ReadString(); if (!AfflictionPrefab.Prefabs.ContainsKey(afflictionName)) { string errorMsg = $"Error in CharacterNetworking.ReadStatus: affliction not found ({afflictionName})"; causeOfDeathType = CauseOfDeathType.Unknown; GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ReadStatus:AfflictionIndexOutOfBounts", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); } else { causeOfDeathAffliction = AfflictionPrefab.Prefabs[afflictionName]; } } byte severedLimbCount = msg.ReadByte(); if (!IsDead) { if (causeOfDeathType == CauseOfDeathType.Pressure) { Implode(true); } else { Kill(causeOfDeathType, causeOfDeathAffliction?.Instantiate(1.0f), true); } } for (int i = 0; i < severedLimbCount; i++) { int severedJointIndex = msg.ReadByte(); if (severedJointIndex < 0 || severedJointIndex >= AnimController.LimbJoints.Length) { string errorMsg = $"Error in CharacterNetworking.ReadStatus: severed joint index out of bounds (index: {severedJointIndex}, joint count: {AnimController.LimbJoints.Length})"; GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ReadStatus:JointIndexOutOfBounts", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); } else { AnimController.SeverLimbJoint(AnimController.LimbJoints[severedJointIndex]); } } } else { if (IsDead) { Revive(); } CharacterHealth.ClientRead(msg); } }
private void ReadTraitorStatus(IReadMessage msg) { IsTraitor = msg.ReadBoolean(); if (IsTraitor) { TraitorCurrentObjective = msg.ReadString(); } }
public TraitorMissionResult(IReadMessage inc) { MissionIdentifier = inc.ReadString(); EndMessage = inc.ReadString(); Success = inc.ReadBoolean(); byte characterCount = inc.ReadByte(); for (int i = 0; i < characterCount; i++) { UInt16 characterID = inc.ReadUInt16(); var character = Entity.FindEntityByID(characterID) as Character; if (character != null) { Characters.Add(character); } } }
public void ClientAdminRead(IReadMessage incMsg) { bool hasPermission = incMsg.ReadBoolean(); if (!hasPermission) { incMsg.ReadPadBits(); return; } bool isOwner = incMsg.ReadBoolean(); incMsg.ReadPadBits(); bannedPlayers.Clear(); UInt32 bannedPlayerCount = incMsg.ReadVariableUInt32(); for (int i = 0; i < (int)bannedPlayerCount; i++) { string name = incMsg.ReadString(); UInt16 uniqueIdentifier = incMsg.ReadUInt16(); bool isRangeBan = incMsg.ReadBoolean(); incMsg.ReadPadBits(); string ip = ""; UInt64 steamID = 0; if (isOwner) { ip = incMsg.ReadString(); steamID = incMsg.ReadUInt64(); } else { ip = "IP concealed by host"; steamID = 0; } bannedPlayers.Add(new BannedPlayer(name, uniqueIdentifier, isRangeBan, ip, steamID)); } if (banFrame != null) { var parent = banFrame.Parent; parent.RemoveChild(banFrame); CreateBanFrame(parent); } }
public void ServerRead(ClientNetObject type, IReadMessage msg, Client c) { bool[] elementStates = new bool[customInterfaceElementList.Count]; string[] elementValues = new string[customInterfaceElementList.Count]; for (int i = 0; i < customInterfaceElementList.Count; i++) { if (customInterfaceElementList[i].HasPropertyName) { elementValues[i] = msg.ReadString(); } else { elementStates[i] = msg.ReadBoolean(); } } CustomInterfaceElement clickedButton = null; if ((c.Character != null && DrawHudWhenEquipped && item.ParentInventory?.Owner == c.Character) || item.CanClientAccess(c)) { for (int i = 0; i < customInterfaceElementList.Count; i++) { if (customInterfaceElementList[i].HasPropertyName) { if (!customInterfaceElementList[i].IsIntegerInput) { TextChanged(customInterfaceElementList[i], elementValues[i]); } else { int.TryParse(elementValues[i], out int value); ValueChanged(customInterfaceElementList[i], value); } } else if (customInterfaceElementList[i].ContinuousSignal) { TickBoxToggled(customInterfaceElementList[i], elementStates[i]); } else if (elementStates[i]) { clickedButton = customInterfaceElementList[i]; ButtonClicked(customInterfaceElementList[i]); } } } //notify all clients of the new state GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.GetComponentIndex(this), clickedButton }); item.CreateServerEvent(this); }
public void ClientAdminRead(IReadMessage incMsg) { bool hasPermission = incMsg.ReadBoolean(); if (!hasPermission) { incMsg.ReadPadBits(); return; } bool isOwner = incMsg.ReadBoolean(); localEnabled = incMsg.ReadBoolean(); Enabled = localEnabled; incMsg.ReadPadBits(); whitelistedPlayers.Clear(); UInt32 bannedPlayerCount = incMsg.ReadVariableUInt32(); for (int i = 0; i < (int)bannedPlayerCount; i++) { string name = incMsg.ReadString(); UInt16 uniqueIdentifier = incMsg.ReadUInt16(); string ip = ""; if (isOwner) { ip = incMsg.ReadString(); } else { ip = "IP concealed by host"; } whitelistedPlayers.Add(new WhiteListedPlayer(name, uniqueIdentifier, ip)); } if (whitelistFrame != null) { CreateWhiteListFrame(whitelistFrame.Parent); } }
private void StartSubmarineVote(IReadMessage inc, VoteType voteType, Client sender) { string subName = inc.ReadString(); SubVote.Sub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName); SubVote.DeliveryFee = voteType == VoteType.SwitchSub ? GameMain.GameSession.Map.DistanceToClosestLocationWithOutpost(GameMain.GameSession.Map.CurrentLocation, out Location endLocation) : 0; SubVote.VoteType = voteType; SubVote.State = VoteState.Started; SubVote.VoteStarter = sender; VoteRunning = true; sender.SetVote(voteType, 2); }
public void ClientRead(IReadMessage incMsg) { ServerName = incMsg.ReadString(); ServerMessageText = incMsg.ReadString(); MaxPlayers = incMsg.ReadByte(); HasPassword = incMsg.ReadBoolean(); isPublic = incMsg.ReadBoolean(); incMsg.ReadPadBits(); TickRate = incMsg.ReadRangedInteger(1, 60); GameMain.NetworkMember.TickRate = TickRate; ReadExtraCargo(incMsg); Voting.ClientRead(incMsg); bool isAdmin = incMsg.ReadBoolean(); incMsg.ReadPadBits(); if (isAdmin) { ClientAdminRead(incMsg); } }
public void ServerRead(ClientNetObject type, IReadMessage msg, Client c) { bool[] elementStates = new bool[customInterfaceElementList.Count]; string[] elementValues = new string[customInterfaceElementList.Count]; for (int i = 0; i < customInterfaceElementList.Count; i++) { if (!string.IsNullOrEmpty(customInterfaceElementList[i].PropertyName)) { elementValues[i] = msg.ReadString(); } else { elementStates[i] = msg.ReadBoolean(); } } CustomInterfaceElement clickedButton = null; if (item.CanClientAccess(c)) { for (int i = 0; i < customInterfaceElementList.Count; i++) { if (!string.IsNullOrEmpty(customInterfaceElementList[i].PropertyName)) { TextChanged(customInterfaceElementList[i], elementValues[i]); } else if (customInterfaceElementList[i].ContinuousSignal) { TickBoxToggled(customInterfaceElementList[i], elementStates[i]); } else if (elementStates[i]) { clickedButton = customInterfaceElementList[i]; ButtonClicked(customInterfaceElementList[i]); } } } //notify all clients of the new state GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.GetComponentIndex(this), clickedButton }); item.CreateServerEvent(this); }
public void ServerRead(ClientNetObject type, IReadMessage msg, Client c) { string newOutputValue = msg.ReadString(); if (item.CanClientAccess(c)) { if (newOutputValue.Length > MaxMessageLength) { newOutputValue = newOutputValue.Substring(0, MaxMessageLength); } GameServer.Log(GameServer.CharacterLogName(c.Character) + " entered \"" + newOutputValue + "\" on " + item.Name, ServerLog.MessageType.ItemInteraction); OutputValue = newOutputValue; item.SendSignal(0, newOutputValue, "signal_out", null); item.CreateServerEvent(this); } }
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime) { for (int i = 0; i < customInterfaceElementList.Count; i++) { if (!string.IsNullOrEmpty(customInterfaceElementList[i].PropertyName)) { TextChanged(customInterfaceElementList[i], msg.ReadString()); } else { bool elementState = msg.ReadBoolean(); if (customInterfaceElementList[i].ContinuousSignal) { ((GUITickBox)uiElements[i]).Selected = elementState; TickBoxToggled(customInterfaceElementList[i], elementState); } else if (elementState) { ButtonClicked(customInterfaceElementList[i]); } } } }
public static CharacterInfo ClientRead(string speciesName, IReadMessage inc) { ushort infoID = inc.ReadUInt16(); string newName = inc.ReadString(); string originalName = inc.ReadString(); int gender = inc.ReadByte(); int race = inc.ReadByte(); int headSpriteID = inc.ReadByte(); int hairIndex = inc.ReadByte(); int beardIndex = inc.ReadByte(); int moustacheIndex = inc.ReadByte(); int faceAttachmentIndex = inc.ReadByte(); Color skinColor = inc.ReadColorR8G8B8(); Color hairColor = inc.ReadColorR8G8B8(); Color facialHairColor = inc.ReadColorR8G8B8(); string ragdollFile = inc.ReadString(); string jobIdentifier = inc.ReadString(); int variant = inc.ReadByte(); JobPrefab jobPrefab = null; Dictionary <string, float> skillLevels = new Dictionary <string, float>(); if (!string.IsNullOrEmpty(jobIdentifier)) { jobPrefab = JobPrefab.Get(jobIdentifier); byte skillCount = inc.ReadByte(); for (int i = 0; i < skillCount; i++) { string skillIdentifier = inc.ReadString(); float skillLevel = inc.ReadSingle(); skillLevels.Add(skillIdentifier, skillLevel); } } // TODO: animations CharacterInfo ch = new CharacterInfo(speciesName, newName, originalName, jobPrefab, ragdollFile, variant) { ID = infoID, }; ch.RecreateHead(headSpriteID, (Race)race, (Gender)gender, hairIndex, beardIndex, moustacheIndex, faceAttachmentIndex); ch.SkinColor = skinColor; ch.HairColor = hairColor; ch.FacialHairColor = facialHairColor; if (ch.Job != null) { foreach (KeyValuePair <string, float> skill in skillLevels) { Skill matchingSkill = ch.Job.Skills.Find(s => s.Identifier == skill.Key); if (matchingSkill == null) { ch.Job.Skills.Add(new Skill(skill.Key, skill.Value)); continue; } matchingSkill.Level = skill.Value; } ch.Job.Skills.RemoveAll(s => !skillLevels.ContainsKey(s.Identifier)); } byte savedStatValueCount = inc.ReadByte(); for (int i = 0; i < savedStatValueCount; i++) { int statType = inc.ReadByte(); string statIdentifier = inc.ReadString(); float statValue = inc.ReadSingle(); bool removeOnDeath = inc.ReadBoolean(); ch.ChangeSavedStatValue((StatTypes)statType, statValue, statIdentifier, removeOnDeath); } ch.ExperiencePoints = inc.ReadUInt16(); ch.AdditionalTalentPoints = inc.ReadUInt16(); return(ch); }
public void ClientRead(IReadMessage inc) { AllowSubVoting = inc.ReadBoolean(); if (allowSubVoting) { UpdateVoteTexts(null, VoteType.Sub); int votableCount = inc.ReadByte(); for (int i = 0; i < votableCount; i++) { int votes = inc.ReadByte(); string subName = inc.ReadString(); List <SubmarineInfo> serversubs = new List <SubmarineInfo>(); foreach (GUIComponent item in GameMain.NetLobbyScreen?.SubList?.Content?.Children) { if (item.UserData != null && item.UserData is SubmarineInfo) { serversubs.Add(item.UserData as SubmarineInfo); } } SubmarineInfo sub = serversubs.FirstOrDefault(s => s.Name == subName); SetVoteText(GameMain.NetLobbyScreen.SubList, sub, votes); } } AllowModeVoting = inc.ReadBoolean(); if (allowModeVoting) { UpdateVoteTexts(null, VoteType.Mode); int votableCount = inc.ReadByte(); for (int i = 0; i < votableCount; i++) { int votes = inc.ReadByte(); string modeIdentifier = inc.ReadString(); GameModePreset mode = GameModePreset.List.Find(m => m.Identifier == modeIdentifier); SetVoteText(GameMain.NetLobbyScreen.ModeList, mode, votes); } } AllowEndVoting = inc.ReadBoolean(); if (AllowEndVoting) { GameMain.NetworkMember.EndVoteCount = inc.ReadByte(); GameMain.NetworkMember.EndVoteMax = inc.ReadByte(); } AllowVoteKick = inc.ReadBoolean(); byte subVoteStateByte = inc.ReadByte(); VoteState subVoteState = VoteState.None; try { subVoteState = (VoteState)subVoteStateByte; } catch (System.Exception e) { DebugConsole.ThrowError("Failed to cast vote type \"" + subVoteStateByte + "\"", e); } if (subVoteState != VoteState.None) { byte voteTypeByte = inc.ReadByte(); VoteType voteType = VoteType.Unknown; try { voteType = (VoteType)voteTypeByte; } catch (System.Exception e) { DebugConsole.ThrowError("Failed to cast vote type \"" + voteTypeByte + "\"", e); } if (voteType != VoteType.Unknown) { byte yesClientCount = inc.ReadByte(); for (int i = 0; i < yesClientCount; i++) { byte clientID = inc.ReadByte(); var matchingClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == clientID); matchingClient?.SetVote(voteType, 2); } byte noClientCount = inc.ReadByte(); for (int i = 0; i < noClientCount; i++) { byte clientID = inc.ReadByte(); var matchingClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == clientID); matchingClient?.SetVote(voteType, 1); } GameMain.NetworkMember.SubmarineVoteYesCount = yesClientCount; GameMain.NetworkMember.SubmarineVoteNoCount = noClientCount; GameMain.NetworkMember.SubmarineVoteMax = inc.ReadByte(); switch (subVoteState) { case VoteState.Started: Client myClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == GameMain.Client.ID); if (!myClient.InGame) { VoteRunning = true; return; } string subName1 = inc.ReadString(); SubmarineInfo info = GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName1); if (info == null) { DebugConsole.ThrowError("Failed to find a matching submarine, vote aborted"); return; } VoteRunning = true; byte starterID = inc.ReadByte(); Client starterClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == starterID); float timeOut = inc.ReadByte(); GameMain.Client.ShowSubmarineChangeVoteInterface(starterClient, info, voteType, timeOut); break; case VoteState.Running: // Nothing specific break; case VoteState.Passed: case VoteState.Failed: VoteRunning = false; bool passed = inc.ReadBoolean(); string subName2 = inc.ReadString(); SubmarineInfo subInfo = GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName2); if (subInfo == null) { DebugConsole.ThrowError("Failed to find a matching submarine, vote aborted"); return; } if (GameMain.Client.VotingInterface != null) { GameMain.Client.VotingInterface.EndVote(passed, yesClientCount, noClientCount); } else if (GameMain.Client.ConnectedClients.Count > 1) { GameMain.NetworkMember.AddChatMessage(VotingInterface.GetSubmarineVoteResultMessage(subInfo, voteType, yesClientCount.ToString(), noClientCount.ToString(), passed), ChatMessageType.Server); } if (passed) { int deliveryFee = inc.ReadInt16(); switch (voteType) { case VoteType.PurchaseAndSwitchSub: GameMain.GameSession.PurchaseSubmarine(subInfo); GameMain.GameSession.SwitchSubmarine(subInfo, 0); break; case VoteType.PurchaseSub: GameMain.GameSession.PurchaseSubmarine(subInfo); break; case VoteType.SwitchSub: GameMain.GameSession.SwitchSubmarine(subInfo, deliveryFee); break; } SubmarineSelection.ContentRefreshRequired = true; } break; } } } GameMain.NetworkMember.ConnectedClients.ForEach(c => c.SetVote(VoteType.StartRound, false)); byte readyClientCount = inc.ReadByte(); for (int i = 0; i < readyClientCount; i++) { byte clientID = inc.ReadByte(); var matchingClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == clientID); matchingClient?.SetVote(VoteType.StartRound, true); } UpdateVoteTexts(GameMain.NetworkMember.ConnectedClients, VoteType.StartRound); inc.ReadPadBits(); }
public void Read(IReadMessage msg) { int oldPos = msg.BitPosition; UInt32 size = msg.ReadVariableUInt32(); float x; float y; float z; float w; byte r; byte g; byte b; byte a; int ix; int iy; int width; int height; switch (typeString) { case "float": if (size != 4) { break; } property.SetValue(parentObject, msg.ReadSingle()); return; case "int": if (size != 4) { break; } property.SetValue(parentObject, msg.ReadInt32()); return; case "vector2": if (size != 8) { break; } x = msg.ReadSingle(); y = msg.ReadSingle(); property.SetValue(parentObject, new Vector2(x, y)); return; case "vector3": if (size != 12) { break; } x = msg.ReadSingle(); y = msg.ReadSingle(); z = msg.ReadSingle(); property.SetValue(parentObject, new Vector3(x, y, z)); return; case "vector4": if (size != 16) { break; } x = msg.ReadSingle(); y = msg.ReadSingle(); z = msg.ReadSingle(); w = msg.ReadSingle(); property.SetValue(parentObject, new Vector4(x, y, z, w)); return; case "color": if (size != 4) { break; } r = msg.ReadByte(); g = msg.ReadByte(); b = msg.ReadByte(); a = msg.ReadByte(); property.SetValue(parentObject, new Color(r, g, b, a)); return; case "rectangle": if (size != 16) { break; } ix = msg.ReadInt32(); iy = msg.ReadInt32(); width = msg.ReadInt32(); height = msg.ReadInt32(); property.SetValue(parentObject, new Rectangle(ix, iy, width, height)); return; default: msg.BitPosition = oldPos; //reset position to properly read the string string incVal = msg.ReadString(); property.TrySetValue(parentObject, incVal); return; } //size didn't match: skip this msg.BitPosition += (int)(8 * size); }
public static void ClientRead(IReadMessage inc) { ReadyCheckState state = (ReadyCheckState)inc.ReadByte(); CrewManager? crewManager = GameMain.GameSession?.CrewManager; List <Client> otherClients = GameMain.Client.ConnectedClients; if (crewManager == null || otherClients == null) { if (state == ReadyCheckState.Start) { SendState(ReadyStatus.No); } return; } switch (state) { case ReadyCheckState.Start: bool isOwn = false; byte authorId = 0; float duration = inc.ReadSingle(); string author = inc.ReadString(); bool hasAuthor = inc.ReadBoolean(); if (hasAuthor) { authorId = inc.ReadByte(); isOwn = authorId == GameMain.Client.ID; } ushort clientCount = inc.ReadUInt16(); List <byte> clients = new List <byte>(); for (int i = 0; i < clientCount; i++) { clients.Add(inc.ReadByte()); } ReadyCheck rCheck = new ReadyCheck(clients, duration); crewManager.ActiveReadyCheck = rCheck; if (isOwn) { SendState(ReadyStatus.Yes); rCheck.CreateResultsMessage(); } else { rCheck.CreateMessageBox(author); } if (hasAuthor && rCheck.Clients.ContainsKey(authorId)) { rCheck.Clients[authorId] = ReadyStatus.Yes; } break; case ReadyCheckState.Update: float time = inc.ReadSingle(); ReadyStatus newState = (ReadyStatus)inc.ReadByte(); byte targetId = inc.ReadByte(); if (crewManager.ActiveReadyCheck != null) { crewManager.ActiveReadyCheck.time = time; crewManager.ActiveReadyCheck?.UpdateState(targetId, newState); } break; case ReadyCheckState.End: ushort count = inc.ReadUInt16(); for (int i = 0; i < count; i++) { byte id = inc.ReadByte(); ReadyStatus status = (ReadyStatus)inc.ReadByte(); crewManager.ActiveReadyCheck?.UpdateState(id, status); } crewManager.ActiveReadyCheck?.EndReadyCheck(); crewManager.ActiveReadyCheck?.msgBox?.Close(); crewManager.ActiveReadyCheck = null; break; } }
public virtual void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime) { switch (type) { case ServerNetObject.ENTITY_POSITION: bool facingRight = AnimController.Dir > 0.0f; lastRecvPositionUpdateTime = (float)Lidgren.Network.NetTime.Now; AnimController.Frozen = false; Enabled = true; UInt16 networkUpdateID = 0; if (msg.ReadBoolean()) { networkUpdateID = msg.ReadUInt16(); } else { bool aimInput = msg.ReadBoolean(); keys[(int)InputType.Aim].Held = aimInput; keys[(int)InputType.Aim].SetState(false, aimInput); bool shootInput = msg.ReadBoolean(); keys[(int)InputType.Shoot].Held = shootInput; keys[(int)InputType.Shoot].SetState(false, shootInput); bool useInput = msg.ReadBoolean(); keys[(int)InputType.Use].Held = useInput; keys[(int)InputType.Use].SetState(false, useInput); if (AnimController is HumanoidAnimController) { bool crouching = msg.ReadBoolean(); keys[(int)InputType.Crouch].Held = crouching; keys[(int)InputType.Crouch].SetState(false, crouching); } bool attackInput = msg.ReadBoolean(); keys[(int)InputType.Attack].Held = attackInput; keys[(int)InputType.Attack].SetState(false, attackInput); double aimAngle = msg.ReadUInt16() / 65535.0 * 2.0 * Math.PI; cursorPosition = AimRefPosition + new Vector2((float)Math.Cos(aimAngle), (float)Math.Sin(aimAngle)) * 500.0f; TransformCursorPos(); bool ragdollInput = msg.ReadBoolean(); keys[(int)InputType.Ragdoll].Held = ragdollInput; keys[(int)InputType.Ragdoll].SetState(false, ragdollInput); facingRight = msg.ReadBoolean(); } bool entitySelected = msg.ReadBoolean(); Character selectedCharacter = null; Item selectedItem = null; AnimController.Animation animation = AnimController.Animation.None; if (entitySelected) { ushort characterID = msg.ReadUInt16(); ushort itemID = msg.ReadUInt16(); selectedCharacter = FindEntityByID(characterID) as Character; selectedItem = FindEntityByID(itemID) as Item; if (characterID != NullEntityID) { bool doingCpr = msg.ReadBoolean(); if (doingCpr && SelectedCharacter != null) { animation = AnimController.Animation.CPR; } } } Vector2 pos = new Vector2( msg.ReadSingle(), msg.ReadSingle()); float MaxVel = NetConfig.MaxPhysicsBodyVelocity; Vector2 linearVelocity = new Vector2( msg.ReadRangedSingle(-MaxVel, MaxVel, 12), msg.ReadRangedSingle(-MaxVel, MaxVel, 12)); linearVelocity = NetConfig.Quantize(linearVelocity, -MaxVel, MaxVel, 12); bool fixedRotation = msg.ReadBoolean(); float?rotation = null; float?angularVelocity = null; if (!fixedRotation) { rotation = msg.ReadSingle(); float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity; angularVelocity = msg.ReadRangedSingle(-MaxAngularVel, MaxAngularVel, 8); angularVelocity = NetConfig.Quantize(angularVelocity.Value, -MaxAngularVel, MaxAngularVel, 8); } bool readStatus = msg.ReadBoolean(); if (readStatus) { ReadStatus(msg); (AIController as EnemyAIController)?.PetBehavior?.ClientRead(msg); } msg.ReadPadBits(); int index = 0; if (GameMain.Client.Character == this && CanMove) { var posInfo = new CharacterStateInfo( pos, rotation, networkUpdateID, facingRight ? Direction.Right : Direction.Left, selectedCharacter, selectedItem, animation); while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID)) { index++; } memState.Insert(index, posInfo); } else { var posInfo = new CharacterStateInfo( pos, rotation, linearVelocity, angularVelocity, sendingTime, facingRight ? Direction.Right : Direction.Left, selectedCharacter, selectedItem, animation); while (index < memState.Count && posInfo.Timestamp > memState[index].Timestamp) { index++; } memState.Insert(index, posInfo); } break; case ServerNetObject.ENTITY_EVENT: int eventType = msg.ReadRangedInteger(0, 5); switch (eventType) { case 0: //NetEntityEvent.Type.InventoryState if (Inventory == null) { string errorMsg = "Received an inventory update message for an entity with no inventory (" + Name + ", removed: " + Removed + ")"; DebugConsole.ThrowError(errorMsg); GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ClientRead:NoInventory" + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); //read anyway to prevent messing up reading the rest of the message UInt16 lastEventID = msg.ReadUInt16(); byte itemCount = msg.ReadByte(); for (int i = 0; i < itemCount; i++) { msg.ReadUInt16(); } } else { Inventory.ClientRead(type, msg, sendingTime); } break; case 1: //NetEntityEvent.Type.Control byte ownerID = msg.ReadByte(); ResetNetState(); if (ownerID == GameMain.Client.ID) { if (controlled != null) { LastNetworkUpdateID = controlled.LastNetworkUpdateID; } if (!IsDead) { Controlled = this; } IsRemotePlayer = false; GameMain.Client.HasSpawned = true; GameMain.Client.Character = this; GameMain.LightManager.LosEnabled = true; } else { if (controlled == this) { Controlled = null; IsRemotePlayer = ownerID > 0; } } break; case 2: //NetEntityEvent.Type.Status ReadStatus(msg); break; case 3: //NetEntityEvent.Type.UpdateSkills int skillCount = msg.ReadByte(); for (int i = 0; i < skillCount; i++) { string skillIdentifier = msg.ReadString(); float skillLevel = msg.ReadSingle(); info?.SetSkillLevel(skillIdentifier, skillLevel, WorldPosition + Vector2.UnitY * 150.0f); } break; case 4: //NetEntityEvent.Type.ExecuteAttack int attackLimbIndex = msg.ReadByte(); UInt16 targetEntityID = msg.ReadUInt16(); int targetLimbIndex = msg.ReadByte(); //255 = entity already removed, no need to do anything if (attackLimbIndex == 255 || Removed) { break; } if (attackLimbIndex >= AnimController.Limbs.Length) { DebugConsole.ThrowError($"Received invalid ExecuteAttack message. Limb index out of bounds (character: {Name}, limb index: {attackLimbIndex}, limb count: {AnimController.Limbs.Length})"); break; } Limb attackLimb = AnimController.Limbs[attackLimbIndex]; Limb targetLimb = null; if (!(FindEntityByID(targetEntityID) is IDamageable targetEntity)) { DebugConsole.ThrowError($"Received invalid ExecuteAttack message. Target entity not found (ID {targetEntityID})"); break; } if (targetEntity is Character targetCharacter) { if (targetLimbIndex >= targetCharacter.AnimController.Limbs.Length) { DebugConsole.ThrowError($"Received invalid ExecuteAttack message. Target limb index out of bounds (target character: {targetCharacter.Name}, limb index: {targetLimbIndex}, limb count: {targetCharacter.AnimController.Limbs.Length})"); break; } targetLimb = targetCharacter.AnimController.Limbs[targetLimbIndex]; } if (attackLimb?.attack != null) { attackLimb.ExecuteAttack(targetEntity, targetLimb, out _); } break; case 5: //NetEntityEvent.Type.AssignCampaignInteraction byte campaignInteractionType = msg.ReadByte(); (GameMain.GameSession?.GameMode as CampaignMode)?.AssignNPCMenuInteraction(this, (CampaignMode.InteractionType)campaignInteractionType); break; } msg.ReadPadBits(); break; } }
//static because we may need to instantiate the campaign if it hasn't been done yet public static void ClientRead(IReadMessage msg) { bool isFirstRound = msg.ReadBoolean(); byte campaignID = msg.ReadByte(); UInt16 updateID = msg.ReadUInt16(); UInt16 saveID = msg.ReadUInt16(); string mapSeed = msg.ReadString(); UInt16 currentLocIndex = msg.ReadUInt16(); UInt16 selectedLocIndex = msg.ReadUInt16(); byte selectedMissionIndex = msg.ReadByte(); bool allowDebugTeleport = msg.ReadBoolean(); float? reputation = null; if (msg.ReadBoolean()) { reputation = msg.ReadSingle(); } Dictionary <string, float> factionReps = new Dictionary <string, float>(); byte factionsCount = msg.ReadByte(); for (int i = 0; i < factionsCount; i++) { factionReps.Add(msg.ReadString(), msg.ReadSingle()); } bool forceMapUI = msg.ReadBoolean(); int money = msg.ReadInt32(); bool purchasedHullRepairs = msg.ReadBoolean(); bool purchasedItemRepairs = msg.ReadBoolean(); bool purchasedLostShuttles = msg.ReadBoolean(); byte missionCount = msg.ReadByte(); List <Pair <string, byte> > availableMissions = new List <Pair <string, byte> >(); for (int i = 0; i < missionCount; i++) { string missionIdentifier = msg.ReadString(); byte connectionIndex = msg.ReadByte(); availableMissions.Add(new Pair <string, byte>(missionIdentifier, connectionIndex)); } UInt16?storeBalance = null; if (msg.ReadBoolean()) { storeBalance = msg.ReadUInt16(); } UInt16 buyCrateItemCount = msg.ReadUInt16(); List <PurchasedItem> buyCrateItems = new List <PurchasedItem>(); for (int i = 0; i < buyCrateItemCount; i++) { string itemPrefabIdentifier = msg.ReadString(); int itemQuantity = msg.ReadRangedInteger(0, CargoManager.MaxQuantity); buyCrateItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity)); } UInt16 purchasedItemCount = msg.ReadUInt16(); List <PurchasedItem> purchasedItems = new List <PurchasedItem>(); for (int i = 0; i < purchasedItemCount; i++) { string itemPrefabIdentifier = msg.ReadString(); int itemQuantity = msg.ReadRangedInteger(0, CargoManager.MaxQuantity); purchasedItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity)); } UInt16 soldItemCount = msg.ReadUInt16(); List <SoldItem> soldItems = new List <SoldItem>(); for (int i = 0; i < soldItemCount; i++) { string itemPrefabIdentifier = msg.ReadString(); UInt16 id = msg.ReadUInt16(); bool removed = msg.ReadBoolean(); byte sellerId = msg.ReadByte(); soldItems.Add(new SoldItem(ItemPrefab.Prefabs[itemPrefabIdentifier], id, removed, sellerId)); } ushort pendingUpgradeCount = msg.ReadUInt16(); List <PurchasedUpgrade> pendingUpgrades = new List <PurchasedUpgrade>(); for (int i = 0; i < pendingUpgradeCount; i++) { string upgradeIdentifier = msg.ReadString(); UpgradePrefab prefab = UpgradePrefab.Find(upgradeIdentifier); string categoryIdentifier = msg.ReadString(); UpgradeCategory category = UpgradeCategory.Find(categoryIdentifier); int upgradeLevel = msg.ReadByte(); if (prefab == null || category == null) { continue; } pendingUpgrades.Add(new PurchasedUpgrade(prefab, category, upgradeLevel)); } bool hasCharacterData = msg.ReadBoolean(); CharacterInfo myCharacterInfo = null; if (hasCharacterData) { myCharacterInfo = CharacterInfo.ClientRead(CharacterPrefab.HumanSpeciesName, msg); } if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaignID != campaign.CampaignID) { string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer); GameMain.GameSession = new GameSession(null, savePath, GameModePreset.MultiPlayerCampaign, mapSeed); campaign = (MultiPlayerCampaign)GameMain.GameSession.GameMode; campaign.CampaignID = campaignID; GameMain.NetLobbyScreen.ToggleCampaignMode(true); } //server has a newer save file if (NetIdUtils.IdMoreRecent(saveID, campaign.PendingSaveID)) { campaign.PendingSaveID = saveID; } if (NetIdUtils.IdMoreRecent(updateID, campaign.lastUpdateID)) { campaign.SuppressStateSending = true; campaign.IsFirstRound = isFirstRound; //we need to have the latest save file to display location/mission/store if (campaign.LastSaveID == saveID) { campaign.ForceMapUI = forceMapUI; UpgradeStore.WaitForServerUpdate = false; campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex); campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex); campaign.Map.SelectMission(selectedMissionIndex); campaign.Map.AllowDebugTeleport = allowDebugTeleport; campaign.CargoManager.SetItemsInBuyCrate(buyCrateItems); campaign.CargoManager.SetPurchasedItems(purchasedItems); campaign.CargoManager.SetSoldItems(soldItems); if (storeBalance.HasValue) { campaign.Map.CurrentLocation.StoreCurrentBalance = storeBalance.Value; } campaign.UpgradeManager.SetPendingUpgrades(pendingUpgrades); campaign.UpgradeManager.PurchasedUpgrades.Clear(); foreach (var(identifier, rep) in factionReps) { Faction faction = campaign.Factions.FirstOrDefault(f => f.Prefab.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase)); if (faction?.Reputation != null) { faction.Reputation.Value = rep; } else { DebugConsole.ThrowError($"Received an update for a faction that doesn't exist \"{identifier}\"."); } } if (reputation.HasValue) { campaign.Map.CurrentLocation.Reputation.Value = reputation.Value; campaign?.CampaignUI?.UpgradeStore?.RefreshAll(); } foreach (var availableMission in availableMissions) { MissionPrefab missionPrefab = MissionPrefab.List.Find(mp => mp.Identifier == availableMission.First); if (missionPrefab == null) { DebugConsole.ThrowError($"Error when receiving campaign data from the server: mission prefab \"{availableMission.First}\" not found."); continue; } if (availableMission.Second < 0 || availableMission.Second >= campaign.Map.CurrentLocation.Connections.Count) { DebugConsole.ThrowError($"Error when receiving campaign data from the server: connection index for mission \"{availableMission.First}\" out of range (index: {availableMission.Second}, current location: {campaign.Map.CurrentLocation.Name}, connections: {campaign.Map.CurrentLocation.Connections.Count})."); continue; } LocationConnection connection = campaign.Map.CurrentLocation.Connections[availableMission.Second]; campaign.Map.CurrentLocation.UnlockMission(missionPrefab, connection); } GameMain.NetLobbyScreen.ToggleCampaignMode(true); } bool shouldRefresh = campaign.Money != money || campaign.PurchasedHullRepairs != purchasedHullRepairs || campaign.PurchasedItemRepairs != purchasedItemRepairs || campaign.PurchasedLostShuttles != purchasedLostShuttles; campaign.Money = money; campaign.PurchasedHullRepairs = purchasedHullRepairs; campaign.PurchasedItemRepairs = purchasedItemRepairs; campaign.PurchasedLostShuttles = purchasedLostShuttles; if (shouldRefresh) { campaign?.CampaignUI?.UpgradeStore?.RefreshAll(); } if (myCharacterInfo != null) { GameMain.Client.CharacterInfo = myCharacterInfo; GameMain.NetLobbyScreen.SetCampaignCharacterInfo(myCharacterInfo); } else { GameMain.NetLobbyScreen.SetCampaignCharacterInfo(null); } campaign.lastUpdateID = updateID; campaign.SuppressStateSending = false; } }
private void ReadConnectionInitializationStep(PendingClient pendingClient, IReadMessage inc) { if (netServer == null) { return; } pendingClient.TimeOut = NetworkConnection.TimeoutThreshold; ConnectionInitialization initializationStep = (ConnectionInitialization)inc.ReadByte(); //DebugConsole.NewMessage(initializationStep+" "+pendingClient.InitializationStep); if (pendingClient.InitializationStep != initializationStep) { return; } pendingClient.UpdateTime = Timing.TotalTime + Timing.Step; switch (initializationStep) { case ConnectionInitialization.SteamTicketAndVersion: string name = Client.SanitizeName(inc.ReadString()); UInt64 steamId = inc.ReadUInt64(); UInt16 ticketLength = inc.ReadUInt16(); inc.BitPosition += ticketLength * 8; //skip ticket, owner handles steam authentication if (!Client.IsValidName(name, serverSettings)) { RemovePendingClient(pendingClient, DisconnectReason.InvalidName, "The name \"" + name + "\" is invalid"); return; } string version = inc.ReadString(); bool isCompatibleVersion = NetworkMember.IsCompatible(version, GameMain.Version.ToString()) ?? false; if (!isCompatibleVersion) { RemovePendingClient(pendingClient, DisconnectReason.InvalidVersion, $"DisconnectMessage.InvalidVersion~[version]={GameMain.Version.ToString()}~[clientversion]={version}"); GameServer.Log(name + " (" + pendingClient.SteamID.ToString() + ") couldn't join the server (incompatible game version)", ServerLog.MessageType.Error); DebugConsole.NewMessage(name + " (" + pendingClient.SteamID.ToString() + ") couldn't join the server (incompatible game version)", Microsoft.Xna.Framework.Color.Red); return; } int contentPackageCount = (int)inc.ReadVariableUInt32(); List <ClientContentPackage> clientContentPackages = new List <ClientContentPackage>(); for (int i = 0; i < contentPackageCount; i++) { string packageName = inc.ReadString(); string packageHash = inc.ReadString(); clientContentPackages.Add(new ClientContentPackage(packageName, packageHash)); } //check if the client is missing any of our packages List <ContentPackage> missingPackages = new List <ContentPackage>(); foreach (ContentPackage serverContentPackage in GameMain.SelectedPackages) { if (!serverContentPackage.HasMultiplayerIncompatibleContent) { continue; } bool packageFound = clientContentPackages.Any(cp => cp.Name == serverContentPackage.Name && cp.Hash == serverContentPackage.MD5hash.Hash); if (!packageFound) { missingPackages.Add(serverContentPackage); } } //check if the client is using packages we don't have List <ClientContentPackage> redundantPackages = new List <ClientContentPackage>(); foreach (ClientContentPackage clientContentPackage in clientContentPackages) { bool packageFound = GameMain.SelectedPackages.Any(cp => cp.Name == clientContentPackage.Name && cp.MD5hash.Hash == clientContentPackage.Hash); if (!packageFound) { redundantPackages.Add(clientContentPackage); } } if (missingPackages.Count == 1) { RemovePendingClient(pendingClient, DisconnectReason.MissingContentPackage, $"DisconnectMessage.MissingContentPackage~[missingcontentpackage]={GetPackageStr(missingPackages[0])}"); GameServer.Log(name + " (" + pendingClient.SteamID + ") couldn't join the server (missing content package " + GetPackageStr(missingPackages[0]) + ")", ServerLog.MessageType.Error); return; } else if (missingPackages.Count > 1) { List <string> packageStrs = new List <string>(); missingPackages.ForEach(cp => packageStrs.Add(GetPackageStr(cp))); RemovePendingClient(pendingClient, DisconnectReason.MissingContentPackage, $"DisconnectMessage.MissingContentPackages~[missingcontentpackages]={string.Join(", ", packageStrs)}"); GameServer.Log(name + " (" + pendingClient.SteamID + ") couldn't join the server (missing content packages " + string.Join(", ", packageStrs) + ")", ServerLog.MessageType.Error); return; } if (redundantPackages.Count == 1) { RemovePendingClient(pendingClient, DisconnectReason.IncompatibleContentPackage, $"DisconnectMessage.IncompatibleContentPackage~[incompatiblecontentpackage]={GetPackageStr(redundantPackages[0])}"); GameServer.Log(name + " (" + pendingClient.SteamID + ") couldn't join the server (using an incompatible content package " + GetPackageStr(redundantPackages[0]) + ")", ServerLog.MessageType.Error); return; } if (redundantPackages.Count > 1) { List <string> packageStrs = new List <string>(); redundantPackages.ForEach(cp => packageStrs.Add(GetPackageStr(cp))); RemovePendingClient(pendingClient, DisconnectReason.IncompatibleContentPackage, $"DisconnectMessage.IncompatibleContentPackages~[incompatiblecontentpackages]={string.Join(", ", packageStrs)}"); GameServer.Log(name + " (" + pendingClient.SteamID + ") couldn't join the server (using incompatible content packages " + string.Join(", ", packageStrs) + ")", ServerLog.MessageType.Error); return; } if (!pendingClient.AuthSessionStarted) { pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password: ConnectionInitialization.Success; pendingClient.Name = name; pendingClient.AuthSessionStarted = true; } break; case ConnectionInitialization.Password: int pwLength = inc.ReadByte(); byte[] incPassword = inc.ReadBytes(pwLength); if (pendingClient.PasswordSalt == null) { DebugConsole.ThrowError("Received password message from client without salt"); return; } if (serverSettings.IsPasswordCorrect(incPassword, pendingClient.PasswordSalt.Value)) { pendingClient.InitializationStep = ConnectionInitialization.Success; } else { pendingClient.Retries++; if (pendingClient.Retries >= 3) { string banMsg = "Failed to enter correct password too many times"; serverSettings.BanList.BanPlayer(pendingClient.Name, pendingClient.SteamID, banMsg, null); RemovePendingClient(pendingClient, DisconnectReason.Banned, banMsg); return; } } pendingClient.UpdateTime = Timing.TotalTime; break; } }
public void ServerReadCrew(IReadMessage msg, Client sender) { int[] pendingHires = null; bool updatePending = msg.ReadBoolean(); if (updatePending) { ushort pendingHireLength = msg.ReadUInt16(); pendingHires = new int[pendingHireLength]; for (int i = 0; i < pendingHireLength; i++) { pendingHires[i] = msg.ReadInt32(); } } bool validateHires = msg.ReadBoolean(); bool renameCharacter = msg.ReadBoolean(); int renamedIdentifier = -1; string newName = null; bool existingCrewMember = false; if (renameCharacter) { renamedIdentifier = msg.ReadInt32(); newName = msg.ReadString(); existingCrewMember = msg.ReadBoolean(); } bool fireCharacter = msg.ReadBoolean(); int firedIdentifier = -1; if (fireCharacter) { firedIdentifier = msg.ReadInt32(); } Location location = map?.CurrentLocation; List <CharacterInfo> hiredCharacters = new List <CharacterInfo>(); CharacterInfo firedCharacter = null; if (location != null && AllowedToManageCampaign(sender)) { if (fireCharacter) { firedCharacter = CrewManager.CharacterInfos.FirstOrDefault(info => info.GetIdentifier() == firedIdentifier); if (firedCharacter != null && (firedCharacter.Character?.IsBot ?? true)) { CrewManager.FireCharacter(firedCharacter); } else { DebugConsole.ThrowError($"Tried to fire an invalid character ({firedIdentifier})"); } } if (renameCharacter) { CharacterInfo characterInfo = null; if (existingCrewMember && CrewManager != null) { characterInfo = CrewManager.CharacterInfos.FirstOrDefault(info => info.GetIdentifierUsingOriginalName() == renamedIdentifier); } else if (!existingCrewMember && location.HireManager != null) { characterInfo = location.HireManager.AvailableCharacters.FirstOrDefault(info => info.GetIdentifierUsingOriginalName() == renamedIdentifier); } if (characterInfo != null && (characterInfo.Character?.IsBot ?? true)) { if (existingCrewMember) { CrewManager.RenameCharacter(characterInfo, newName); } else { location.HireManager.RenameCharacter(characterInfo, newName); } } else { DebugConsole.ThrowError($"Tried to rename an invalid character ({renamedIdentifier})"); } } if (location.HireManager != null) { if (validateHires) { foreach (CharacterInfo hireInfo in location.HireManager.PendingHires) { if (TryHireCharacter(location, hireInfo)) { hiredCharacters.Add(hireInfo); } ; } } if (updatePending) { List <CharacterInfo> pendingHireInfos = new List <CharacterInfo>(); foreach (int identifier in pendingHires) { CharacterInfo match = location.GetHireableCharacters().FirstOrDefault(info => info.GetIdentifierUsingOriginalName() == identifier); if (match == null) { DebugConsole.ThrowError($"Tried to add a character that doesn't exist ({identifier}) to pending hires"); continue; } pendingHireInfos.Add(match); if (pendingHireInfos.Count + CrewManager.CharacterInfos.Count() >= CrewManager.MaxCrewSize) { break; } } location.HireManager.PendingHires = pendingHireInfos; } location.HireManager.AvailableCharacters.ForEachMod(info => { if (!location.HireManager.PendingHires.Contains(info)) { location.HireManager.RenameCharacter(info, info.OriginalName); } }); } } // bounce back if (renameCharacter && existingCrewMember) { SendCrewState(hiredCharacters, (renamedIdentifier, newName), firedCharacter); } else { SendCrewState(hiredCharacters, default, firedCharacter);
public void ServerRead(IReadMessage msg, Client sender) { UInt16 currentLocIndex = msg.ReadUInt16(); UInt16 selectedLocIndex = msg.ReadUInt16(); byte selectedMissionCount = msg.ReadByte(); List <int> selectedMissionIndices = new List <int>(); for (int i = 0; i < selectedMissionCount; i++) { selectedMissionIndices.Add(msg.ReadByte()); } bool purchasedHullRepairs = msg.ReadBoolean(); bool purchasedItemRepairs = msg.ReadBoolean(); bool purchasedLostShuttles = msg.ReadBoolean(); UInt16 buyCrateItemCount = msg.ReadUInt16(); List <PurchasedItem> buyCrateItems = new List <PurchasedItem>(); for (int i = 0; i < buyCrateItemCount; i++) { string itemPrefabIdentifier = msg.ReadString(); int itemQuantity = msg.ReadRangedInteger(0, CargoManager.MaxQuantity); buyCrateItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity)); } UInt16 purchasedItemCount = msg.ReadUInt16(); List <PurchasedItem> purchasedItems = new List <PurchasedItem>(); for (int i = 0; i < purchasedItemCount; i++) { string itemPrefabIdentifier = msg.ReadString(); int itemQuantity = msg.ReadRangedInteger(0, CargoManager.MaxQuantity); purchasedItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity)); } UInt16 soldItemCount = msg.ReadUInt16(); List <SoldItem> soldItems = new List <SoldItem>(); for (int i = 0; i < soldItemCount; i++) { string itemPrefabIdentifier = msg.ReadString(); UInt16 id = msg.ReadUInt16(); bool removed = msg.ReadBoolean(); byte sellerId = msg.ReadByte(); soldItems.Add(new SoldItem(ItemPrefab.Prefabs[itemPrefabIdentifier], id, removed, sellerId)); } ushort purchasedUpgradeCount = msg.ReadUInt16(); List <PurchasedUpgrade> purchasedUpgrades = new List <PurchasedUpgrade>(); for (int i = 0; i < purchasedUpgradeCount; i++) { string upgradeIdentifier = msg.ReadString(); UpgradePrefab prefab = UpgradePrefab.Find(upgradeIdentifier); string categoryIdentifier = msg.ReadString(); UpgradeCategory category = UpgradeCategory.Find(categoryIdentifier); int upgradeLevel = msg.ReadByte(); if (category == null || prefab == null) { continue; } purchasedUpgrades.Add(new PurchasedUpgrade(prefab, category, upgradeLevel)); } ushort purchasedItemSwapCount = msg.ReadUInt16(); List <PurchasedItemSwap> purchasedItemSwaps = new List <PurchasedItemSwap>(); for (int i = 0; i < purchasedItemSwapCount; i++) { UInt16 itemToRemoveID = msg.ReadUInt16(); Item itemToRemove = Entity.FindEntityByID(itemToRemoveID) as Item; string itemToInstallIdentifier = msg.ReadString(); ItemPrefab itemToInstall = string.IsNullOrEmpty(itemToInstallIdentifier) ? null : ItemPrefab.Find(string.Empty, itemToInstallIdentifier); if (itemToRemove == null) { continue; } purchasedItemSwaps.Add(new PurchasedItemSwap(itemToRemove, itemToInstall)); } if (!AllowedToManageCampaign(sender)) { DebugConsole.ThrowError("Client \"" + sender.Name + "\" does not have a permission to manage the campaign"); return; } Location location = Map.CurrentLocation; int hullRepairCost = location?.GetAdjustedMechanicalCost(HullRepairCost) ?? HullRepairCost; int itemRepairCost = location?.GetAdjustedMechanicalCost(ItemRepairCost) ?? ItemRepairCost; int shuttleRetrieveCost = location?.GetAdjustedMechanicalCost(ShuttleReplaceCost) ?? ShuttleReplaceCost; if (purchasedHullRepairs != this.PurchasedHullRepairs) { if (purchasedHullRepairs && Money >= hullRepairCost) { this.PurchasedHullRepairs = true; Money -= hullRepairCost; } else if (!purchasedHullRepairs) { this.PurchasedHullRepairs = false; Money += hullRepairCost; } } if (purchasedItemRepairs != this.PurchasedItemRepairs) { if (purchasedItemRepairs && Money >= itemRepairCost) { this.PurchasedItemRepairs = true; Money -= itemRepairCost; } else if (!purchasedItemRepairs) { this.PurchasedItemRepairs = false; Money += itemRepairCost; } } if (purchasedLostShuttles != this.PurchasedLostShuttles) { if (GameMain.GameSession?.SubmarineInfo != null && GameMain.GameSession.SubmarineInfo.LeftBehindSubDockingPortOccupied) { GameMain.Server.SendDirectChatMessage(TextManager.FormatServerMessage("ReplaceShuttleDockingPortOccupied"), sender, ChatMessageType.MessageBox); } else if (purchasedLostShuttles && Money >= shuttleRetrieveCost) { this.PurchasedLostShuttles = true; Money -= shuttleRetrieveCost; } else if (!purchasedItemRepairs) { this.PurchasedLostShuttles = false; Money += shuttleRetrieveCost; } } if (currentLocIndex < Map.Locations.Count && Map.AllowDebugTeleport) { Map.SetLocation(currentLocIndex); } Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex); if (Map.SelectedLocation == null) { Map.SelectRandomLocation(preferUndiscovered: true); } if (Map.SelectedConnection != null) { Map.SelectMission(selectedMissionIndices); } CheckTooManyMissions(Map.CurrentLocation, sender); List <PurchasedItem> currentBuyCrateItems = new List <PurchasedItem>(CargoManager.ItemsInBuyCrate); currentBuyCrateItems.ForEach(i => CargoManager.ModifyItemQuantityInBuyCrate(i.ItemPrefab, -i.Quantity)); buyCrateItems.ForEach(i => CargoManager.ModifyItemQuantityInBuyCrate(i.ItemPrefab, i.Quantity)); CargoManager.SellBackPurchasedItems(new List <PurchasedItem>(CargoManager.PurchasedItems)); CargoManager.PurchaseItems(purchasedItems, false); // for some reason CargoManager.SoldItem is never cleared by the server, I've added a check to SellItems that ignores all // sold items that are removed so they should be discarded on the next message CargoManager.BuyBackSoldItems(new List <SoldItem>(CargoManager.SoldItems)); CargoManager.SellItems(soldItems); foreach (var(prefab, category, _) in purchasedUpgrades) { UpgradeManager.PurchaseUpgrade(prefab, category); // unstable logging int price = prefab.Price.GetBuyprice(UpgradeManager.GetUpgradeLevel(prefab, category), Map?.CurrentLocation); int level = UpgradeManager.GetUpgradeLevel(prefab, category); GameServer.Log($"SERVER: Purchased level {level} {category.Identifier}.{prefab.Identifier} for {price}", ServerLog.MessageType.ServerMessage); } foreach (var purchasedItemSwap in purchasedItemSwaps) { if (purchasedItemSwap.ItemToInstall == null) { UpgradeManager.CancelItemSwap(purchasedItemSwap.ItemToRemove); } else { UpgradeManager.PurchaseItemSwap(purchasedItemSwap.ItemToRemove, purchasedItemSwap.ItemToInstall); } } foreach (Item item in Item.ItemList) { if (item.PendingItemSwap != null && !purchasedItemSwaps.Any(it => it.ItemToRemove == item)) { UpgradeManager.CancelItemSwap(item); item.PendingItemSwap = null; } } }
public static Character ReadSpawnData(IReadMessage inc) { DebugConsole.Log("Reading character spawn data"); if (GameMain.Client == null) { return(null); } bool noInfo = inc.ReadBoolean(); ushort id = inc.ReadUInt16(); string speciesName = inc.ReadString(); string seed = inc.ReadString(); Vector2 position = new Vector2(inc.ReadSingle(), inc.ReadSingle()); bool enabled = inc.ReadBoolean(); DebugConsole.Log("Received spawn data for " + speciesName); Character character = null; if (noInfo) { character = Create(speciesName, position, seed, null, false); character.ID = id; bool containsStatusData = inc.ReadBoolean(); if (containsStatusData) { character.ReadStatus(inc); } } else { bool hasOwner = inc.ReadBoolean(); int ownerId = hasOwner ? inc.ReadByte() : -1; byte teamID = inc.ReadByte(); bool hasAi = inc.ReadBoolean(); string infoSpeciesName = inc.ReadString(); CharacterInfo info = CharacterInfo.ClientRead(infoSpeciesName, inc); character = Create(speciesName, position, seed, info, ownerId > 0 && GameMain.Client.ID != ownerId, hasAi); character.ID = id; character.TeamID = (TeamType)teamID; character.CampaignInteractionType = (CampaignMode.InteractionType)inc.ReadByte(); if (character.CampaignInteractionType != CampaignMode.InteractionType.None) { (GameMain.GameSession.GameMode as CampaignMode)?.AssignNPCMenuInteraction(character, character.CampaignInteractionType); } // Check if the character has a current order if (inc.ReadBoolean()) { int orderPrefabIndex = inc.ReadByte(); Entity targetEntity = FindEntityByID(inc.ReadUInt16()); Character orderGiver = inc.ReadBoolean() ? FindEntityByID(inc.ReadUInt16()) as Character : null; int orderOptionIndex = inc.ReadByte(); OrderTarget targetPosition = null; if (inc.ReadBoolean()) { var x = inc.ReadSingle(); var y = inc.ReadSingle(); var hull = FindEntityByID(inc.ReadUInt16()) as Hull; targetPosition = new OrderTarget(new Vector2(x, y), hull, true); } if (orderPrefabIndex >= 0 && orderPrefabIndex < Order.PrefabList.Count) { var orderPrefab = Order.PrefabList[orderPrefabIndex]; var component = orderPrefab.GetTargetItemComponent(targetEntity as Item); if (!orderPrefab.MustSetTarget || (targetEntity != null && component != null) || targetPosition != null) { var order = targetPosition == null ? new Order(orderPrefab, targetEntity, component, orderGiver: orderGiver) : new Order(orderPrefab, targetPosition, orderGiver: orderGiver); character.SetOrder(order, orderOptionIndex >= 0 && orderOptionIndex < orderPrefab.Options.Length ? orderPrefab.Options[orderOptionIndex] : null, orderGiver, speak: false); } else { DebugConsole.ThrowError("Could not set order \"" + orderPrefab.Identifier + "\" for character \"" + character.Name + "\" because required target entity was not found."); } } else { DebugConsole.ThrowError("Invalid order prefab index - index (" + orderPrefabIndex + ") out of bounds."); } } bool containsStatusData = inc.ReadBoolean(); if (containsStatusData) { character.ReadStatus(inc); } if (character.IsHuman && character.TeamID != TeamType.FriendlyNPC && !character.IsDead) { CharacterInfo duplicateCharacterInfo = GameMain.GameSession.CrewManager.GetCharacterInfos().FirstOrDefault(c => c.ID == info.ID); GameMain.GameSession.CrewManager.RemoveCharacterInfo(duplicateCharacterInfo); GameMain.GameSession.CrewManager.AddCharacter(character); } if (GameMain.Client.ID == ownerId) { GameMain.Client.HasSpawned = true; GameMain.Client.Character = character; if (!character.IsDead) { Controlled = character; } GameMain.LightManager.LosEnabled = true; character.memInput.Clear(); character.memState.Clear(); character.memLocalState.Clear(); } } character.Enabled = Controlled == character || enabled; return(character); }
protected void ReadConnectionInitializationStep(IReadMessage inc) { ConnectionInitialization step = (ConnectionInitialization)inc.ReadByte(); IWriteMessage outMsg; switch (step) { case ConnectionInitialization.SteamTicketAndVersion: if (initializationStep != ConnectionInitialization.SteamTicketAndVersion) { return; } outMsg = new WriteOnlyMessage(); outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep); outMsg.Write((byte)ConnectionInitialization.SteamTicketAndVersion); outMsg.Write(Name); outMsg.Write(ownerKey); outMsg.Write(SteamManager.GetSteamID()); if (steamAuthTicket == null) { outMsg.Write((UInt16)0); } else { outMsg.Write((UInt16)steamAuthTicket.Data.Length); outMsg.Write(steamAuthTicket.Data, 0, steamAuthTicket.Data.Length); } outMsg.Write(GameMain.Version.ToString()); outMsg.Write(GameMain.Config.Language); SendMsgInternal(DeliveryMethod.Reliable, outMsg); break; case ConnectionInitialization.ContentPackageOrder: if (initializationStep == ConnectionInitialization.SteamTicketAndVersion || initializationStep == ConnectionInitialization.Password) { initializationStep = ConnectionInitialization.ContentPackageOrder; } if (initializationStep != ConnectionInitialization.ContentPackageOrder) { return; } outMsg = new WriteOnlyMessage(); outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep); outMsg.Write((byte)ConnectionInitialization.ContentPackageOrder); string serverName = inc.ReadString(); UInt32 cpCount = inc.ReadVariableUInt32(); ServerContentPackage corePackage = null; List <ServerContentPackage> regularPackages = new List <ServerContentPackage>(); List <ServerContentPackage> missingPackages = new List <ServerContentPackage>(); for (int i = 0; i < cpCount; i++) { string name = inc.ReadString(); string hash = inc.ReadString(); UInt64 workshopId = inc.ReadUInt64(); var pkg = new ServerContentPackage(name, hash, workshopId); if (pkg.CorePackage != null) { corePackage = pkg; } else if (pkg.RegularPackage != null) { regularPackages.Add(pkg); } else { missingPackages.Add(pkg); } } if (missingPackages.Count > 0) { var nonDownloadable = missingPackages.Where(p => p.WorkshopId == 0); if (nonDownloadable.Any()) { string disconnectMsg; if (nonDownloadable.Count() == 1) { disconnectMsg = $"DisconnectMessage.MissingContentPackage~[missingcontentpackage]={GetPackageStr(missingPackages[0])}"; } else { List <string> packageStrs = new List <string>(); nonDownloadable.ForEach(cp => packageStrs.Add(GetPackageStr(cp))); disconnectMsg = $"DisconnectMessage.MissingContentPackages~[missingcontentpackages]={string.Join(", ", packageStrs)}"; } Close(disconnectMsg, disableReconnect: true); OnDisconnectMessageReceived?.Invoke(DisconnectReason.MissingContentPackage + "/" + disconnectMsg); } else { Close(disableReconnect: true); string missingModNames = "\n"; int displayedModCount = 0; foreach (ServerContentPackage missingPackage in missingPackages) { missingModNames += "\n- " + GetPackageStr(missingPackage); displayedModCount++; if (GUI.Font.MeasureString(missingModNames).Y > GameMain.GraphicsHeight * 0.5f) { missingModNames += "\n\n" + TextManager.GetWithVariable("workshopitemdownloadprompttruncated", "[number]", (missingPackages.Count - displayedModCount).ToString()); break; } } missingModNames += "\n\n"; var msgBox = new GUIMessageBox( TextManager.Get("WorkshopItemDownloadTitle"), TextManager.GetWithVariable("WorkshopItemDownloadPrompt", "[items]", missingModNames), new string[] { TextManager.Get("Yes"), TextManager.Get("No") }); msgBox.Buttons[0].OnClicked = (yesBtn, userdata) => { GameMain.ServerListScreen.Select(); GameMain.ServerListScreen.DownloadWorkshopItems(missingPackages.Select(p => p.WorkshopId), serverName, ServerConnection.EndPointString); return(true); }; msgBox.Buttons[0].OnClicked += msgBox.Close; msgBox.Buttons[1].OnClicked = msgBox.Close; } return; } if (!contentPackageOrderReceived) { GameMain.Config.BackUpModOrder(); GameMain.Config.SwapPackages(corePackage.CorePackage, regularPackages.Select(p => p.RegularPackage).ToList()); contentPackageOrderReceived = true; } SendMsgInternal(DeliveryMethod.Reliable, outMsg); break; case ConnectionInitialization.Password: if (initializationStep == ConnectionInitialization.SteamTicketAndVersion) { initializationStep = ConnectionInitialization.Password; } if (initializationStep != ConnectionInitialization.Password) { return; } bool incomingSalt = inc.ReadBoolean(); inc.ReadPadBits(); int retries = 0; if (incomingSalt) { passwordSalt = inc.ReadInt32(); } else { retries = inc.ReadInt32(); } OnRequestPassword?.Invoke(passwordSalt, retries); break; } }