mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 11:40:52 +01:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e78ab8f922 | ||
|
|
6972000293 | ||
|
|
58560f589f | ||
|
|
6e931ac175 | ||
|
|
a7eb5e8115 | ||
|
|
712e4acc66 | ||
|
|
fdcfdffc0b | ||
|
|
74eb8e3e8d | ||
|
|
ae4c764e4f | ||
|
|
7ef2cec121 | ||
|
|
40bff81017 | ||
|
|
f7c28992f8 | ||
|
|
920ae58019 |
@@ -13,7 +13,7 @@ highp float createOcclusion(highp vec2 diff)
|
||||
// Change soft shadow size based on distance from primary occluder.
|
||||
highp float distRatio = (ourDist - occlDist.x) / occlDist.x / 2.0;
|
||||
|
||||
perpendicular *= distRatio;
|
||||
perpendicular *= distRatio * lightSoftness;
|
||||
|
||||
// Totally not hacky PCF on top of VSM.
|
||||
highp float occlusion = smoothstep(0.1, 1.0, ChebyshevUpperBound(occlDist, ourDist));
|
||||
|
||||
@@ -13,6 +13,7 @@ uniform highp vec4 lightColor;
|
||||
uniform highp vec2 lightCenter;
|
||||
uniform highp float lightRange;
|
||||
uniform highp float lightPower;
|
||||
uniform highp float lightSoftness;
|
||||
uniform highp float lightIndex;
|
||||
uniform sampler2D shadowMap;
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ using Robust.Shared.Interfaces.Timers;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -65,6 +66,7 @@ namespace Robust.Client
|
||||
[Dependency] private readonly IScriptClient _scriptClient = default!;
|
||||
[Dependency] private readonly IComponentManager _componentManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IRobustMappedStringSerializer _stringSerializer = default!;
|
||||
|
||||
private CommandLineArgs? _commandLineArgs;
|
||||
private bool _disableAssemblyLoadContext;
|
||||
@@ -125,6 +127,7 @@ namespace Robust.Client
|
||||
ProgramShared.DoMounts(_resourceCache, _commandLineArgs?.MountOptions, "Content.Client", _loaderArgs != null);
|
||||
if (_loaderArgs != null)
|
||||
{
|
||||
_stringSerializer.EnableCaching = false;
|
||||
_resourceCache.MountLoaderApi(_loaderArgs.FileApi, "Resources/");
|
||||
_modLoader.VerifierExtraLoadHandler = VerifierExtraLoadHandler;
|
||||
}
|
||||
|
||||
@@ -83,6 +83,18 @@ namespace Robust.Client.GameObjects
|
||||
set => _energy = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Soft shadow strength multiplier.
|
||||
/// Has no effect if soft shadows are not enabled.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[Animatable]
|
||||
public float Softness
|
||||
{
|
||||
get => _softness;
|
||||
set => _softness = value;
|
||||
}
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool VisibleNested
|
||||
{
|
||||
@@ -115,6 +127,7 @@ namespace Robust.Client.GameObjects
|
||||
private bool _maskAutoRotate;
|
||||
private Angle _rotation;
|
||||
private float _energy;
|
||||
private float _softness;
|
||||
|
||||
/// <summary>
|
||||
/// Radius, in meters.
|
||||
@@ -167,6 +180,7 @@ namespace Robust.Client.GameObjects
|
||||
serializer.DataFieldCached(ref _color, "color", Color.White);
|
||||
serializer.DataFieldCached(ref _enabled, "enabled", true);
|
||||
serializer.DataFieldCached(ref _energy, "energy", 1f);
|
||||
serializer.DataFieldCached(ref _softness, "softness", 1f);
|
||||
serializer.DataFieldCached(ref _maskAutoRotate, "autoRot", false);
|
||||
serializer.DataFieldCached(ref _visibleNested, "nestedvisible", true);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Robust.Client.GameObjects.EntitySystems
|
||||
/// Handles interpolation of transform positions.
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
internal sealed class TransformSystem : EntitySystem
|
||||
internal sealed class TransformSystem : SharedTransformSystem
|
||||
{
|
||||
// Max distance per tick how far an entity can move before it is considered teleporting.
|
||||
// TODO: Make these values somehow dependent on server TPS.
|
||||
|
||||
@@ -11,6 +11,22 @@ namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
static Clyde()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
|
||||
RuntimeInformation.ProcessArchitecture == Architecture.X64)
|
||||
{
|
||||
try
|
||||
{
|
||||
// We force load nvapi64.dll so nvidia gives us the dedicated GPU on optimus laptops.
|
||||
// This is 100x easier than nvidia's documented approach of NvOptimusEnablement,
|
||||
// and works while developing.
|
||||
NativeLibrary.Load("nvapi64.dll");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// If this fails whatever.
|
||||
}
|
||||
}
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -377,6 +377,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
var lastRange = float.NaN;
|
||||
var lastPower = float.NaN;
|
||||
var lastColor = new Color(float.NaN, float.NaN, float.NaN, float.NaN);
|
||||
var lastSoftness = float.NaN;
|
||||
Texture? lastMask = null;
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
@@ -424,6 +425,12 @@ namespace Robust.Client.Graphics.Clyde
|
||||
lightShader.SetUniformMaybe("lightColor", lastColor);
|
||||
}
|
||||
|
||||
if (_enableSoftShadows && !MathHelper.CloseTo(lastSoftness, component.Softness))
|
||||
{
|
||||
lastSoftness = component.Softness;
|
||||
lightShader.SetUniformMaybe("lightSoftness", lastSoftness);
|
||||
}
|
||||
|
||||
lightShader.SetUniformMaybe("lightCenter", lightPos);
|
||||
lightShader.SetUniformMaybe("lightIndex", (i + 0.5f) / ShadowTexture.Height);
|
||||
|
||||
|
||||
@@ -38,7 +38,10 @@ namespace Robust.Client.ResourceManagement
|
||||
{
|
||||
foreach (var relPath in _api.AllFiles)
|
||||
{
|
||||
var resP = new ResourcePath(relPath);
|
||||
if (!relPath.StartsWith(_prefix))
|
||||
continue;
|
||||
|
||||
var resP = new ResourcePath(relPath[_prefix.Length..]);
|
||||
if (resP.TryRelativeTo(path, out _))
|
||||
{
|
||||
yield return resP;
|
||||
|
||||
@@ -38,13 +38,6 @@ namespace Robust.Server.ServerStatus
|
||||
return false;
|
||||
}
|
||||
|
||||
if (OnStatusRequest == null)
|
||||
{
|
||||
_httpSawmill.Warning("OnStatusRequest is not set, responding with a 501.");
|
||||
response.Respond(method, "Not Implemented", HttpStatusCode.NotImplemented);
|
||||
return true;
|
||||
}
|
||||
|
||||
response.StatusCode = (int) HttpStatusCode.OK;
|
||||
response.ContentType = "application/json";
|
||||
|
||||
@@ -53,7 +46,13 @@ namespace Robust.Server.ServerStatus
|
||||
return true;
|
||||
}
|
||||
|
||||
var jObject = new JObject();
|
||||
var jObject = new JObject
|
||||
{
|
||||
// We need to send at LEAST name and player count to have the launcher work with us.
|
||||
// Content can override these if it wants (e.g. stealthmins).
|
||||
["name"] = _serverNameCache,
|
||||
["players"] = _playerManager.PlayerCount
|
||||
};
|
||||
|
||||
OnStatusRequest?.Invoke(jObject);
|
||||
|
||||
|
||||
@@ -7,8 +7,11 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Robust.Server.Interfaces;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Server.Interfaces.ServerStatus;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.Interfaces.Configuration;
|
||||
using Robust.Shared.Interfaces.Log;
|
||||
@@ -28,6 +31,8 @@ namespace Robust.Server.ServerStatus
|
||||
|
||||
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
||||
[Dependency] private readonly IServerNetManager _netManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IBaseServer _baseServer = default!;
|
||||
|
||||
private static readonly JsonSerializer JsonSerializer = new();
|
||||
private readonly List<StatusHostHandler> _handlers = new();
|
||||
@@ -35,6 +40,8 @@ namespace Robust.Server.ServerStatus
|
||||
private TaskCompletionSource? _stopSource;
|
||||
private ISawmill _httpSawmill = default!;
|
||||
|
||||
private string? _serverNameCache;
|
||||
|
||||
public Task ProcessRequestAsync(HttpListenerContext context)
|
||||
{
|
||||
var response = context.Response;
|
||||
@@ -85,6 +92,10 @@ namespace Robust.Server.ServerStatus
|
||||
_httpSawmill = Logger.GetSawmill($"{Sawmill}.http");
|
||||
RegisterCVars();
|
||||
|
||||
// Cache this in a field to avoid thread safety shenanigans.
|
||||
// Writes/reads of references are atomic in C# so no further synchronization necessary.
|
||||
_configurationManager.OnValueChanged(CVars.GameHostName, n => _serverNameCache = n);
|
||||
|
||||
if (!_configurationManager.GetCVar(CVars.StatusEnabled))
|
||||
{
|
||||
return;
|
||||
@@ -146,15 +157,22 @@ namespace Robust.Server.ServerStatus
|
||||
var buildInfo = File.ReadAllText(PathHelpers.ExecutableRelativeFile("build.json"));
|
||||
var info = JsonConvert.DeserializeObject<BuildInfo>(buildInfo);
|
||||
|
||||
_configurationManager.SetCVar(CVars.BuildEngineVersion, info.EngineVersion);
|
||||
_configurationManager.SetCVar(CVars.BuildForkId, info.ForkId);
|
||||
_configurationManager.SetCVar(CVars.BuildVersion, info.Version);
|
||||
_configurationManager.SetCVar(CVars.BuildDownloadUrl, info.Download);
|
||||
_configurationManager.SetCVar(CVars.BuildHash, info.Hash ?? "");
|
||||
// Don't replace cvars with contents of build.json if overriden by --cvar or such.
|
||||
SetCVarIfUnmodified(CVars.BuildEngineVersion, info.EngineVersion);
|
||||
SetCVarIfUnmodified(CVars.BuildForkId, info.ForkId);
|
||||
SetCVarIfUnmodified(CVars.BuildVersion, info.Version);
|
||||
SetCVarIfUnmodified(CVars.BuildDownloadUrl, info.Download ?? "");
|
||||
SetCVarIfUnmodified(CVars.BuildHash, info.Hash ?? "");
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
}
|
||||
|
||||
void SetCVarIfUnmodified(CVarDef<string> cvar, string val)
|
||||
{
|
||||
if (_configurationManager.GetCVar(cvar) == "")
|
||||
_configurationManager.SetCVar(cvar, val);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
@@ -172,8 +190,8 @@ namespace Robust.Server.ServerStatus
|
||||
private sealed class BuildInfo
|
||||
{
|
||||
[JsonProperty("engine_version")] public string EngineVersion = default!;
|
||||
[JsonProperty("hashes")] public string? Hash;
|
||||
[JsonProperty("downloads")] public string Download = default!;
|
||||
[JsonProperty("hash")] public string? Hash;
|
||||
[JsonProperty("download")] public string? Download;
|
||||
[JsonProperty("fork_id")] public string ForkId = default!;
|
||||
[JsonProperty("version")] public string Version = default!;
|
||||
}
|
||||
|
||||
@@ -233,10 +233,10 @@ namespace Robust.Shared
|
||||
CVarDef.Create("display.height", 720, CVar.CLIENTONLY);
|
||||
|
||||
public static readonly CVarDef<int> DisplayLightMapDivider =
|
||||
CVarDef.Create("display.lightmapdivider", 2, CVar.CLIENTONLY);
|
||||
CVarDef.Create("display.lightmapdivider", 2, CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||
|
||||
public static readonly CVarDef<bool> DisplaySoftShadows =
|
||||
CVarDef.Create("display.softshadows", true, CVar.CLIENTONLY);
|
||||
CVarDef.Create("display.softshadows", true, CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||
|
||||
public static readonly CVarDef<float> DisplayUIScale =
|
||||
CVarDef.Create("display.uiScale", 0f, CVar.ARCHIVE | CVar.CLIENTONLY);
|
||||
@@ -261,7 +261,7 @@ namespace Robust.Shared
|
||||
CVarDef.Create("audio.device", string.Empty, CVar.CLIENTONLY);
|
||||
|
||||
public static readonly CVarDef<float> AudioMasterVolume =
|
||||
CVarDef.Create("audio.mastervolume", 1.0f, CVar.CLIENTONLY);
|
||||
CVarDef.Create("audio.mastervolume", 1.0f, CVar.ARCHIVE | CVar.CLIENTONLY);
|
||||
|
||||
/*
|
||||
* PLAYER
|
||||
|
||||
@@ -845,6 +845,7 @@ Types:
|
||||
Func`15: { All: True }
|
||||
Func`16: { All: True }
|
||||
Func`17: { All: True }
|
||||
Guid: { All: True }
|
||||
HashCode: { All: True }
|
||||
IAsyncDisposable: { All: True }
|
||||
IAsyncResult: { }
|
||||
|
||||
@@ -5,6 +5,7 @@ using Robust.Shared.Animations;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects.Components.Map;
|
||||
using Robust.Shared.GameObjects.EntitySystemMessages;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects.Components;
|
||||
using Robust.Shared.Interfaces.Map;
|
||||
@@ -722,8 +723,9 @@ namespace Robust.Shared.GameObjects.Components.Transform
|
||||
var oldPos = Coordinates;
|
||||
SetPosition(newState.LocalPosition);
|
||||
|
||||
Owner.EntityManager.EventBus.RaiseEvent(
|
||||
EventSource.Local, new MoveEvent(Owner, oldPos, Coordinates));
|
||||
var ev = new MoveEvent(Owner, oldPos, Coordinates);
|
||||
EntitySystem.Get<SharedTransformSystem>().DeferMoveEvent(ev);
|
||||
|
||||
rebuildMatrices = true;
|
||||
}
|
||||
|
||||
@@ -873,6 +875,7 @@ namespace Robust.Shared.GameObjects.Components.Transform
|
||||
public IEntity Sender { get; }
|
||||
public EntityCoordinates OldPosition { get; }
|
||||
public EntityCoordinates NewPosition { get; }
|
||||
public bool Handled { get; set; }
|
||||
}
|
||||
|
||||
public class RotateEvent : EntitySystemMessage
|
||||
|
||||
34
Robust.Shared/GameObjects/Systems/SharedTransformSystem.cs
Normal file
34
Robust.Shared/GameObjects/Systems/SharedTransformSystem.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Robust.Shared.GameObjects.Components.Map;
|
||||
using Robust.Shared.GameObjects.Components.Transform;
|
||||
|
||||
namespace Robust.Shared.GameObjects.Systems
|
||||
{
|
||||
internal class SharedTransformSystem : EntitySystem
|
||||
{
|
||||
private readonly List<MoveEvent> _deferredMoveEvents = new();
|
||||
|
||||
public void DeferMoveEvent(MoveEvent moveEvent)
|
||||
{
|
||||
_deferredMoveEvents.Add(moveEvent);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var events = _deferredMoveEvents
|
||||
.OrderBy(e => e.Sender.HasComponent<IMapGridComponent>())
|
||||
.ToArray();
|
||||
|
||||
foreach (var ev in events)
|
||||
{
|
||||
ev.Sender.EntityManager.EventBus.RaiseEvent(EventSource.Local, ev);
|
||||
ev.Handled = true;
|
||||
}
|
||||
|
||||
_deferredMoveEvents.RemoveAll(e => e.Handled);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,8 @@ namespace Robust.Shared.Serialization
|
||||
/// </exception>
|
||||
ReadOnlySpan<byte> MappedStringsHash { get; }
|
||||
|
||||
bool EnableCaching { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Add a string to the constant mapping.
|
||||
/// </summary>
|
||||
|
||||
@@ -29,6 +29,8 @@ namespace Robust.Shared.Reflection
|
||||
|
||||
private readonly Dictionary<(Type baseType, string typeName), Type?> _yamlTypeTagCache = new();
|
||||
|
||||
private readonly Dictionary<string, Type> _looseTypeCache = new();
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<Type> GetAllChildren<T>(bool inclusive = false)
|
||||
{
|
||||
@@ -134,6 +136,9 @@ namespace Robust.Shared.Reflection
|
||||
|
||||
public bool TryLooseGetType(string name, [NotNullWhen(true)] out Type? type)
|
||||
{
|
||||
if (_looseTypeCache.TryGetValue(name, out type))
|
||||
return true;
|
||||
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
foreach (var tryType in assembly.DefinedTypes)
|
||||
@@ -141,6 +146,7 @@ namespace Robust.Shared.Reflection
|
||||
if (tryType.FullName!.EndsWith(name))
|
||||
{
|
||||
type = tryType;
|
||||
_looseTypeCache[name] = type;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +121,8 @@ namespace Robust.Shared.Serialization
|
||||
/// </exception>
|
||||
public ReadOnlySpan<byte> MappedStringsHash => _stringMapHash;
|
||||
|
||||
public bool EnableCaching { get; set; } = true;
|
||||
|
||||
private static readonly Regex RxSymbolSplitter
|
||||
= new(
|
||||
@"(?<=[^\s\W])(?=[A-Z]) # Match for split at start of new capital letter
|
||||
@@ -283,7 +285,10 @@ namespace Robust.Shared.Serialization
|
||||
LogSzr.Debug($"Locked in at {_dict.StringCount} mapped strings.");
|
||||
|
||||
packageStream.Position = 0;
|
||||
WriteStringCache(packageStream);
|
||||
if (EnableCaching)
|
||||
{
|
||||
WriteStringCache(packageStream);
|
||||
}
|
||||
|
||||
// ok we're good now
|
||||
var channel = msg.MsgChannel;
|
||||
@@ -405,7 +410,7 @@ namespace Robust.Shared.Serialization
|
||||
LogSzr.Debug($"Received server handshake with hash {hashStr}.");
|
||||
|
||||
var fileName = CacheForHash(hashStr);
|
||||
if (!File.Exists(fileName))
|
||||
if (fileName == null || !File.Exists(fileName))
|
||||
{
|
||||
LogSzr.Debug($"No string cache for {hashStr}.");
|
||||
var handshake = _net.CreateNetMessage<MsgMapStrClientHandshake>();
|
||||
@@ -458,8 +463,12 @@ namespace Robust.Shared.Serialization
|
||||
/// file itself may or may not exist. If it does not exist, no cache
|
||||
/// was made for the given hash.
|
||||
/// </returns>
|
||||
private static string CacheForHash(string hashStr)
|
||||
private string? CacheForHash(string hashStr)
|
||||
{
|
||||
if (!EnableCaching)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return PathHelpers.ExecutableRelativeFile($"strings-{hashStr}");
|
||||
}
|
||||
|
||||
@@ -471,7 +480,7 @@ namespace Robust.Shared.Serialization
|
||||
var hashStr = Convert.ToBase64String(MappedStringsHash);
|
||||
hashStr = ConvertToBase64Url(hashStr);
|
||||
|
||||
var fileName = CacheForHash(hashStr);
|
||||
var fileName = CacheForHash(hashStr)!;
|
||||
using var file = File.OpenWrite(fileName);
|
||||
stream.CopyTo(file);
|
||||
|
||||
|
||||
@@ -614,6 +614,11 @@ namespace Robust.Shared.Serialization
|
||||
throw new ArgumentException($"Type {type.FullName} is not supported.", nameof(type));
|
||||
}
|
||||
|
||||
public T NodeToType<T>(YamlNode node)
|
||||
{
|
||||
return (T) NodeToType(typeof(T), node);
|
||||
}
|
||||
|
||||
private static Type ResolveConcreteType(Type baseType, string typeName)
|
||||
{
|
||||
var reflection = IoCManager.Resolve<IReflectionManager>();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System.IO;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Robust.Client.Interfaces.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components.Transform;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.GameObjects.Components;
|
||||
using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
@@ -35,6 +35,17 @@ namespace Robust.UnitTesting.Client.GameObjects.Components
|
||||
private MapId MapB;
|
||||
private IMapGrid GridB = default!;
|
||||
|
||||
protected override void OverrideIoC()
|
||||
{
|
||||
base.OverrideIoC();
|
||||
|
||||
var mock = new Mock<IEntitySystemManager>();
|
||||
var system = new SharedTransformSystem();
|
||||
mock.Setup(m => m.GetEntitySystem<SharedTransformSystem>()).Returns(system);
|
||||
|
||||
IoCManager.RegisterInstance<IEntitySystemManager>(mock.Object, true);
|
||||
}
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void Setup()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user