/// <summary> /// Handles the reception, verification of a strings package /// and subsequent mapping of strings and initiator of /// receipt response. /// /// Uncached flow: <code> /// Client | Server /// | <-------------- Hash | /// | Need Strings ------> | /// | <----------- Strings | /// | Dont Need Strings -> | <- you are here on client /// /// Verification failure flow: <code> /// Client | Server /// | <-------------- Hash | /// | Need Strings ------> | /// | <----------- Strings | /// + Hash Failed | <- you are here on client /// | Need Strings ------> | /// | <----------- Strings | /// | Dont Need Strings -> | <- you are here on client /// </code> /// /// NOTE: Verification failure flow is currently not implemented. /// </code> /// </summary> /// <exception cref="InvalidOperationException">Unable to verify strings package by hash.</exception> /// <seealso cref="NetworkInitialize"/> private void HandleStringsMessage(INetManager net, MsgRobustMappedStringsSerializerStrings msgRobustMappedStringsSerializer) { if (net.IsServer) { LogSzr.Error("Received strings from client."); return; } LockMappedStrings = false; ClearStrings(); DebugTools.Assert(msgRobustMappedStringsSerializer.Package != null, "msg.Package != null"); LoadStrings(new MemoryStream(msgRobustMappedStringsSerializer.Package !, false)); var checkHash = CalculateHash(msgRobustMappedStringsSerializer.Package !); if (!checkHash.SequenceEqual(ServerHash)) { // TODO: retry sending MsgClientHandshake with NeedsStrings = false throw new InvalidOperationException("Unable to verify strings package by hash." + $"\n{ConvertToBase64Url(checkHash)} vs. {ConvertToBase64Url(ServerHash)}"); } _stringMapHash = ServerHash; LockMappedStrings = true; LogSzr.Debug($"Locked in at {_mappedStrings.Count} mapped strings."); WriteStringCache(); // ok we're good now var channel = msgRobustMappedStringsSerializer.MsgChannel; OnClientCompleteHandshake(net, channel); }
/// <summary> /// Polymorphs the target entity into the specific polymorph prototype /// </summary> /// <param name="target">The entity that will be transformed</param> /// <param name="id">The id of the polymorph prototype</param> public EntityUid?PolymorphEntity(EntityUid target, string id) { if (!_proto.TryIndex <PolymorphPrototype>(id, out var proto)) { _saw.Error("Invalid polymorph prototype"); return(null); } return(PolymorphEntity(target, proto)); }
private void RequestHandler(IRequestHandlerContext context) { Uri newUri = new Uri(context.Url); if (newUri.Scheme == "usr") { Stream stream; HttpStatusCode status; var path = new ResourcePath(newUri.AbsolutePath); try { stream = _resourceManager.UserData.OpenRead(_dreamResource.GetCacheFilePath(newUri.AbsolutePath)); status = HttpStatusCode.OK; } catch (FileNotFoundException) { stream = Stream.Null; status = HttpStatusCode.NotFound; } catch (Exception e) { _sawmill.Error($"Exception while loading file from usr://:\n{e}"); stream = Stream.Null; status = HttpStatusCode.InternalServerError; } if (!FileExtensionMimeTypes.TryGetValue(path.Extension, out var mimeType)) { mimeType = "application/octet-stream"; } context.DoRespondStream(stream, mimeType, status); return; } }
private void HandleCameraKick(CameraKickEvent args) { if (!EntityManager.TryGetComponent(args.Euid, out CameraRecoilComponent recoil)) { _log.Warning($"Received a kick for euid {args.Euid}, but it is missing required components."); return; } if (!float.IsFinite(args.Recoil.X) || !float.IsFinite(args.Recoil.Y)) { _log.Error($"CameraRecoilComponent on entity {recoil.Owner} passed a NaN recoil value. Ignoring."); return; } // Use really bad math to "dampen" kicks when we're already kicked. var existing = recoil.CurrentKick.Length; var dampen = existing / KickMagnitudeMax; recoil.CurrentKick += args.Recoil * (1 - dampen); if (recoil.CurrentKick.Length > KickMagnitudeMax) { recoil.CurrentKick = recoil.CurrentKick.Normalized * KickMagnitudeMax; } recoil.LastKickTime = 0; }
private void LoadGroupYamlStream(Stream stream) { try { using (var reader = new StreamReader(stream)) { var groupList = new Deserializer().Deserialize <List <ConGroup> >(reader); foreach (var permGroup in groupList) { var grpIndex = new ConGroupIndex(permGroup.Index); if (!_groups.ContainsKey(grpIndex)) { _groups.Add(grpIndex, permGroup); } } } } catch (Exception e) { _logger.Error($"Could not parse the yaml group file! {e.Message}"); } }
private void UpdateEffects(ThirstComponent component) { if (IsMovementThreshold(component.LastThirstThreshold) != IsMovementThreshold(component.CurrentThirstThreshold) && TryComp(component.Owner, out MovementSpeedModifierComponent? movementSlowdownComponent)) { _movement.RefreshMovementSpeedModifiers(component.Owner, movementSlowdownComponent); } // Update UI if (ThirstComponent.ThirstThresholdAlertTypes.TryGetValue(component.CurrentThirstThreshold, out var alertId)) { _alerts.ShowAlert(component.Owner, alertId); } else { _alerts.ClearAlertCategory(component.Owner, AlertCategory.Thirst); } switch (component.CurrentThirstThreshold) { case ThirstThreshold.OverHydrated: component.LastThirstThreshold = component.CurrentThirstThreshold; component.ActualDecayRate = component.BaseDecayRate * 1.2f; return; case ThirstThreshold.Okay: component.LastThirstThreshold = component.CurrentThirstThreshold; component.ActualDecayRate = component.BaseDecayRate; return; case ThirstThreshold.Thirsty: // Same as okay except with UI icon saying drink soon. component.LastThirstThreshold = component.CurrentThirstThreshold; component.ActualDecayRate = component.BaseDecayRate * 0.8f; return; case ThirstThreshold.Parched: _movement.RefreshMovementSpeedModifiers(component.Owner); component.LastThirstThreshold = component.CurrentThirstThreshold; component.ActualDecayRate = component.BaseDecayRate * 0.6f; return; case ThirstThreshold.Dead: return; default: _sawmill.Error($"No thirst threshold found for {component.CurrentThirstThreshold}"); throw new ArgumentOutOfRangeException($"No thirst threshold found for {component.CurrentThirstThreshold}"); } }
public void Error(string message, params object[] args) { if (message.StartsWith("Failed connection to") || message == "Failed to connect for some reason.") { if (_successfullyConnected) { _successfullyConnected = false; } else { return; } } _sawmill.Error(message, args); }
/// <summary> /// Interpret a server's handshake, either requesting a package /// of strings or completing the handshake. /// /// Uncached flow: <code> /// Client | Server /// | <-------------- Hash | <- you are here on client /// | Need Strings ------> | /// | <----------- Strings | /// | Dont Need Strings -> | /// </code> /// /// Cached flow: <code> /// Client | Server /// | <-------------- Hash | <- you are here on client /// | Dont Need Strings -> | /// </code> /// /// Verification failure flow: <code> /// Client | Server /// | <-------------- Hash | <- you are here on client /// | Need Strings ------> | /// | <----------- Strings | /// + Hash Failed | /// | Need Strings ------> | /// | <----------- Strings | /// | Dont Need Strings -> | /// </code> /// /// NOTE: Verification failure flow is currently not implemented. /// </summary> /// <exception cref="InvalidOperationException">Mapped strings are locked.</exception> /// <seealso cref="NetworkInitialize"/> private void HandleServerHandshake(MsgMapStrServerHandshake msgMapStr) { if (_net.IsServer) { LogSzr.Error("Received server handshake on server."); return; } _serverHash = msgMapStr.Hash; var hashStr = ConvertToBase64Url(msgMapStr.Hash !); LogSzr.Debug($"Received server handshake with hash {hashStr}."); var fileName = CacheForHash(hashStr); if (!File.Exists(fileName)) { LogSzr.Debug($"No string cache for {hashStr}."); var handshake = _net.CreateNetMessage <MsgMapStrClientHandshake>(); LogSzr.Debug("Asking server to send mapped strings."); handshake.NeedsStrings = true; msgMapStr.MsgChannel.SendMessage(handshake); } else { LogSzr.Debug($"We had a cached string map that matches {hashStr}."); using var file = File.OpenRead(fileName); var added = _dict.LoadFromPackage(file, out _); _stringMapHash = msgMapStr.Hash !; LogSzr.Debug($"Read {added} strings from cache {hashStr}."); LogSzr.Debug($"Locked in at {_dict.StringCount} mapped strings."); // ok we're good now var channel = msgMapStr.MsgChannel; OnClientCompleteHandshake(_net, channel); } }
private void PreloadTextures(ISawmill sawmill) { sawmill.Debug("Preloading textures..."); var sw = Stopwatch.StartNew(); var resList = GetTypeDict <TextureResource>(); var texList = ContentFindFiles("/Textures/") // Skip PNG files inside RSIs. .Where(p => p.Extension == "png" && !p.ToString().Contains(".rsi/") && !resList.ContainsKey(p)) .Select(p => new TextureResource.LoadStepData { Path = p }) .ToArray(); Parallel.ForEach(texList, data => { try { TextureResource.LoadPreTexture(this, data); } catch (Exception e) { // Mark failed loads as bad and skip them in the next few stages. // Avoids any silly array resizing or similar. sawmill.Error($"Exception while loading RSI {data.Path}:\n{e}"); data.Bad = true; } }); foreach (var data in texList) { if (data.Bad) { continue; } try { TextureResource.LoadTexture(_clyde, data); } catch (Exception e) { sawmill.Error($"Exception while loading RSI {data.Path}:\n{e}"); data.Bad = true; } } var errors = 0; foreach (var data in texList) { if (data.Bad) { errors += 1; continue; } try { var texResource = new TextureResource(); texResource.LoadFinish(this, data); resList[data.Path] = texResource; } catch (Exception e) { sawmill.Error($"Exception while loading RSI {data.Path}:\n{e}"); data.Bad = true; errors += 1; } } sawmill.Debug( "Preloaded {CountLoaded} textures ({CountErrored} errored) in {LoadTime}", texList.Length, errors, sw.Elapsed); }
private void PreloadRsis(ISawmill sawmill) { var sw = Stopwatch.StartNew(); var resList = GetTypeDict <RSIResource>(); var rsiList = ContentFindFiles("/Textures/") .Where(p => p.ToString().EndsWith(".rsi/meta.json")) .Select(c => c.Directory) .Where(p => !resList.ContainsKey(p)) .Select(p => new RSIResource.LoadStepData { Path = p }) .ToArray(); Parallel.ForEach(rsiList, data => { try { RSIResource.LoadPreTexture(this, data); } catch (Exception e) { // Mark failed loads as bad and skip them in the next few stages. // Avoids any silly array resizing or similar. sawmill.Error($"Exception while loading RSI {data.Path}:\n{e}"); data.Bad = true; } }); foreach (var data in rsiList) { if (data.Bad) { continue; } try { RSIResource.LoadTexture(_clyde, data); } catch (Exception e) { sawmill.Error($"Exception while loading RSI {data.Path}:\n{e}"); data.Bad = true; } } Parallel.ForEach(rsiList, data => { if (data.Bad) { return; } try { RSIResource.LoadPostTexture(data); } catch (Exception e) { data.Bad = true; sawmill.Error($"Exception while loading RSI {data.Path}:\n{e}"); } }); var errors = 0; foreach (var data in rsiList) { if (data.Bad) { errors += 1; continue; } try { var rsiRes = new RSIResource(); rsiRes.LoadFinish(this, data); resList[data.Path] = rsiRes; } catch (Exception e) { sawmill.Error($"Exception while loading RSI {data.Path}:\n{e}"); data.Bad = true; errors += 1; } } sawmill.Debug( "Preloaded {CountLoaded} RSIs ({CountErrored} errored) in {LoadTime}", rsiList.Length, errors, sw.Elapsed); }
private DockingComponent?GetDockable(PhysicsComponent body, TransformComponent dockingXform) { // Did you know Saltern is the most dockable station? // Assume the docking port itself (and its body) is valid if (!_mapManager.TryGetGrid(dockingXform.GridUid, out var grid) || !HasComp <ShuttleComponent>(grid.GridEntityId)) { return(null); } var transform = body.GetTransform(); var dockingFixture = _fixtureSystem.GetFixtureOrNull(body, DockingFixture); if (dockingFixture == null) { return(null); } Box2?aabb = null; for (var i = 0; i < dockingFixture.Shape.ChildCount; i++) { aabb = aabb?.Union(dockingFixture.Shape.ComputeAABB(transform, i)) ?? dockingFixture.Shape.ComputeAABB(transform, i); } if (aabb == null) { return(null); } var enlargedAABB = aabb.Value.Enlarged(DockingRadius * 1.5f); // Get any docking ports in range on other grids. _mapManager.FindGridsIntersectingEnumerator(dockingXform.MapID, enlargedAABB, out var enumerator); while (enumerator.MoveNext(out var otherGrid)) { if (otherGrid.GridEntityId == dockingXform.GridUid) { continue; } foreach (var ent in otherGrid.GetAnchoredEntities(enlargedAABB)) { if (!TryComp(ent, out DockingComponent? otherDocking) || !otherDocking.Enabled || !TryComp(ent, out PhysicsComponent? otherBody)) { continue; } var otherTransform = otherBody.GetTransform(); var otherDockingFixture = _fixtureSystem.GetFixtureOrNull(otherBody, DockingFixture); if (otherDockingFixture == null) { DebugTools.Assert(false); _sawmill.Error($"Found null docking fixture on {ent}"); continue; } for (var i = 0; i < otherDockingFixture.Shape.ChildCount; i++) { var otherAABB = otherDockingFixture.Shape.ComputeAABB(otherTransform, i); if (!aabb.Value.Intersects(otherAABB)) { continue; } // TODO: Need CollisionManager's GJK for accurate bounds // Realistically I want 2 fixtures anyway but I'll deal with that later. return(otherDocking); } } } return(null); }
public void Error(string message, params object[] args) { _sawmill.Error(message, args); }