Compare commits

...

298 Commits

Author SHA1 Message Date
Silver
d49075a970 Update and clean up Prototype manager methods 2022-02-11 00:27:34 -07:00
Silver
a67acd453c Split out Interface and Attribute 2022-02-11 00:26:58 -07:00
ElectroJr
b540f04a7a Version: 0.8.52 2022-02-10 21:46:08 +13:00
Leon Friedrich
bcaa7001ad Hopefully fix container occlusion bug? (#2464) 2022-02-10 09:29:26 +01:00
metalgearsloth
3f0fba7b4e Version: 0.8.51 2022-02-10 12:57:00 +11:00
metalgearsloth
d7d7a53045 Raise appearance event by ref 2022-02-10 12:56:14 +11:00
metalgearsloth
40daba9adf Version: 0.8.50 2022-02-10 12:53:26 +11:00
mirrorcult
5665f8eb1c Abstract VisualizerSystem (#2522) 2022-02-10 12:52:42 +11:00
metalgearsloth
8f0d562f3e Version: 0.8.49 2022-02-10 11:21:29 +11:00
ike709
f3950e940e Re-adds UpdateEntityTree() to EntityLookup's interface (#2525) 2022-02-10 11:15:09 +11:00
Leon Friedrich
3fdca65cc9 Make occluder use try get map (#2516) 2022-02-10 01:40:11 +11:00
ike709
23d0b8a555 Expose LastTick on IGameTiming (#2518) 2022-02-08 14:02:36 +11:00
mirrorcult
452b03d5a6 Merge pull request #2513 from metalgearsloth/2022-02-07_EnsureCompOut 2022-02-07 13:41:59 -07:00
metalgearsloth
c8f2dab381 Don't crash on VV edit for angles (#2517) 2022-02-08 02:58:55 +11:00
metalgearsloth
7409df07f8 Merge remote-tracking branch 'upstream/master' into 2022-02-07_EnsureCompOut 2022-02-07 19:55:45 +11:00
metalgearsloth
973406b91d Cleanup contact code a lot (#2480) 2022-02-07 13:10:58 +11:00
metalgearsloth
2e646fe2b6 EntityQueryEnumerator "fix" (#2501) 2022-02-07 12:06:50 +11:00
mirrorcult
6b902d22d4 Merge pull request #2504 from metalgearsloth/2022-02-03_appearance-events
Appearance data event
2022-02-06 11:23:01 -07:00
metalgearsloth
83e6d52e58 Version: 0.8.47 2022-02-07 02:56:24 +11:00
metalgearsloth
025fdcd0b3 GetHardAABB (#2514) 2022-02-07 02:10:02 +11:00
metalgearsloth
fe3ace92bd Another helper 2022-02-07 02:04:57 +11:00
metalgearsloth
317070f167 Some animation helpers for cargo telepad too 2022-02-07 02:00:31 +11:00
metalgearsloth
3524363ad4 fix build 2022-02-07 01:44:27 +11:00
metalgearsloth
90287dbb09 Merge remote-tracking branch 'upstream/master' into 2022-02-03_appearance-events
# Conflicts:
#	Robust.Shared/GameObjects/Components/Appearance/AppearanceComponent.cs
2022-02-07 01:42:53 +11:00
metalgearsloth
9a2f35f2d3 Also pass comp 2022-02-07 01:42:32 +11:00
metalgearsloth
3f10dbe770 EnsureComponent<T> with out variable
Useful for EnsureComponent<T>(uid, out var comp) && comp.Thing
2022-02-07 00:07:01 +11:00
metalgearsloth
8fcba93ada Don't draw 0-mass non-hard fixtures as invalid (#2499) 2022-02-06 19:42:47 +11:00
ElectroJr
35366b5bc1 Version: 0.8.46 2022-02-06 15:18:56 +13:00
mirrorcult
d8bf31ecc4 Merge pull request #2510 from ElectroJr/fix-sprite-bug 2022-02-05 15:23:25 -07:00
Pieter-Jan Briers
de4d255841 Analyzer to enforce classes to be either [Virtual], abstract, or sealed. (#2469)
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
2022-02-05 19:31:58 +01:00
Leon Friedrich
ec768c563f Add spin command (#2484) 2022-02-05 12:38:02 +11:00
metalgearsloth
2114d2bc67 Funny struct enumerator for xform kids (#2487) 2022-02-05 12:32:13 +11:00
ElectroJr
43478d0e45 avoid unnecessary RoundToCardinal calls 2022-02-05 14:27:31 +13:00
Leon Friedrich
561699b26e Replace EntityDirtyEvent with C# event. (#2495) 2022-02-05 12:23:51 +11:00
ElectroJr
460923e54d fix sprite bug 2022-02-05 14:10:28 +13:00
Kara D
c299104f0c Version: 0.8.45 2022-02-04 14:35:35 -07:00
Kara D
224bebeeb5 ok then 2022-02-04 14:35:15 -07:00
Kara D
52c8e8ecdf Version: 0.8.44 2022-02-04 14:20:48 -07:00
mirrorcult
ac636b2703 Merge pull request #2441 from metalgearsloth/2022-01-20_more-caching 2022-02-04 14:13:26 -07:00
mirrorcult
a892f9ac99 Merge pull request #2506 from metalgearsloth/2022-02-04_xform-children 2022-02-04 14:13:18 -07:00
mirrorcult
2ebee8f40c Merge pull request #2508 from metalgearsloth/2022-02-04_powa 2022-02-04 14:13:10 -07:00
mirrorcult
43741dc5fc Merge pull request #2490 from metalgearsloth/2022-02-01_game-state 2022-02-04 14:12:56 -07:00
metalgearsloth
da9467b678 Reduce FindGridsIntersecting allocs 2022-02-04 17:44:44 +11:00
Leon Friedrich
8f24a7b4fc Reduce ContainerHelper IoCManager resolves (#2498) 2022-02-04 12:51:29 +11:00
metalgearsloth
ff48959e97 Merge remote-tracking branch 'upstream/master' into 2022-01-20_more-caching 2022-02-04 12:46:01 +11:00
metalgearsloth
09e648d086 Version: 0.8.43 2022-02-04 12:43:43 +11:00
metalgearsloth
1d1db2e109 Also that sneaky pvs one 2022-02-04 12:40:40 +11:00
metalgearsloth
6a902286cd Merge remote-tracking branch 'upstream/master' into 2022-01-20_more-caching 2022-02-04 12:38:32 +11:00
metalgearsloth
933724e4ee Nuke CompGetStateAttempt allocs (#2497) 2022-02-04 12:35:57 +11:00
metalgearsloth
53034e6f05 Replace xform children sortedset with hashset 2022-02-04 12:27:51 +11:00
metalgearsloth
6a31c5649c Tweak 2022-02-03 18:03:56 +11:00
metalgearsloth
7bd90578dc Appearance data event
We agreed that AppearanceVisualizers should probably be deprecated in favour of just using a system instead.
2022-02-03 18:01:31 +11:00
metalgearsloth
c076be95a6 Version: 0.8.42 2022-02-03 13:26:13 +11:00
metalgearsloth
7b732dd68a Remove unnecessary resolves from MapLoader (#2462) 2022-02-03 13:25:22 +11:00
metalgearsloth
3e34b1414e The end of IMapInit (#2479) 2022-02-03 13:15:17 +11:00
Acruid
8456cd90d1 Move MapGrid data from MapManager to MapGridComponent (#2430) 2022-02-03 13:15:06 +11:00
Pieter-Jan Briers
d716e1ff62 Fix EstPixelSize for Rg32f.
This function literally isn't used but that won't stop me from making this commit.
2022-02-02 21:46:42 +01:00
metalgearsloth
8e9acc9191 Reduce broadphase allocs a l'il bit (#2493) 2022-02-03 00:52:04 +11:00
metalgearsloth
773a068b7d Merge remote-tracking branch 'upstream/master' into 2022-02-01_game-state 2022-02-02 22:13:17 +11:00
metalgearsloth
b37bfff155 Remove string allocs from client prediction (#2494) 2022-02-02 21:59:40 +11:00
Leon Friedrich
a14cce222b Misc physics/shutdown related optimizations (#2496) 2022-02-02 18:12:53 +11:00
Leon Friedrich
c077e09436 Add explicit transform matrices (#2483) 2022-02-02 10:03:45 +11:00
Leon Friedrich
213955566b remove GetBus() (#2491) 2022-02-02 10:03:03 +11:00
metalgearsloth
b98cd3e6e1 Reduce batch for lowerpop I guess 2022-02-01 23:11:35 +11:00
metalgearsloth
987c8e8229 Reduce gamestate allocs
Parallel.ForEach has no right to be that expensive.
2022-02-01 23:11:05 +11:00
metalgearsloth
fcbb97ec55 Fix edge collisions (#2482) 2022-02-01 15:28:12 +11:00
Pieter-Jan Briers
c1ac7aebdb Version: 0.8.41 2022-01-31 17:37:35 +01:00
Pieter-Jan Briers
e4b0d1a03c Hotfix servers not working due to auto pause. 2022-01-31 17:37:19 +01:00
Leon Friedrich
f13f9dc5cd Make OffsetRsiDir() and GetDir() public (#2434) 2022-01-31 19:22:56 +11:00
metalgearsloth
1f6170c000 Merge remote-tracking branch 'upstream/master' into 2022-01-20_more-caching 2022-01-31 18:21:23 +11:00
metalgearsloth
53c7ec8ddc Version: 0.8.40 2022-01-31 17:55:53 +11:00
metalgearsloth
e438e53d36 Silly caching 2022-01-31 17:50:30 +11:00
metalgearsloth
792608f0d0 Merge remote-tracking branch 'upstream/master' into 2022-01-20_more-caching 2022-01-31 17:42:09 +11:00
metalgearsloth
7b5678fd0f woops 2022-01-31 17:34:49 +11:00
metalgearsloth
88c328a636 Smol entityquery change 2022-01-31 17:33:21 +11:00
metalgearsloth
f9573530a8 Nuke entitylookup to get it merged 2022-01-31 17:30:53 +11:00
Leon Friedrich
c1df7dcca7 Move some static helpers to container system (#2470) 2022-01-31 17:21:09 +11:00
Pieter-Jan Briers
f141a0033e Automatically pause server if no players connected. (#2465) 2022-01-31 17:20:26 +11:00
metalgearsloth
227d047584 Version: 0.8.39 2022-01-31 16:25:52 +11:00
metalgearsloth
73b73cd9da Fix InvWorldMatrix helper (#2478) 2022-01-31 16:20:21 +11:00
Pieter-Jan Briers
66be082bdb Fix display.angle_force_es2 defaulting to true. 2022-01-30 20:21:35 +01:00
Pieter-Jan Briers
ac43cf0de1 Fix GLES2 support. 2022-01-30 20:20:23 +01:00
Pieter-Jan Briers
fb41601d9f CVar to force a GLES2 context with GLContextAngle. 2022-01-30 18:06:59 +01:00
metalgearsloth
f35dda3fb3 Version: 0.8.38 2022-01-31 02:09:20 +11:00
metalgearsloth
7ee14f6f4f Remove some unnecessary writer resolves (#2475) 2022-01-31 00:54:30 +11:00
metalgearsloth
97920b42ee Fix FindGridContacts (#2474) 2022-01-30 18:32:13 +11:00
metalgearsloth
8ace0ec254 Fix entity map change crash (#2461) 2022-01-30 17:44:07 +11:00
metalgearsloth
a3606f1098 Fix grid fixture deserialization (#2472) 2022-01-30 17:09:22 +11:00
metalgearsloth
616d379902 Version: 0.8.37 2022-01-29 16:18:05 +11:00
metalgearsloth
a27f475715 Proxy method for entitymanager.dirty(comp) (#2467) 2022-01-29 16:16:32 +11:00
Leon Friedrich
6ee76e8f46 Fix point light add/remove (#2466) 2022-01-29 16:05:23 +11:00
metalgearsloth
891c30c9be Fix maplinearvelocity? (#2317) 2022-01-27 18:01:20 +11:00
metalgearsloth
9757a4c3b6 Fix broadphase for rotation events (#2463) 2022-01-27 17:36:17 +11:00
Pieter-Jan Briers
5be2f610cd Fix thread pool queue histogram having buckets divided by 1000. 2022-01-27 01:55:33 +01:00
metalgearsloth
35324e0853 Version: 0.8.36 2022-01-26 17:56:54 +11:00
metalgearsloth
ac753cdb93 Revert "Reduce component / resolve calls in transformcomp (#2450)" (#2459) 2022-01-26 17:56:30 +11:00
metalgearsloth
3edd39f0eb Version: 0.8.35 2022-01-26 16:10:45 +11:00
metalgearsloth
8f790c28be Deprecate component.Paused (#2449) 2022-01-26 16:10:25 +11:00
metalgearsloth
c253afaf8e Version: 0.8.34 2022-01-26 15:15:19 +11:00
metalgearsloth
a6ac1dced0 Fix more physics ordering bugs (#2458) 2022-01-26 14:59:31 +11:00
wrexbe
d1e0f2cd94 Automatic Component Names (Alternate ending) (#2389) 2022-01-25 14:10:08 +01:00
metalgearsloth
af861d289a Remove some unnecessary resolves (#2452) 2022-01-25 14:01:44 +01:00
metalgearsloth
753f3f8c0f Add dirty method to entmanager for components (#2453) 2022-01-25 14:00:03 +01:00
Leon Friedrich
5c2a5741ee Prevent CreateAudioSource() from erroring/crashing in debug when hitting source limit (#2448) 2022-01-25 13:35:01 +01:00
metalgearsloth
26941a2013 Reduce component / resolve calls in transformcomp (#2450) 2022-01-25 13:32:28 +01:00
Moony
fad4c20da2 VV for entity systems. (#2447) 2022-01-25 13:29:17 +01:00
Pieter-Jan Briers
2b79ef301d Add prometheus-net.DotNetRuntime for more detailed runtime metrics like GC pause times. (#2457) 2022-01-25 13:23:55 +01:00
metalgearsloth
014491e674 Fix joints crash (#2454) 2022-01-25 12:39:31 +11:00
metalgearsloth
2e70cd4f2e Add HasComp to EntityQuery struct (#2451) 2022-01-24 18:48:45 +11:00
metalgearsloth
689e1baa12 Version: 0.8.33 2022-01-24 11:58:16 +11:00
metalgearsloth
c34e84378a Fix grid deletion (#2445) 2022-01-24 11:55:37 +11:00
Kara D
9a44becc73 Version: 0.8.32 2022-01-21 20:08:35 -07:00
mirrorcult
d324d9fcf3 Merge pull request #2429 from metalgearsloth/2022-01-17_grid-iter 2022-01-21 20:04:35 -07:00
Pieter-Jan Briers
74cd48401c Engine changes for launcher ContentDB/delta updates. 2022-01-21 17:24:07 +01:00
metalgearsloth
43081c57e7 Add acruid's funny entity query (#2440) 2022-01-21 10:45:10 +11:00
Leon Friedrich
b80a51d03f Raise an attempt-event when receiving client BUI messages. (#2414) 2022-01-20 02:42:48 +11:00
mirrorcult
e90d5e4977 Merge pull request #2433 from wrexbe/warningfixes 2022-01-18 15:24:14 -07:00
mirrorcult
979034906a Merge pull request #2417 from weaversam8/shutdown-pre-mainloop 2022-01-18 15:23:46 -07:00
Pieter-Jan Briers
9e4fd2905b Release DXGI Factory in VramCommand 2022-01-18 18:16:02 +01:00
Leon Friedrich
914c269411 return -> continue (#2437) 2022-01-18 23:41:55 +11:00
metalgearsloth
2cacc4cd49 Version: 0.8.31 2022-01-18 19:02:43 +11:00
Leon Friedrich
3024094584 Add IsQueuedForDeletion (#2421)
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
2022-01-18 19:02:10 +11:00
Leon Friedrich
4c66451324 Stop updating entity tree on pre-delete un-anchor event (#2422) 2022-01-18 17:49:31 +11:00
Leon Friedrich
7e7d808c90 Sprite offset rendering fix (#2432) 2022-01-18 17:45:49 +11:00
wrexbe
0538e89948 Fixes warnings 2022-01-17 19:13:54 -08:00
Sam Weaver
6376f7c35d Add System.Text.Json.JsonPropertyNameAttribute to sandbox allowlist (#2435) 2022-01-18 03:14:10 +01:00
metalgearsloth
37721f2327 Align rotation 2022-01-17 15:26:39 +11:00
metalgearsloth
b0d2404644 sussy init 2022-01-17 15:09:33 +11:00
metalgearsloth
5f76cb4819 Tests working let's go 2022-01-17 15:05:36 +11:00
metalgearsloth
427a54fc67 Fix tests I guess 2022-01-17 14:53:51 +11:00
metalgearsloth
1cd1fb905d Comment 2022-01-17 14:40:12 +11:00
metalgearsloth
33333f87d2 Nuke broadphase caches
Scales really poorly at high grid counts and better to just lazy load.
2022-01-17 14:26:15 +11:00
metalgearsloth
4e5b8ec1e2 Fix early move / rotate crash 2022-01-17 13:40:54 +11:00
metalgearsloth
007feb76b7 Optimise broadphase movebuffer 2022-01-17 13:27:16 +11:00
metalgearsloth
d34dcb81fb ! 2022-01-17 12:47:16 +11:00
metalgearsloth
8abb366903 aaaaaaaaaaaAAAAAAAAAAAAAAA 2022-01-17 12:43:31 +11:00
metalgearsloth
3e7ba7ca28 Just work please 2022-01-17 11:55:19 +11:00
Pieter-Jan Briers
14d52a9da9 Update ManagedHttpListener. This gives it IPv6 support 2022-01-16 16:32:46 +01:00
Pieter-Jan Briers
847f8d1fee Document most engine CVars.c 2022-01-16 15:08:10 +01:00
Pieter-Jan Briers
0c8d7adf37 Fix wrong comment in cvars 2022-01-16 14:12:23 +01:00
Leon Friedrich
d68d803709 Prevent disembowelling on tile removal. (#2418) 2022-01-16 18:51:04 +11:00
metalgearsloth
13ef514d3e Version: 0.8.30 2022-01-16 18:47:43 +11:00
Vera Aguilera Puerto
e20cd248a0 Makes VirtualController an abstract class inheriting EntitySystem (#2424) 2022-01-16 18:46:48 +11:00
mirrorcult
b8a3bda31d Don't dirty entities when NetSyncEnabled is false (#2426) 2022-01-15 19:31:05 +01:00
ElectroJr
001493d984 Version: 0.8.29 2022-01-15 15:21:54 +13:00
Paul Ritter
013a3e3e8c removes componentdependencies (#2423) 2022-01-15 13:06:29 +11:00
Vera Aguilera Puerto
4c2d984835 Fix singleplayer clients being in "prediction" always, breaking physics. 2022-01-14 19:07:16 +01:00
Paul Ritter
21bb0f15e0 i fudged it 2022-01-12 23:03:54 +01:00
Paul Ritter
8d5162ef8d forgot some 2022-01-12 22:49:10 +01:00
Paul Ritter
257913ac0e add myself to codeowners 2022-01-12 22:43:11 +01:00
metalgearsloth
c90dfccbf4 Version: 0.8.28 2022-01-12 23:15:37 +11:00
metalgearsloth
9c7dc8876f Deduplicate most of loadbp and loadmap (#2409) 2022-01-12 23:14:19 +11:00
metalgearsloth
fc8cbdf01f Entity lookup fixes (#2407) 2022-01-12 14:45:01 +11:00
Sam Weaver
5af4bfa912 Merge branch 'space-wizards:master' into shutdown-pre-mainloop 2022-01-11 22:16:33 -05:00
Sam Weaver
0c5a47ff9d Allow the server to shutdown before the main loop has started 2022-01-11 19:34:41 -05:00
metalgearsloth
b4b4a3864f Version: 0.8.27 2022-01-12 00:43:33 +11:00
metalgearsloth
dca8561881 Remove some unnecessary physics resolves and events (#2404) 2022-01-12 00:35:32 +11:00
metalgearsloth
ee58b5299d Joint serialization (#2410) 2022-01-12 00:31:39 +11:00
Leon Friedrich
7868b12279 Remove unused grid-tile-lookup related code (#2416) 2022-01-11 18:56:09 +11:00
Leon Friedrich
42e91e8c4d Deparent entities on grid tile delete (#2415) 2022-01-11 18:55:23 +11:00
Leon Friedrich
28c9326305 Move popup above modal in RootControl (#2412) 2022-01-10 16:35:04 +01:00
metalgearsloth
40b8772980 Prettify contact deletions (#2413) 2022-01-10 16:34:50 +01:00
Pieter-Jan Briers
b6a548629a More async stuff for StatusHost. 2022-01-10 16:34:16 +01:00
Vera Aguilera Puerto
291a37924d Add a method to unregister "manual" commands from IConsoleHost. (#2403) 2022-01-10 12:51:13 +01:00
Vera Aguilera Puerto
0b5eccd60a Expose ConsoleHost.RegisteredCommand and its callback. (#2394) 2022-01-10 12:50:55 +01:00
Vera Aguilera Puerto
866a324922 ServerConsoleHost logs errors as errors, not warnings. 2022-01-10 12:50:23 +01:00
Pieter-Jan Briers
baf48a8dc1 Update ManagedHttpListener submodule 2022-01-10 11:55:08 +01:00
Pieter-Jan Briers
a85b2dd43c Version: 0.8.26 2022-01-10 01:36:12 +01:00
Pieter-Jan Briers
43059b3985 Remove usages of Newtonsoft.Json from StatusHost (#2405) 2022-01-10 01:36:00 +01:00
Vera Aguilera Puerto
4d6183d6af Add new entries to CODEOWNERS for myself. 2022-01-09 19:26:22 +01:00
metalgearsloth
79f87f03ce Version: 0.8.25 2022-01-09 23:46:35 +11:00
metalgearsloth
01ede29fc4 Nuke gridtilelookup (#2399) 2022-01-09 23:45:48 +11:00
Pieter-Jan Briers
fb54d0df1c Remove usages of Newtonsoft.Json outside StatusHost 2022-01-09 11:53:06 +01:00
E F R
5b65495fbc Controls/SplitContainer: Allow Content to change the SplitState (#2392) 2022-01-09 10:26:24 +01:00
Pieter-Jan Briers
cec3a8c1c2 Remove unnecessary warning mute from Clyde. 2022-01-09 10:21:00 +01:00
Leon Friedrich
8bd0b459b9 Make entity manager proxy methods protected (#2402) 2022-01-07 11:21:28 +01:00
Leon Friedrich
7da50516f9 Fix ghost-pointing visibility (#2401) 2022-01-07 17:08:19 +11:00
Kara D
6cbb2135b8 Version: 0.8.24 2022-01-04 17:51:39 -07:00
mirrorcult
66dbc05022 Merge pull request #2390 from wrexbe/tilesid 2022-01-04 17:48:50 -07:00
Paul
18cc385c70 version bump & changes to itemlist 2022-01-04 21:11:47 +01:00
Matz05
384f672eec Engine changes for more server-pushed lighting variables (#2367)
* Engine changes for more server-pushed lighting variables, but apparently this is a deprecated way of doing things anyway

* Removed two unecessary uses of virtual
2022-01-05 02:57:49 +11:00
Paul
f49a29cfb3 smol itemlist change & version bump 2022-01-03 04:12:04 +01:00
Wrexbe
e8b70877cf Tiles Name->Id DisplayName->Name 2022-01-01 20:52:59 -08:00
Paul Ritter
9b084ea6a9 bandaid fix pvs grid crash for or14 2022-01-01 23:29:14 +01:00
ShadowCommander
51f2fc4259 TeleportTo upgrades (#2384)
* Clean up TeleportTo

* Change TeleportTo to allow teleporting to EntitiyUid

* Rename TeleportToPlayerCommand to TeleportToCommand

* Move duplicate parsing code to TryGetTransformFromUidOrUsername
2022-01-01 17:14:17 +01:00
Pieter-Jan Briers
bb27482e9f Fix release/debug serializer mismatch. 2021-12-31 10:06:32 +01:00
Pieter-Jan Briers
75912896c9 Version: 0.8.21 2021-12-31 09:37:30 +01:00
Pieter-Jan Briers
6e0632ae1b Explicitly block P/Invoke methods in AssemblyTypeChecker 2021-12-31 09:35:34 +01:00
Pieter-Jan Briers
7c90da0402 Correctly load mismatching versions from Robust modules. 2021-12-31 09:35:34 +01:00
Pieter-Jan Briers
313a3eb7f2 Minor GLContextEgl cleanup:
* Compile it in by default but leave display.egl=false by default.
* Minor code cleanup/TerraFX usage.
2021-12-31 09:35:34 +01:00
metalgearsloth
cb054f0761 Avoid touching physicscomp when removed from container (#2379) 2021-12-31 08:36:08 +01:00
Paul Ritter
579b21716d version 0.8.20 2021-12-30 22:55:06 +01:00
Paul Ritter
3ffdc8cc2d changes needed for inventory refactor (#2350)
* get that crap outta here

* reenables tests

* helper

* removes serverside itemcomp & misc fixes

* oopsie

* fixes tests

* motivation low

* container stuff

* resolves optional

* fix some tests

* fixes

Co-authored-by: Paul Ritter <ritter.paul1@gmail.com>
2021-12-30 22:54:00 +01:00
Pieter-Jan Briers
e68af15b40 Don't skip viewer entity in PVS for streaming
This causes problems on the client.
2021-12-30 21:00:52 +01:00
Pieter-Jan Briers
8e5fafaf05 Version: 0.8.19 2021-12-30 18:20:38 +01:00
Pieter-Jan Briers
95f9418e56 Remove some garbage from .gitignore
A different time
2021-12-30 18:12:35 +01:00
Pieter-Jan Briers
23af814ebc Remove Resources/.gitignore
:salute:
2021-12-30 18:10:13 +01:00
Pieter-Jan Briers
ae7dda9dab Update NetSerializer 2021-12-30 18:04:59 +01:00
Pieter-Jan Briers
c5899944a2 Uncomment stuff in manifest so it's not empty and won't break the launcher.
Whoops.
2021-12-30 17:48:22 +01:00
Pieter-Jan Briers
c0e0f65ebe Unhardcode Lidgren App Identifier.
Default value is now RobustToolbox, not SS14_NetTag
2021-12-30 17:32:49 +01:00
Pieter-Jan Briers
3bdce98964 Change X11 instance/class names to RobustToolbox 2021-12-30 17:24:25 +01:00
Pieter-Jan Briers
478ab3bec4 Remove Space Station 14 reference from a MessageBox 2021-12-30 17:23:29 +01:00
Pieter-Jan Briers
ae77ee3df4 Remove SS14 logo/icon/splash/window title branding. Make it all configurable with manifest.yml 2021-12-30 17:22:21 +01:00
Pieter-Jan Briers
86e4a558c5 F3 menu moves out of the way when console opens 2021-12-30 16:49:36 +01:00
metalgearsloth
15c1e8f7bf Run appearancevisualizers on dummy entities again (#2380) 2021-12-30 20:41:55 +11:00
metalgearsloth
f38770dbb5 Poly-edge collision optimisations (#2366) 2021-12-30 20:17:55 +11:00
Pieter-Jan Briers
75d37f8309 Version: 0.8.18 2021-12-30 03:10:50 +01:00
Pieter-Jan Briers
ed641c8cc8 Properly dispose debug console history writer so it flushes properly. 2021-12-30 03:10:01 +01:00
Pieter-Jan Briers
069ebbc8d0 Make disabled prediction work again.
Simulation input and Update() does not happen when prediction is disabled. Both of these can be re-opted in on a per-handler/system basis with a bool flag. Stuff like physics opts out of this now.
2021-12-30 03:03:39 +01:00
Pieter-Jan Briers
720f33a12a Updated webview packaging script 2021-12-29 20:27:50 +01:00
Leon Friedrich
08f1cfbc79 add CanInsertIfEmpty() (#2382)
* add CanInsertIfEmpty

* make CanInsert call CanInsertIfEmpty
2021-12-29 20:27:01 +01:00
Pieter-Jan Briers
9896697919 Viewports have configurable clear color, default to black. 2021-12-29 20:11:08 +01:00
metalgearsloth
057d50b60b BQL optimisations (#2315) 2021-12-29 14:04:19 +11:00
Pieter-Jan Briers
e3dc446e9e Version: 0.8.17 2021-12-28 22:27:33 +01:00
Pieter-Jan Briers
c529f756af Make default visibility mask if no EyeComponent 1 in PVS.
This fixes OpenDream.

@metalgearsloth
2021-12-28 22:27:20 +01:00
metalgearsloth
c07eaecacb Version: 0.8.16 2021-12-29 05:12:05 +11:00
metalgearsloth
ddc03a1d62 Cache vismask on each entity (#2312) 2021-12-29 05:11:53 +11:00
Pieter-Jan Briers
ca59cff07f WiP launcher CEF loading. (#2376) 2021-12-28 17:37:54 +01:00
Pieter-Jan Briers
df4ddfdf25 Unhardcode ACZ stuff to be more flexible (and work on master SS14). 2021-12-28 16:17:21 +01:00
Pieter-Jan Briers
c667a326a3 Fix ACZ creating invalid zip paths on Windows.
Zip files always use / path separators.
2021-12-28 16:17:21 +01:00
Vera Aguilera Puerto
0099442852 Version 0.8.15 2021-12-27 18:48:46 +01:00
Vera Aguilera Puerto
eecb104cc5 Adds help method to C# scripting. (#2368) 2021-12-27 18:47:16 +01:00
Vera Aguilera Puerto
a54283e637 ByRefEvent attribute for events. (#2375) 2021-12-27 17:59:32 +01:00
Vera Aguilera Puerto
ed06107a9f Proxy method AddComp actually returns the added component now. 2021-12-27 16:43:54 +01:00
Vera Aguilera Puerto
2d833daa57 Fix EntitySpawnWindow Erase Mode not being toggled off correctly.
It would always get toggled back on after Clear cleared the erase mode status...
2021-12-27 16:40:52 +01:00
metalgearsloth
67dd0a9433 Make gridfixture_test use fixturescomp (#2370) 2021-12-25 19:05:16 +01:00
Vera Aguilera Puerto
fcc16d67f7 Remove Eye Lerping from engine. (#2371) 2021-12-25 19:05:07 +01:00
metalgearsloth
394f51f70d Version: 0.8.14 2021-12-25 21:42:26 +11:00
metalgearsloth
538627328e Don't wake destroyed contact bodies if they can't collide (#2369)
e.g. if they're getting yeeted to nullspace or inserted into a container.
2021-12-25 11:26:47 +01:00
Vera Aguilera Puerto
b5a21ccc4d Version 0.8.13 2021-12-23 13:06:39 +01:00
metalgearsloth
2d331ff786 Broadphase fix take 2 (#2327)
Co-authored-by: Paul Ritter <ritter.paul1@googlemail.com>
2021-12-23 12:20:59 +01:00
metalgearsloth
9d9ad15274 Entity deletion stuff (#2365) 2021-12-23 12:20:44 +01:00
Pieter-Jan Briers
114ec2e493 This is literally me when you need to google just to delete a submodule 2021-12-23 12:10:51 +01:00
Pieter-Jan Briers
2fb45da0d7 Switch to NuGet packages for Linguini 2021-12-23 10:42:19 +01:00
metalgearsloth
54a693dfa7 Fix attached effects 2021-12-23 15:50:19 +11:00
Pieter-Jan Briers
4be572ba58 whoops 2021-12-23 01:25:42 +01:00
Pieter-Jan Briers
e22d6ea65c Use float.IsFinite in some appropriate places previously using IsNan || IsInfinity 2021-12-23 01:21:57 +01:00
Pieter-Jan Briers
baf86b5b83 Get rid of ComponentTypeCache stuff.
It didn't really work.
2021-12-23 01:15:25 +01:00
Pieter-Jan Briers
e56c77319c Fix tests breaking due to component index stuff. 2021-12-23 01:12:56 +01:00
Pieter-Jan Briers
a170dbd716 Use BitOperations for MathHelper.NextPowerOfTwo instead. 2021-12-23 01:12:02 +01:00
Pieter-Jan Briers
b821833437 Fix compiler warning in GLContextAngle.cs 2021-12-22 20:50:53 +01:00
Pieter-Jan Briers
1bb9b8cae3 Fix launchauth command 2021-12-22 20:46:57 +01:00
metalgearsloth
1e32eb135d Version: 0.8.12 2021-12-22 10:30:23 +11:00
Pieter-Jan Briers
b695ce581e Replace Win32 interop sigs with TerraFX.
We include TerraFX in builds now so this shouldn't be a problem.
2021-12-21 17:29:06 +01:00
Pieter-Jan Briers
8138fc5fa2 Remove component get caching from PVS.
This was literally slower than simply doing it directly.
2021-12-21 17:16:58 +01:00
Pieter-Jan Briers
0b2693cb98 Optimize TryGetComponent & friends with array type -> dict lookups. 2021-12-21 17:16:08 +01:00
Vera Aguilera Puerto
3d959c98ed Version 0.8.11 2021-12-20 17:17:03 +01:00
Vera Aguilera Puerto
0ccee0b496 Fix engine status host not reporting hostname correctly.
The hostname wasn't being cached at server start.
2021-12-20 17:16:13 +01:00
Paul
b7b2a0ab5e quickly put that back 2021-12-20 15:33:50 +01:00
metalgearsloth
375402c455 Optimise DetachParentToNull for grid deletion (#2362) 2021-12-20 13:59:50 +01:00
Paul
03505da382 fixes a bunch of warnings 2021-12-20 13:59:01 +01:00
metalgearsloth
f56219746b Allow tight grid fits (#2309) 2021-12-20 13:58:33 +01:00
metalgearsloth
116c3e491c Use velocities and positions by ref in constraints solver (#2360) 2021-12-20 13:57:32 +01:00
Vera Aguilera Puerto
e94c2f039c Some fixes for map init. (#2355) 2021-12-20 13:57:26 +01:00
Pieter-Jan Briers
2fd52ef3eb Add automatic hub advertisement. 2021-12-20 13:56:17 +01:00
Paul
29659536aa version 0.8.10 2021-12-20 12:39:19 +01:00
Paul Ritter
338a2831ee Revert Rich Text (#2363) 2021-12-20 12:38:35 +01:00
metalgearsloth
c64c1aca5b Fix effect rotation (#2357) 2021-12-19 17:44:26 +11:00
Vera Aguilera Puerto
0dd72f4434 Extra MIDI sanity checks.
Makes sure the tracking entity is valid before setting source velocity based on global linear velocity.
2021-12-18 00:31:23 +01:00
Vera Aguilera Puerto
891d1da208 Version 0.8.9 2021-12-17 23:41:02 +01:00
E F R
f8e903c422 Rich Text Fixes The 3rd (#2351) 2021-12-17 23:39:46 +01:00
Vera Aguilera Puerto
b373824cf5 Various MIDI improvements and fixes.
- Fix bug where MIDI renderers in other maps than the current map in IEyeManager would be silenced forever.
- Tracking an entity now sets the TrackingCoordinates to the entity's coordinates.
- MIDI renderers not in your same IEyeManager.CurrentMap or that have invalid coordinates will have their occlusion set to the max value, essentially becoming silenced. I feel like this is a much better solution than changing the volume, as things should be able to call Source.SetVolume without it being changed by positional audio shenanigans.
2021-12-17 23:38:14 +01:00
Paul
6c3c51e816 fix FloatSerializer.cs 2021-12-16 17:52:14 +01:00
Paul
9abc3fbee2 remove allocations with this one simple trick. doctors hate em! 2021-12-16 14:25:26 +01:00
Vera Aguilera Puerto
9f20c325ab Cache transform comp in CreateEntityUninitialized.
Instead of getting it 5 times in a row.
2021-12-16 12:58:12 +01:00
Vera Aguilera Puerto
e7308efdd7 Botch VV to allow viewing remote entities that don't exist locally. (#2346) 2021-12-16 11:32:54 +01:00
Vera Aguilera Puerto
c2113b5719 Remove AggressiveOptimization flag from EntitySystem proxy methods.
Also fixes xmldoc inheritance for some methods.
2021-12-15 11:45:34 +01:00
Leon Friedrich
c43f7ea861 Add nullable overrides for the the Deleted() & Exists() proxy methods. (#2348) 2021-12-15 11:38:45 +01:00
E F R
5fac3f4adb UserInterface/RichTextEntry: Rich Text Fixes (Round 2) (#2340)
Co-authored-by: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com>
Co-authored-by: Paul Ritter <ritter.paul1@googlemail.com>
2021-12-15 10:25:33 +01:00
metalgearsloth
7a31525c3c EntityQuery funnies (#2347) 2021-12-15 18:02:02 +11:00
Vera Aguilera Puerto
1613f5e982 Expose IContentRoot to content. (#2338) 2021-12-14 13:49:07 +01:00
Leon Friedrich
b6907e999d Make ContainerSystem.ContainsEntity() not log missing components (#2345) 2021-12-14 10:14:09 +01:00
Vera Aguilera Puerto
c73077014b EntityUid now shows a "View" button in VV. (#2342) 2021-12-14 09:57:46 +01:00
metalgearsloth
ce9bf26204 Minor render tree updates optimisation (#2337) 2021-12-14 09:51:27 +01:00
Paul Ritter
85f716ef03 pvs optimizations (#2341) 2021-12-14 09:50:34 +01:00
metalgearsloth
fba696ad6d Optimise client 5% with this one trick (#2334) 2021-12-14 09:50:03 +01:00
metalgearsloth
ed4267df50 Minor xform optimisations (#2335) 2021-12-14 09:49:30 +01:00
Insineer
1afeac4b95 fix(server): specify default culture for float.Parse (#2307)
Co-authored-by: Acruid <shatter66@gmail.com>
2021-12-13 11:27:16 +01:00
ShadowCommander
1c761737b6 Version: 0.8.8 2021-12-12 23:19:42 -08:00
ShadowCommander
a159db74f6 Version: 0.2.26 2021-12-12 23:19:07 -08:00
ShadowCommander
ac781e51ec Clean up unused variables in OutputPanel 2021-12-12 23:17:38 -08:00
E F R
e050af31af Controls/OutputPanel: Conslidate logic in _invalidateEntries, and get rid of some rogue LineHeight calculations (#2332) 2021-12-12 23:10:24 -08:00
Acruid
9ca1b8dae0 Version: 0.8.7 2021-12-12 18:20:47 -08:00
wrexbe
a59ab44199 Add IWritableDirProvider helper (#2321) 2021-12-12 16:19:51 -08:00
ShadowCommander
45d4a67ff4 Fix replicated cvars not copying overrides from cmd line (#2329) 2021-12-12 16:17:19 -08:00
Acruid
97f5131ce0 Fixed bug where _pendingResolves was not getting cleared. (#2328)
Added an option to defer field DI for RegisteredInstances until BuildGraph is called. This lets you register instances that contain dependency fields that are not instantiated yet.
2021-12-12 16:12:52 -08:00
localcc
2d4ddd8bd1 Texture GetPixel implemented (#2320) 2021-12-12 16:09:02 -08:00
wrexbe
c94e49ed08 Cache Component Types (#2325) 2021-12-12 16:06:51 -08:00
metalgearsloth
30a72b1227 Optimise some physics stuff (#2303)
* Optimise some physics stuff

* Fix build
2021-12-12 15:45:29 -08:00
metalgearsloth
b5ac7752d4 Make client console check perms locally (#2188) 2021-12-13 00:43:33 +01:00
E F R
04ed7e14e2 Console/SystemConsoleManager: Short-circuit console input handling when not interactive (#2311)
* Console/SystemConsoleManager: Short-circuit console input handling when not interactive

* Console/SystemConsoleManager: Use a `Task` for reading input

Now with 100% less blocking (on the main thread, at least)

* Console/SystemConsoleManager: move command execution off the worker thread
2021-12-12 15:28:02 -08:00
E F R
d168926f98 Graphics/Clyde: add option to submit GLSL #defines for shaders (#2306) 2021-12-12 15:05:50 -08:00
E F R
2a8887d0b4 Rich text redux (#2213)
* Shared/Utility: Define new FormattedMessage core types

* Shared/Utility: Move MarkupParser to a new namespace, update to new FormattedText

* Shared/Serialization: Temporary fix for FormattedMessageSerializer

* Scripting/ScriptInstanceShared: Move to new FormattedMessage.Builder

* Shared/Utility: Add a FormattedMessage loader to the .Builder

* Server/Scripting: Port SciptHost to FormattedMessage.Builder

* UserInterface/RichTextEntry: NOP out almost everything

not gonna bother fixing it until more groundwork is laid

* Shared/Utility: Expand Utility.Extensions a bit

strictly for pesonal reasons

* Client/UserInterface: Add the base TextLayout engine

* Client/Graphics: Add a Font Library manager

* Graphics/TextLayout: Finish up implementing the TextLayout engine

* Utility/FormattedMessage: Add yet another hack to keep the serializer in service

* Commands/Debug: Use FormattedMessage.Builder

* Console/Completions: Use FormattedMessage.Builder

* Utility/FormattedMessage: Add `AddMessage` methods

* Console/ScriptConsole: Use FormattedMessage.Builder

* Client/Log: Use FormattedMessage.Builder

* CustomControls/DebugConsole: Use FormattedMessage.Builder

* Controls/OutputPanel: Use FormattedMessage.Builder, NOP `Draw` pending rewrite

* Controls/RichTextLabel: Use FormattedMessage.Builder, NOP `Draw` pending rewrite

* UnitTesting: Update FormattedMessage/Markup Tests

They will NOT pass yet, but I don't care; it compiles.

* Utility/FormattedMessage: Fix some off-by-one Builder bugs

* Utility/FormattedMessage: Continue cleanup, test compliance

* Utility/FormattedMessage: Work around https://github.com/dotnet/roslyn/issues/57870

* Utility/FormattedMessage: Move ISectionable from TextLayout, implement it for FormattedMessage

* UserInterface/TextLayout: Add a `postcreate` function to set up new `TIn`s

Apparently Roslyn isn't big-brained enough to understand that a
closure of type `Func<T>` means that `var n = new(); return n;` requires
`new()` to return a `T`.

Ironically, it's significantly less cbt to add this than to convert
that big tuple in `Layout` in to a class or struct of some sort
(to initialize the `List<>`s).

* UserInterface/TextLayout: Throw if `Meta` isn't recognized

TODO warning go brrr

* Graphics/FontLibrary: Add a `DummyVariant`

* UserInterface/UITheme: Move to FontLibraries

* UserInterface/TextLayout: Move to an un-nested `ImmutableArray`

* UserInterface/RichTextEntry: Go ahead. Draw.

* Markup/Basic: Add extension & helpers for FormattedMessage.Builder

* Markup/Basic: Add `EscapeText` back in

A forgotten casualty of the great Markup separation of 2021

* Graphics/FontLibrary: Clean up bit magic, ensure that at least one font is picked

* Graphics/FontLibrary: Add diagnostics to the "no fonts" exception

* UserInterface/TextLayout: Scrap `Word`, return to `Offset`

* UserInterface/TextLayout: A whole bunch of hard-fought bugfixes

* Utility/FormattedMessage: Add a static, empty FormattedMessage

* Utility/FormattedMessage: Fix. Bugs.

* UserInterface/RichTextEntry: Bug fixin'

* UserInterface: CSS teim

* Markup/Basic: Add an optional "default" style to use

* Utility/FormattedMessage: I'm surprised I only made this mistake once.

* Log/DebugConsoleLogHandler: work around lack of a default style
2021-12-12 14:35:26 -08:00
E F R
f7f6b74fd3 Graphics/Clyde: make Clearing RenderTargets optional (#2302) 2021-12-11 16:48:34 -08:00
Leon Friedrich
7609a49c17 Make AudioSystem no longer automatically add players in range. (#2299)
* make adding entities in range optional

* Revert "make adding entities in range optional"

This reverts commit bd707b9f4e.

* remove AudioSystem filter modifications
2021-12-11 16:32:17 -08:00
Vera Aguilera Puerto
213db08566 Version 0.8.6 2021-12-11 21:09:40 +01:00
Vera Aguilera Puerto
ba2fbd99a8 Revert "Fix broadphase RemoveBody issue (#2318)"
Caused severe issues, such as firelocks not having collision and some funny exceptions.
This reverts commit fd1a1d326c.
2021-12-11 20:59:44 +01:00
Vera Aguilera Puerto
8ed681d82e EntityStringRepresentation implements IFormattable 2021-12-11 16:00:26 +01:00
827 changed files with 10203 additions and 8470 deletions

19
.github/CODEOWNERS vendored
View File

@@ -1,7 +1,20 @@
# Last match in file takes precedence.
# Ping for all PRs
* @Acruid @PJB3005 @Silvertorch5
/Robust.*/Audio/Midi/ @Zumorica
/Robust.Client.NameGenerator @PaulRitter
/Robust.Client.Injectors @PaulRitter
/Robust.Generators @PaulRitter
/Robust.Analyzers @PaulRitter
/Robust.*/GameStates @PaulRitter
/Robust.Shared/Analyzers @PaulRitter
/Robust.*/Serialization @PaulRitter
/Robust.*/Prototypes @PaulRitter
/Robust.Shared/GameObjects/ComponentDependencies @PaulRitter
/Robust.*/Containers @PaulRitter
# Be they Fluent translations or Freemarker templates, I know them both!
*.ftl @RemieRichards
# Ping for all PRs
* @Acruid @PJB3005 @Silvertorch5

22
.gitignore vendored
View File

@@ -41,18 +41,6 @@ _ReSharper*/
# Resources
*.resources
/Resources/textures/Animations/*.*
/Resources/ResourcePack.zip
/Resources/textures/*_Animations.png
/Resources/textures/*_Decals.png
/Resources/textures/*_Effects.png
/Resources/textures/*_Items.png
/Resources/textures/*_Objects.png
/Resources/textures/*_Tiles.png
/Resources/textures/*_UserInterface.png
/Resources/textures/*.TAI
/Resources/SpriteRenderer/Ogre.log
/Resources/Spriterenderer/output
/Media
/setenv.bat
@@ -78,16 +66,6 @@ project.lock.json
# Created by NUnit.
TestResult.xml
NetSerializerDebug.dll
# We're not gonna ship Mac extlibs with the repo due to size. (11 MB)
Third-Party/extlibs/Mac/
# Or the automatically-fetched Windows natives, for that matter.
Third-Party/extlibs/Windows/
# Actually I'll make this folder because SS14.Shared.Bsdiff isn't third-party is it?
Dependencies/
# Python stuff
__pycache__
.mypy_cache

3
.gitmodules vendored
View File

@@ -13,9 +13,6 @@
[submodule "ManagedHttpListener"]
path = ManagedHttpListener
url = https://github.com/space-wizards/ManagedHttpListener.git
[submodule "Linguini"]
path = Linguini
url = https://github.com/space-wizards/Linguini
[submodule "cefglue"]
path = cefglue
url = https://github.com/space-wizards/cefglue.git

Submodule Linguini deleted from b3c05c2f31

View File

@@ -1,4 +1,4 @@
<Project>
<!-- This file automatically reset by Tools/version.py -->
<PropertyGroup><Version>0.8.5</Version></PropertyGroup>
<PropertyGroup><Version>0.8.52</Version></PropertyGroup>
</Project>

View File

@@ -1,8 +0,0 @@
# .import files are made by Godot because the assets are exposed if using symlinks.
# IF you need to persist a .import file because of something used Godot-side (GUI-side),
# you can do a negation with !.
*.import
# Negation would be like this:
#!/Textures/UserInterface/1pxwhite.png.import
!/Scenes/SS14Window/closewindow.png.import
/I_MADE_THE_SYMLINK

View File

@@ -0,0 +1 @@
defaultwindow-placeholder-title = Exemplary Window Title Here

View File

@@ -1 +0,0 @@
ss14window-placeholder-title = Exemplary Window Title Here

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 927 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -1,2 +0,0 @@
sample:
filter: true

View File

@@ -1,152 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="113.67364mm"
height="56.37999mm"
viewBox="0 0 113.67364 56.37999"
version="1.1"
id="svg3223"
inkscape:version="0.92.4 5da689c313, 2019-01-14"
sodipodi:docname="logo.svg"
inkscape:export-filename="/home/pj/Projects/space-station-14/RobustToolbox/Resources/Textures/Logo/logo.png"
inkscape:export-xdpi="67.034012"
inkscape:export-ydpi="67.034012">
<defs
id="defs3217" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="159.25688"
inkscape:cy="149.8376"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:pagecheckerboard="true"
inkscape:window-width="1920"
inkscape:window-height="1043"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata3220">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-56.556041,-109.30405)">
<g
transform="translate(-3.7799155,-23.482217)"
id="g2559">
<path
inkscape:connector-curvature="0"
id="path148"
style="fill:#e23229;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34773216"
d="m 143.44393,145.03077 0.1484,-0.70241 5.14257,-0.35974 -6.23062,29.75753 -0.69199,0.0483 6.08255,-29.05476 z m 1.18682,31.16724 7.31835,-35.07438 -10.43302,0.72923 -1.28514,6.12249 4.45021,-0.31125 -6.03235,28.95253 z" />
<path
sodipodi:nodetypes="cccccccccccccccccccccc"
inkscape:connector-curvature="0"
id="path152"
style="fill:#e23229;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34773216"
d="m 169.25392,142.53363 -3.53672,16.8925 4.79124,-0.32874 -0.15681,0.75402 -4.79234,0.32881 -2.53549,12.11072 -0.75405,0.052 2.53724,-12.11108 -11.37332,0.78724 z m -18.98495,21.327 11.37324,-0.78724 -2.5247,12.11146 5.98312,-0.41839 2.52513,-12.10406 4.82658,-0.33116 1.26721,-6.07903 -4.82564,0.33109 3.52398,-16.89101 -4.56014,0.33565 -16.70168,19.60839 z" />
<path
inkscape:connector-curvature="0"
id="path156"
style="fill:#fefefe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34773216"
d="m 88.591903,151.83158 -2.595368,0.18103 0.741705,-3.62685 2.595079,-0.182 z m -4.581719,-6.72375 -3.99857,19.05572 3.468889,-0.24195 1.774487,-8.38766 6.064403,-0.42299 2.224789,-10.66981 z" />
<path
inkscape:connector-curvature="0"
id="path160"
style="fill:#fefefe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34773216"
d="m 100.85029,147.82177 2.83371,-0.19837 -0.74166,3.60045 -2.83371,0.19836 z m -6.726869,15.77696 3.469312,-0.24198 1.774487,-8.38695 2.8337,-0.19837 -1.77453,8.38695 3.46938,-0.24296 3.99895,-19.05608 -9.771974,0.68329 z" />
<path
inkscape:connector-curvature="0"
id="path164"
style="fill:#fefefe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34773216"
d="m 108.80467,162.68768 9.74554,-0.68118 1.377,-6.50502 -3.4693,0.24296 -0.63527,2.9832 -2.80718,0.19654 2.51548,-12.01379 2.80731,-0.19754 -0.50239,2.4195 3.46902,-0.24294 1.24513,-5.93998 -9.74589,0.68119 z" />
<path
inkscape:connector-curvature="0"
id="path168"
style="fill:#fefefe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34773216"
d="m 135.66767,145.61788 0.7409,-3.5211 -8.95132,0.6259 -3.99824,19.0564 8.95097,-0.62626 0.74082,-3.52077 -5.4816,0.383 1.03272,-4.89224 3.78675,-0.26474 0.74189,-3.52113 -3.78675,0.26474 0.74081,-3.6011 z" />
<path
inkscape:connector-curvature="0"
id="path172"
style="fill:#d5d5d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34773216"
d="m 71.070134,172.95255 -4.734664,0.33077 0.57447,-2.73456 2.139294,-0.14973 -0.376241,1.80924 2.595442,-0.18103 0.930868,-4.44332 -7.330114,0.5118 -1.66358,8.00131 4.734672,-0.33077 -0.773014,3.62025 -2.119829,0.1484 0.475696,-2.23174 -2.614982,0.18237 -1.030327,4.86616 7.330104,-0.5118 z" />
<path
inkscape:connector-curvature="0"
id="path176"
style="fill:#d5d5d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34773216"
d="m 74.794828,169.99754 2.496095,-0.17422 -2.436556,11.62085 2.595151,-0.182 2.436903,-11.62086 2.496023,-0.17421 0.554678,-2.63441 -7.587516,0.53064 z" />
<path
inkscape:connector-curvature="0"
id="path180"
style="fill:#d5d5d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34773216"
d="m 87.573322,171.75893 0.554606,-2.69318 2.119754,-0.1484 -0.554978,2.69354 z m 2.832629,8.59803 2.991888,-14.25529 -7.310379,0.51154 -2.99153,14.25493 2.595227,-0.18201 1.327293,-6.27378 2.11968,-0.14839 -1.327288,6.27414 z" />
<path
inkscape:connector-curvature="0"
id="path184"
style="fill:#d5d5d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34773216"
d="m 98.977684,179.78056 2.436926,-11.62086 2.49608,-0.1752 0.55493,-2.63374 -7.587518,0.53065 -0.554634,2.63373 2.495947,-0.17421 -2.436599,11.6212 z" />
<path
inkscape:connector-curvature="0"
id="path188"
style="fill:#d5d5d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34773216"
d="m 104.62426,179.38562 2.5951,-0.18101 2.9915,-14.25528 -2.59522,0.182 z" />
<path
inkscape:connector-curvature="0"
id="path192"
style="fill:#d5d5d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34773216"
d="m 115.73198,167.18138 2.11975,-0.14839 -1.88236,8.98749 -2.11949,0.14838 z m -5.03203,11.80203 7.31001,-0.51042 2.99153,-14.25494 -7.31028,0.51044 z" />
<path
inkscape:connector-curvature="0"
id="path196"
style="fill:#d5d5d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34773216"
d="m 124.08538,178.07141 1.36653,-6.47511 1.18856,6.29603 2.25853,-0.15792 2.99192,-14.25493 -2.59522,0.18201 -1.36734,6.57353 -1.18854,-6.39514 -2.25854,0.15791 -2.99084,14.25493 z" />
<path
inkscape:connector-curvature="0"
id="path200"
style="fill:#fefefe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34773216"
d="m 66.677649,158.65784 -1.377018,6.50538 9.798398,-0.68471 2.489415,-11.87958 -6.329111,0.44214 0.767747,-3.65465 2.860076,-0.20018 -0.503204,2.41917 3.469299,-0.24297 1.244526,-5.93996 -4.328229,0.30289 -8.728772,0.56991 2.909827,1.489 -1.87565,9.01912 6.329037,-0.44213 -1.032406,4.83973 -2.833645,0.19738 0.635302,-2.98354 z" />
<path
inkscape:connector-curvature="0"
id="path204"
style="fill:#e23229;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34773216"
d="m 70.519326,139.92277 -0.277457,1.36553 103.473271,-7.11317 0.29445,-1.38886 z" />
<path
inkscape:connector-curvature="0"
id="path208"
style="fill:#e23229;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.34773216"
d="m 60.335956,189.16626 103.473274,-7.11356 0.29444,-1.38885 -103.489968,7.13649 z" />
<path
sodipodi:nodetypes="cccccccc"
inkscape:connector-curvature="0"
id="path1772"
d="m 167.92741,145.26275 -12.87687,14.89523 9.91366,-0.68019 z m -3.743,7.27758 -1.02896,4.93612 -3.51544,0.2412 z"
style="fill:#e23229;fill-opacity:1;stroke:none;stroke-width:0.2626844px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.4 KiB

View File

@@ -1,10 +1,14 @@
using Microsoft.CodeAnalysis;
namespace Robust.Generators
namespace Robust.Analyzers;
public static class Diagnostics
{
public static class Diagnostics
{
public static SuppressionDescriptor MeansImplicitAssignment =>
new SuppressionDescriptor("RADC1000", "CS0649", "Marked as implicitly assigned.");
}
public const string IdExplicitInterface = "RA0000";
public const string IdSerializable = "RA0001";
public const string IdFriend = "RA0002";
public const string IdExplicitVirtual = "RA0003";
public static SuppressionDescriptor MeansImplicitAssignment =>
new SuppressionDescriptor("RADC1000", "CS0649", "Marked as implicitly assigned.");
}

View File

@@ -24,14 +24,14 @@ namespace Robust.Analyzers
SyntaxKind.OverrideKeyword
};
public const string DiagnosticId = "RA0000";
private const string Title = "No explicit interface specified";
private const string MessageFormat = "No explicit interface specified";
private const string Description = "Make sure to specify the interface in your method-declaration.";
private const string Category = "Usage";
[SuppressMessage("ReSharper", "RS2008")] private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: Description);
[SuppressMessage("ReSharper", "RS2008")] private static readonly DiagnosticDescriptor Rule = new(
Diagnostics.IdExplicitInterface,
"No explicit interface specified",
"No explicit interface specified",
"Usage",
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
description: "Make sure to specify the interface in your method-declaration.");
private const string RequiresExplicitImplementationAttributeMetadataName =
"Robust.Shared.Analyzers.RequiresExplicitImplementationAttribute";

View File

@@ -0,0 +1,176 @@
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Robust.Analyzers;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class ExplicitVirtualAnalyzer : DiagnosticAnalyzer
{
internal const string Attribute = "Robust.Shared.Analyzers.VirtualAttribute";
[SuppressMessage("ReSharper", "RS2008")]
private static readonly DiagnosticDescriptor Rule = new(
Diagnostics.IdExplicitVirtual,
"Class must be explicitly marked as [Virtual], abstract, static or sealed",
"Class must be explicitly marked as [Virtual], abstract, static or sealed",
"Usage",
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
description: "Class must be explicitly marked as [Virtual], abstract, static or sealed.");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ClassDeclaration);
}
private static bool HasAttribute(INamedTypeSymbol namedTypeSymbol, INamedTypeSymbol attrSymbol)
{
return namedTypeSymbol.GetAttributes()
.Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, attrSymbol));
}
private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var attrSymbol = context.Compilation.GetTypeByMetadataName(Attribute);
var classDecl = (ClassDeclarationSyntax)context.Node;
var classSymbol = context.SemanticModel.GetDeclaredSymbol(classDecl);
if (classSymbol == null)
return;
if (classSymbol.IsSealed || classSymbol.IsAbstract || classSymbol.IsStatic)
return;
if (HasAttribute(classSymbol, attrSymbol))
return;
var diag = Diagnostic.Create(Rule, classDecl.Keyword.GetLocation());
context.ReportDiagnostic(diag);
}
}
// Doesn't work as I'd hoped: Roslyn doesn't provide an API for global usings and I can't get batch changes to work.
/*
[ExportCodeFixProvider(LanguageNames.CSharp)]
public sealed class ExplicitVirtualCodeFixProvider : CodeFixProvider
{
private const string TitleSealed = "Annotate class as sealed.";
private const string TitleVirtual = "Annotate class as [Virtual].";
private const string TitleAbstract = "Annotate class as abstract.";
private const string TitleStatic = "Annotate class as static.";
public override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
foreach (var diagnostic in context.Diagnostics)
{
var span = diagnostic.Location.SourceSpan;
var classDecl = root.FindToken(span.Start).Parent.AncestorsAndSelf().OfType<ClassDeclarationSyntax>()
.First();
context.RegisterCodeFix(
CodeAction.Create(
TitleVirtual,
c => FixVirtualAsync(context.Document, classDecl, c),
TitleVirtual),
diagnostic);
context.RegisterCodeFix(
CodeAction.Create(
TitleStatic,
c => FixStaticAsync(context.Document, classDecl, c),
TitleStatic),
diagnostic);
context.RegisterCodeFix(
CodeAction.Create(
TitleSealed,
c => FixSealedAsync(context.Document, classDecl, c),
TitleSealed),
diagnostic);
context.RegisterCodeFix(
CodeAction.Create(
TitleAbstract,
c => FixAbstractAsync(context.Document, classDecl, c),
TitleAbstract),
diagnostic);
}
}
private async Task<Document> FixVirtualAsync(
Document document,
ClassDeclarationSyntax classDecl,
CancellationToken cancellationToken)
{
var ns = "Robust.Shared.Analyzers";
var attrib = SyntaxFactory.Attribute(SyntaxFactory.ParseName("Virtual"));
var newClassDecl = classDecl.AddAttributeLists(
SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(new[] { attrib })));
var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(cancellationToken);
root = root.ReplaceNode(classDecl, newClassDecl);
var options = await document.GetOptionsAsync(cancellationToken);
if (root.Usings.All(u => u.Name.ToString() != ns))
{
root = root.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(ns)));
}
return document.WithSyntaxRoot(root);
}
private async Task<Document> FixStaticAsync(
Document document,
ClassDeclarationSyntax classDecl,
CancellationToken cancellationToken)
{
var newClassDecl = classDecl.AddModifiers(SyntaxFactory.Token(SyntaxKind.StaticKeyword));
var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(cancellationToken);
root = root.ReplaceNode(classDecl, newClassDecl);
return document.WithSyntaxRoot(root);
}
private async Task<Document> FixAbstractAsync(
Document document,
ClassDeclarationSyntax classDecl,
CancellationToken cancellationToken)
{
var newClassDecl = classDecl.AddModifiers(SyntaxFactory.Token(SyntaxKind.AbstractKeyword));
var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(cancellationToken);
root = root.ReplaceNode(classDecl, newClassDecl);
return document.WithSyntaxRoot(root);
}
private async Task<Document> FixSealedAsync(
Document document,
ClassDeclarationSyntax classDecl,
CancellationToken cancellationToken)
{
var newClassDecl = classDecl.AddModifiers(SyntaxFactory.Token(SyntaxKind.SealedKeyword));
var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(cancellationToken);
root = root.ReplaceNode(classDecl, newClassDecl);
return document.WithSyntaxRoot(root);
}
public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(Diagnostics.IdExplicitVirtual);
}
*/

View File

@@ -14,15 +14,15 @@ namespace Robust.Analyzers
{
const string FriendAttribute = "Robust.Shared.Analyzers.FriendAttribute";
public const string DiagnosticId = "RA0002";
private const string Title = "Tried to access friend-only member";
private const string MessageFormat = "Tried to access member \"{0}\" in class \"{1}\" which can only be accessed by friend classes";
private const string Description = "Make sure to specify the accessing class in the friends attribute.";
private const string Category = "Usage";
[SuppressMessage("ReSharper", "RS2008")]
private static readonly DiagnosticDescriptor Rule = new (DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Error, true, Description);
private static readonly DiagnosticDescriptor Rule = new (
Diagnostics.IdFriend,
"Tried to access friend-only member",
"Tried to access member \"{0}\" in class \"{1}\" which can only be accessed by friend classes",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to specify the accessing class in the friends attribute.");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);

View File

@@ -1,9 +1,7 @@
using System;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Robust.Generators;
namespace Robust.Analyzers
{

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>9</LangVersion>
<LangVersion>10</LangVersion>
</PropertyGroup>
<ItemGroup>

View File

@@ -17,19 +17,21 @@ namespace Robust.Analyzers
public class SerializableAnalyzer : DiagnosticAnalyzer
{
// Metadata of the analyzer
public const string DiagnosticId = "RA0001";
// You could use LocalizedString but it's a little more complicated for this sample
private const string Title = "Class not marked as (Net)Serializable";
private const string MessageFormat = "Class not marked as (Net)Serializable";
private const string Description = "The class should be marked as (Net)Serializable.";
private const string Category = "Usage";
private const string RequiresSerializableAttributeMetadataName = "Robust.Shared.Analyzers.RequiresSerializableAttribute";
private const string SerializableAttributeMetadataName = "System.SerializableAttribute";
private const string NetSerializableAttributeMetadataName = "Robust.Shared.Serialization.NetSerializableAttribute";
[SuppressMessage("ReSharper", "RS2008")] private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: Description);
[SuppressMessage("ReSharper", "RS2008")] private static readonly DiagnosticDescriptor Rule = new(
Diagnostics.IdSerializable,
"Class not marked as (Net)Serializable",
"Class not marked as (Net)Serializable",
"Usage",
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
description: "The class should be marked as (Net)Serializable.");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
@@ -139,7 +141,8 @@ namespace Robust.Analyzers
return document.WithSyntaxRoot(root);
}
public sealed override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(SerializableAnalyzer.DiagnosticId);
public sealed override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(Diagnostics.IdSerializable);
public override FixAllProvider GetFixAllProvider()
{

View File

@@ -1,7 +1,9 @@
using BenchmarkDotNet.Attributes;
using Robust.Shared.Analyzers;
namespace Robust.Benchmarks.NumericsHelpers
{
[Virtual]
public class AddBenchmark
{
[Params(32, 128)]

View File

@@ -4,7 +4,7 @@ using System;
namespace Robust.Benchmarks
{
internal class Program
internal static class Program
{
// --allCategories=ctg1,ctg2
// --anyCategories=ctg1,ctg2

View File

@@ -9,7 +9,7 @@ using Robust.Shared.Serialization.TypeSerializers.Interfaces;
namespace Robust.Benchmarks.Serialization
{
public class BenchmarkIntSerializer : ITypeSerializer<int, ValueDataNode>
public sealed class BenchmarkIntSerializer : ITypeSerializer<int, ValueDataNode>
{
public ValidationNode Validate(ISerializationManager serializationManager, ValueDataNode node,
IDependencyCollection dependencies, ISerializationContext? context = null)

View File

@@ -2,6 +2,7 @@
using System.Linq;
using BenchmarkDotNet.Attributes;
using Robust.Benchmarks.Serialization.Definitions;
using Robust.Shared.Analyzers;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.Markdown;
using Robust.Shared.Serialization.Markdown.Mapping;
@@ -13,6 +14,7 @@ using YamlDotNet.RepresentationModel;
namespace Robust.Benchmarks.Serialization.Copy
{
[MemoryDiagnoser]
[Virtual]
public class SerializationCopyBenchmark : SerializationBenchmark
{
public SerializationCopyBenchmark()

View File

@@ -3,7 +3,7 @@ using Robust.Shared.Serialization;
namespace Robust.Benchmarks.Serialization.Definitions
{
public class BenchmarkFlags
public sealed class BenchmarkFlags
{
public const int Zero = 1 << 0;
public const int ThirtyOne = 1 << 31;

View File

@@ -1,8 +1,10 @@
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Analyzers;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Robust.Benchmarks.Serialization.Definitions
{
[DataDefinition]
[Virtual]
public class DataDefinitionWithString
{
[DataField("string")]

View File

@@ -11,7 +11,7 @@ namespace Robust.Benchmarks.Serialization.Definitions
/// Taken from content.
/// </summary>
[Prototype("seed")]
public class SeedDataDefinition : IPrototype
public sealed class SeedDataDefinition : IPrototype
{
public const string Prototype = @"
- type: seed

View File

@@ -1,9 +1,11 @@
using BenchmarkDotNet.Attributes;
using Robust.Shared.Analyzers;
using Robust.Shared.Serialization.Manager;
namespace Robust.Benchmarks.Serialization.Initialize
{
[MemoryDiagnoser]
[Virtual]
public class SerializationInitializeBenchmark : SerializationBenchmark
{
[IterationCleanup]

View File

@@ -1,6 +1,7 @@
using System.IO;
using BenchmarkDotNet.Attributes;
using Robust.Benchmarks.Serialization.Definitions;
using Robust.Shared.Analyzers;
using Robust.Shared.Serialization.Manager.Result;
using Robust.Shared.Serialization.Markdown;
using Robust.Shared.Serialization.Markdown.Mapping;
@@ -12,6 +13,7 @@ using YamlDotNet.RepresentationModel;
namespace Robust.Benchmarks.Serialization.Read
{
[MemoryDiagnoser]
[Virtual]
public class SerializationReadBenchmark : SerializationBenchmark
{
public SerializationReadBenchmark()

View File

@@ -1,5 +1,6 @@
using BenchmarkDotNet.Attributes;
using Robust.Benchmarks.Serialization.Definitions;
using Robust.Shared.Analyzers;
using Robust.Shared.Serialization.Markdown.Mapping;
using Robust.Shared.Serialization.Markdown.Sequence;
using Robust.Shared.Serialization.Markdown.Value;
@@ -7,6 +8,7 @@ using Robust.Shared.Serialization.Markdown.Value;
namespace Robust.Benchmarks.Serialization
{
[MemoryDiagnoser]
[Virtual]
public class SerializationArrayBenchmark : SerializationBenchmark
{
public SerializationArrayBenchmark()

View File

@@ -2,6 +2,7 @@
using System.IO;
using BenchmarkDotNet.Attributes;
using Robust.Benchmarks.Serialization.Definitions;
using Robust.Shared.Analyzers;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.Markdown;
using Robust.Shared.Serialization.Markdown.Mapping;
@@ -13,6 +14,7 @@ using YamlDotNet.RepresentationModel;
namespace Robust.Benchmarks.Serialization.Write
{
[MemoryDiagnoser]
[Virtual]
public class SerializationWriteBenchmark : SerializationBenchmark
{
public SerializationWriteBenchmark()

View File

@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Reflection;
using Robust.Shared.ContentPack;
using Robust.Shared.IoC;
using Robust.Shared.Log;
@@ -10,6 +11,8 @@ namespace Robust.Client.WebView.Cef
{
internal partial class WebViewManagerCef : IWebViewManagerImpl
{
private static readonly string BasePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location!)!;
private CefApp _app = default!;
[Dependency] private readonly IDependencyCollection _dependencyCollection = default!;
@@ -27,7 +30,7 @@ namespace Robust.Client.WebView.Cef
else
throw new NotSupportedException("Unsupported platform for CEF!");
var subProcessPath = PathHelpers.ExecutableRelativeFile(subProcessName);
var subProcessPath = Path.Combine(BasePath, subProcessName);
var cefResourcesPath = LocateCefResources();
// System.Console.WriteLine(AppContext.GetData("NATIVE_DLL_SEARCH_DIRECTORIES"));
@@ -60,7 +63,7 @@ namespace Robust.Client.WebView.Cef
private static string? LocateCefResources()
{
if (ProbeDir(PathHelpers.GetExecutableDirectory(), out var path))
if (ProbeDir(BasePath, out var path))
return path;

View File

@@ -14,7 +14,6 @@
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2020.3.0" />
<PackageReference Include="System.Drawing.Common" Version="5.0.2" />
<PackageReference Include="Robust.Natives.Cef" Version="95.7.14" />
</ItemGroup>

View File

@@ -3,7 +3,7 @@ using Robust.Shared.Animations;
namespace Robust.Client.Animations
{
public class AnimationTrackControlProperty : AnimationTrackProperty
public sealed class AnimationTrackControlProperty : AnimationTrackProperty
{
public string? Property { get; set; }

View File

@@ -58,7 +58,7 @@ namespace Robust.Client.Audio.Midi
void Shutdown();
}
internal class MidiManager : IMidiManager
internal sealed class MidiManager : IMidiManager
{
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IResourceManagerInternal _resourceManager = default!;
@@ -293,60 +293,50 @@ namespace Robust.Client.Audio.Midi
}
MapCoordinates? mapPos = null;
var trackingEntity = renderer.TrackingEntity != null && !_entityManager.Deleted(renderer.TrackingEntity);
if (trackingEntity)
{
renderer.TrackingCoordinates = _entityManager.GetComponent<TransformComponent>(renderer.TrackingEntity!.Value).Coordinates;
}
if (renderer.TrackingCoordinates != null)
{
mapPos = renderer.TrackingCoordinates.Value.ToMap(_entityManager);
}
else if (renderer.TrackingEntity != null)
{
mapPos = _entityManager.GetComponent<TransformComponent>(renderer.TrackingEntity.Value).MapPosition;
}
if (mapPos != null)
if (mapPos != null && mapPos.Value.MapId == _eyeManager.CurrentMap)
{
var pos = mapPos.Value;
if (pos.MapId != _eyeManager.CurrentMap)
{
renderer.Source.SetVolume(-10000000);
}
else
{
var sourceRelative = _eyeManager.CurrentEye.Position.Position - pos.Position;
var occlusion = 0f;
if (sourceRelative.Length > 0)
{
occlusion = _broadPhaseSystem.IntersectRayPenetration(
pos.MapId,
new CollisionRay(
pos.Position,
sourceRelative.Normalized,
OcclusionCollisionMask),
sourceRelative.Length,
renderer.TrackingEntity);
}
renderer.Source.SetOcclusion(occlusion);
var sourceRelative = _eyeManager.CurrentEye.Position.Position - pos.Position;
var occlusion = 0f;
if (sourceRelative.Length > 0)
{
occlusion = _broadPhaseSystem.IntersectRayPenetration(
pos.MapId,
new CollisionRay(
pos.Position,
sourceRelative.Normalized,
OcclusionCollisionMask),
sourceRelative.Length,
renderer.TrackingEntity);
}
if (renderer.Source.SetPosition(pos.Position))
renderer.Source.SetOcclusion(occlusion);
if (!renderer.Source.SetPosition(pos.Position))
{
continue;
return;
}
if (renderer.TrackingEntity != null)
if (trackingEntity)
{
renderer.Source.SetVelocity(renderer.TrackingEntity.Value.GlobalLinearVelocity());
renderer.Source.SetVelocity(renderer.TrackingEntity!.Value.GlobalLinearVelocity());
}
if (float.IsNaN(pos.Position.X) || float.IsNaN(pos.Position.Y))
{
// just duck out instead of move to NaN
renderer.Source.SetOcclusion(float.MaxValue);
continue;
}
_midiSawmill?.Warning("Interrupting positional audio, can't set position.");
renderer.Source.StopPlaying();
}
else
{
renderer.Source.SetOcclusion(float.MaxValue);
}
}
@@ -402,7 +392,7 @@ namespace Robust.Client.Audio.Midi
/// <summary>
/// This class is used to load soundfonts.
/// </summary>
private class ResourceLoaderCallbacks : SoundFontLoaderCallbacks
private sealed class ResourceLoaderCallbacks : SoundFontLoaderCallbacks
{
private readonly Dictionary<int, Stream> _openStreams = new();
private int _nextStreamId = 1;

View File

@@ -180,7 +180,7 @@ namespace Robust.Client.Audio.Midi
internal void InternalDispose();
}
internal class MidiRenderer : IMidiRenderer
internal sealed class MidiRenderer : IMidiRenderer
{
[Dependency] private readonly IClydeAudio _clydeAudio = default!;
[Dependency] private readonly ITaskManager _taskManager = default!;

View File

@@ -20,7 +20,7 @@ using Robust.Shared.Utility;
namespace Robust.Client
{
/// <inheritdoc />
public class BaseClient : IBaseClient
public sealed class BaseClient : IBaseClient
{
[Dependency] private readonly IClientNetManager _net = default!;
[Dependency] private readonly IPlayerManager _playMan = default!;
@@ -291,7 +291,7 @@ namespace Robust.Client
/// <summary>
/// Event arguments for when something changed with the player.
/// </summary>
public class PlayerEventArgs : EventArgs
public sealed class PlayerEventArgs : EventArgs
{
/// <summary>
/// The session that triggered the event.
@@ -310,7 +310,7 @@ namespace Robust.Client
/// <summary>
/// Event arguments for when the RunLevel has changed in the BaseClient.
/// </summary>
public class RunLevelChangedEventArgs : EventArgs
public sealed class RunLevelChangedEventArgs : EventArgs
{
/// <summary>
/// RunLevel that the BaseClient switched from.
@@ -335,7 +335,7 @@ namespace Robust.Client
/// <summary>
/// Info about the server and player that is sent to the client while connecting.
/// </summary>
public class ServerInfo
public sealed class ServerInfo
{
public ServerInfo(string serverName)
{

View File

@@ -43,9 +43,9 @@ namespace Robust.Client
IoCManager.Register<IGameTiming, ClientGameTiming>();
IoCManager.Register<IClientGameTiming, ClientGameTiming>();
IoCManager.Register<IPrototypeManager, ClientPrototypeManager>();
IoCManager.Register<IMapManager, ClientMapManager>();
IoCManager.Register<IMapManagerInternal, ClientMapManager>();
IoCManager.Register<IClientMapManager, ClientMapManager>();
IoCManager.Register<IMapManager, NetworkedMapManager>();
IoCManager.Register<IMapManagerInternal, NetworkedMapManager>();
IoCManager.Register<INetworkedMapManager, NetworkedMapManager>();
IoCManager.Register<IEntityManager, ClientEntityManager>();
IoCManager.Register<IEntityLookup, EntityLookup>();
IoCManager.Register<IReflectionManager, ClientReflectionManager>();

View File

@@ -2,7 +2,7 @@
namespace Robust.Client.Console
{
public class ClientConGroupController : IClientConGroupController
public sealed class ClientConGroupController : IClientConGroupController
{
private IClientConGroupImplementation? _implementation;
public event Action? ConGroupUpdated;
@@ -23,7 +23,7 @@ namespace Robust.Client.Console
public bool CanCommand(string cmdName)
{
return _implementation?.CanCommand(cmdName) ?? false;
return _implementation?.CanCommand(cmdName) ?? true;
}
public bool CanViewVar()

View File

@@ -1,7 +1,10 @@
using System;
using System.Collections.Generic;
using Robust.Client.Log;
using Robust.Client.Player;
using Robust.Shared.Console;
using Robust.Shared.Enums;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Network;
using Robust.Shared.Network.Messages;
@@ -11,7 +14,7 @@ using Robust.Shared.Utility;
namespace Robust.Client.Console
{
public class AddStringArgs : EventArgs
public sealed class AddStringArgs : EventArgs
{
public string Text { get; }
@@ -27,7 +30,7 @@ namespace Robust.Client.Console
}
}
public class AddFormattedMessageArgs : EventArgs
public sealed class AddFormattedMessageArgs : EventArgs
{
public readonly FormattedMessage Message;
@@ -38,8 +41,10 @@ namespace Robust.Client.Console
}
/// <inheritdoc cref="IClientConsoleHost" />
internal class ClientConsoleHost : ConsoleHost, IClientConsoleHost
internal sealed class ClientConsoleHost : ConsoleHost, IClientConsoleHost
{
[Dependency] private readonly IClientConGroupController _conGroup = default!;
private bool _requestedCommands;
/// <inheritdoc />
@@ -103,6 +108,14 @@ namespace Robust.Client.Console
if (AvailableCommands.ContainsKey(commandName))
{
var playerManager = IoCManager.Resolve<IPlayerManager>();
if (!_conGroup.CanCommand(commandName) && playerManager.LocalPlayer?.Session.Status > SessionStatus.Connecting)
{
WriteError(null, $"Insufficient perms for command: {commandName}");
return;
}
var command1 = AvailableCommands[commandName];
args.RemoveAt(0);
var shell = new ConsoleShell(this, null);
@@ -196,7 +209,7 @@ namespace Robust.Client.Console
/// These dummies are made purely so list and help can list server-side commands.
/// </summary>
[Reflect(false)]
internal class ServerDummyCommand : IConsoleCommand
internal sealed class ServerDummyCommand : IConsoleCommand
{
internal ServerDummyCommand(string command, string help, string description)
{

View File

@@ -59,7 +59,7 @@ namespace Robust.Client.Console.Commands
}
[UsedImplicitly]
public class SaveConfig : IConsoleCommand
public sealed class SaveConfig : IConsoleCommand
{
public string Command => "saveconfig";
public string Description => "Saves the client configuration to the config file";

View File

@@ -6,7 +6,7 @@ using Robust.Shared.Console;
namespace Robust.Client.Console.Commands
{
class ClearCommand : IConsoleCommand
sealed class ClearCommand : IConsoleCommand
{
public string Command => "cls";
public string Help => "Clears the debug console of all messages.";
@@ -18,7 +18,7 @@ namespace Robust.Client.Console.Commands
}
}
class FillCommand : IConsoleCommand
sealed class FillCommand : IConsoleCommand
{
public string Command => "fill";
public string Help => "Fills the console with some nonsense for debugging.";

View File

@@ -30,7 +30,7 @@ using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Robust.Client.Console.Commands
{
internal class DumpEntitiesCommand : IConsoleCommand
internal sealed class DumpEntitiesCommand : IConsoleCommand
{
public string Command => "dumpentities";
public string Help => "Dump entity list";
@@ -47,7 +47,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class GetComponentRegistrationCommand : IConsoleCommand
internal sealed class GetComponentRegistrationCommand : IConsoleCommand
{
public string Command => "getcomponentregistration";
public string Help => "Usage: getcomponentregistration <componentName>";
@@ -93,7 +93,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class ToggleMonitorCommand : IConsoleCommand
internal sealed class ToggleMonitorCommand : IConsoleCommand
{
public string Command => "monitor";
@@ -148,7 +148,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class ExceptionCommand : IConsoleCommand
internal sealed class ExceptionCommand : IConsoleCommand
{
public string Command => "fuck";
public string Help => "Throws an exception";
@@ -160,7 +160,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class ShowPositionsCommand : IConsoleCommand
internal sealed class ShowPositionsCommand : IConsoleCommand
{
public string Command => "showpos";
public string Help => "";
@@ -173,7 +173,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class ShowRayCommand : IConsoleCommand
internal sealed class ShowRayCommand : IConsoleCommand
{
public string Command => "showrays";
public string Help => "Usage: showrays <raylifetime>";
@@ -200,7 +200,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class DisconnectCommand : IConsoleCommand
internal sealed class DisconnectCommand : IConsoleCommand
{
public string Command => "disconnect";
public string Help => "";
@@ -212,7 +212,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class EntityInfoCommand : IConsoleCommand
internal sealed class EntityInfoCommand : IConsoleCommand
{
public string Command => "entfo";
@@ -264,7 +264,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class SnapGridGetCell : IConsoleCommand
internal sealed class SnapGridGetCell : IConsoleCommand
{
public string Command => "sggcell";
public string Help => "sggcell <gridID> <vector2i>\nThat vector2i param is in the form x<int>,y<int>.";
@@ -313,7 +313,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class SetPlayerName : IConsoleCommand
internal sealed class SetPlayerName : IConsoleCommand
{
public string Command => "overrideplayername";
public string Description => "Changes the name used when attempting to connect to the server.";
@@ -333,7 +333,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class LoadResource : IConsoleCommand
internal sealed class LoadResource : IConsoleCommand
{
public string Command => "ldrsc";
public string Description => "Pre-caches a resource.";
@@ -370,7 +370,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class ReloadResource : IConsoleCommand
internal sealed class ReloadResource : IConsoleCommand
{
public string Command => "rldrsc";
public string Description => "Reloads a resource.";
@@ -404,7 +404,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class GridTileCount : IConsoleCommand
internal sealed class GridTileCount : IConsoleCommand
{
public string Command => "gridtc";
public string Description => "Gets the tile count of a grid";
@@ -438,7 +438,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class GuiDumpCommand : IConsoleCommand
internal sealed class GuiDumpCommand : IConsoleCommand
{
public string Command => "guidump";
public string Description => "Dump GUI tree to /guidump.txt in user data.";
@@ -449,15 +449,13 @@ namespace Robust.Client.Console.Commands
var uiMgr = IoCManager.Resolve<IUserInterfaceManager>();
var res = IoCManager.Resolve<IResourceManager>();
using (var stream = res.UserData.Create(new ResourcePath("/guidump.txt")))
using (var writer = new StreamWriter(stream, EncodingHelpers.UTF8))
using var writer = res.UserData.OpenWriteText(new ResourcePath("/guidump.txt"));
foreach (var root in uiMgr.AllRoots)
{
foreach (var root in uiMgr.AllRoots)
{
writer.WriteLine($"ROOT: {root}");
_writeNode(root, 0, writer);
writer.WriteLine("---------------");
}
writer.WriteLine($"ROOT: {root}");
_writeNode(root, 0, writer);
writer.WriteLine("---------------");
}
shell.WriteLine("Saved guidump");
@@ -514,7 +512,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class UITestCommand : IConsoleCommand
internal sealed class UITestCommand : IConsoleCommand
{
public string Command => "uitest";
public string Description => "Open a dummy UI testing window";
@@ -522,7 +520,7 @@ namespace Robust.Client.Console.Commands
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
var window = new SS14Window { MinSize = (500, 400)};
var window = new DefaultWindow { MinSize = (500, 400)};
var tabContainer = new TabContainer();
window.Contents.AddChild(tabContainer);
var scroll = new ScrollContainer();
@@ -646,7 +644,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class SetClipboardCommand : IConsoleCommand
internal sealed class SetClipboardCommand : IConsoleCommand
{
public string Command => "setclipboard";
public string Description => "Sets the system clipboard";
@@ -659,7 +657,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class GetClipboardCommand : IConsoleCommand
internal sealed class GetClipboardCommand : IConsoleCommand
{
public string Command => "getclipboard";
public string Description => "Gets the system clipboard";
@@ -672,7 +670,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class ToggleLight : IConsoleCommand
internal sealed class ToggleLight : IConsoleCommand
{
public string Command => "togglelight";
public string Description => "Toggles light rendering.";
@@ -686,7 +684,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class ToggleFOV : IConsoleCommand
internal sealed class ToggleFOV : IConsoleCommand
{
public string Command => "togglefov";
public string Description => "Toggles fov for client.";
@@ -700,7 +698,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class ToggleHardFOV : IConsoleCommand
internal sealed class ToggleHardFOV : IConsoleCommand
{
public string Command => "togglehardfov";
public string Description => "Toggles hard fov for client (for debugging space-station-14#2353).";
@@ -714,7 +712,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class ToggleShadows : IConsoleCommand
internal sealed class ToggleShadows : IConsoleCommand
{
public string Command => "toggleshadows";
public string Description => "Toggles shadow rendering.";
@@ -727,7 +725,7 @@ namespace Robust.Client.Console.Commands
mgr.DrawShadows = !mgr.DrawShadows;
}
}
internal class ToggleLightBuf : IConsoleCommand
internal sealed class ToggleLightBuf : IConsoleCommand
{
public string Command => "togglelightbuf";
public string Description => "Toggles lighting rendering. This includes shadows but not FOV.";
@@ -741,7 +739,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class GcCommand : IConsoleCommand
internal sealed class GcCommand : IConsoleCommand
{
public string Command => "gc";
public string Description => "Run the GC.";
@@ -763,7 +761,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class GcFullCommand : IConsoleCommand
internal sealed class GcFullCommand : IConsoleCommand
{
public string Command => "gcf";
public string Description => "Run the GC, fully, compacting LOH and everything.";
@@ -776,7 +774,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class GcModeCommand : IConsoleCommand
internal sealed class GcModeCommand : IConsoleCommand
{
public string Command => "gc_mode";
@@ -818,7 +816,7 @@ namespace Robust.Client.Console.Commands
}
internal class SerializeStatsCommand : IConsoleCommand
internal sealed class SerializeStatsCommand : IConsoleCommand
{
public string Command => "szr_stats";
@@ -838,7 +836,7 @@ namespace Robust.Client.Console.Commands
}
internal class ChunkInfoCommand : IConsoleCommand
internal sealed class ChunkInfoCommand : IConsoleCommand
{
public string Command => "chunkinfo";
public string Description => "Gets info about a chunk under your mouse cursor.";
@@ -867,7 +865,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class ReloadShadersCommand : IConsoleCommand
internal sealed class ReloadShadersCommand : IConsoleCommand
{
public string Command => "rldshader";
@@ -1038,7 +1036,7 @@ namespace Robust.Client.Console.Commands
}
internal class ClydeDebugLayerCommand : IConsoleCommand
internal sealed class ClydeDebugLayerCommand : IConsoleCommand
{
public string Command => "cldbglyr";
public string Description => "Toggle fov and light debug layers";
@@ -1063,7 +1061,7 @@ namespace Robust.Client.Console.Commands
}
}
internal class GetKeyInfoCommand : IConsoleCommand
internal sealed class GetKeyInfoCommand : IConsoleCommand
{
public string Command => "keyinfo";
public string Description => "Keys key info for a key";

View File

@@ -4,7 +4,7 @@ using Robust.Shared.GameObjects;
namespace Robust.Client.Console.Commands
{
public class GridChunkBBCommand : IConsoleCommand
public sealed class GridChunkBBCommand : IConsoleCommand
{
public string Command => "showchunkbb";
public string Description => "Displays chunk bounds for the purposes of rendering";

View File

@@ -5,7 +5,7 @@ using Robust.Shared.Network;
namespace Robust.Client.Console.Commands
{
class HelpCommand : IConsoleCommand
sealed class HelpCommand : IConsoleCommand
{
public string Command => "help";
public string Help => "When no arguments are provided, displays a generic help text. When an argument is passed, display the help text for the command with that name.";
@@ -44,7 +44,7 @@ namespace Robust.Client.Console.Commands
}
}
class ListCommand : IConsoleCommand
sealed class ListCommand : IConsoleCommand
{
public string Command => "list";
public string Help => "Usage: list [filter]\n" +

View File

@@ -1,9 +1,7 @@
#if !FULL_RELEASE
using System;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Data.Sqlite;
using Robust.Client.Utility;
using Robust.Shared.Console;
using Robust.Shared.IoC;
@@ -22,44 +20,38 @@ namespace Robust.Client.Console.Commands
var wantName = args.Length > 0 ? args[0] : null;
var basePath = Path.GetDirectoryName(UserDataDir.GetUserDataDir())!;
var cfgPath = Path.Combine(basePath, "launcher", "launcher_config.json");
var dbPath = Path.Combine(basePath, "launcher", "settings.db");
var data = JsonSerializer.Deserialize<LauncherConfig>(File.ReadAllText(cfgPath))!;
using var con = new SqliteConnection($"Data Source={dbPath};Mode=ReadOnly");
con.Open();
using var cmd = con.CreateCommand();
cmd.CommandText = "SELECT UserId, UserName, Token FROM Login WHERE Expires > datetime('NOW')";
var login = wantName != null
? data.Logins.FirstOrDefault(p => p.Username == wantName)
: data.Logins.FirstOrDefault();
if (wantName != null)
{
cmd.CommandText += " AND UserName = @userName";
cmd.Parameters.AddWithValue("@userName", wantName);
}
if (login == null)
cmd.CommandText += " LIMIT 1;";
using var reader = cmd.ExecuteReader();
if (!reader.Read())
{
shell.WriteLine("Unable to find a matching login");
return;
}
var token = login.Token.Token;
var userId = login.UserId;
var userId = Guid.Parse(reader.GetString(0));
var userName = reader.GetString(1);
var token = reader.GetString(2);
var cfg = IoCManager.Resolve<IAuthManager>();
cfg.Token = token;
cfg.UserId = new NetUserId(Guid.Parse(userId));
}
cfg.UserId = new NetUserId(userId);
private sealed class LauncherConfig
{
[JsonInclude] [JsonPropertyName("logins")]
public LauncherLogin[] Logins = default!;
}
private sealed class LauncherLogin
{
[JsonInclude] public string Username = default!;
[JsonInclude] public string UserId = default!;
[JsonInclude] public LauncherToken Token = default!;
}
private sealed class LauncherToken
{
[JsonInclude] public string Token = default!;
shell.WriteLine($"Logged into account {userName}");
}
}
}

View File

@@ -4,7 +4,7 @@ using Robust.Shared.Console;
namespace Robust.Client.Console.Commands
{
class LogSetLevelCommand : IConsoleCommand
sealed class LogSetLevelCommand : IConsoleCommand
{
public string Command => "loglevel";
public string Description => "Changes the log level for a provided sawmill.";
@@ -40,7 +40,7 @@ namespace Robust.Client.Console.Commands
}
}
class TestLog : IConsoleCommand
sealed class TestLog : IConsoleCommand
{
public string Command => "testlog";
public string Description => "Writes a test log to a sawmill.";

View File

@@ -4,7 +4,7 @@ using Robust.Shared.IoC;
namespace Robust.Client.Console.Commands
{
class HardQuitCommand : IConsoleCommand
sealed class HardQuitCommand : IConsoleCommand
{
public string Command => "hardquit";
public string Description => "Kills the game client instantly.";
@@ -16,7 +16,7 @@ namespace Robust.Client.Console.Commands
}
}
class QuitCommand : IConsoleCommand
sealed class QuitCommand : IConsoleCommand
{
public string Command => "quit";
public string Description => "Shuts down the game client gracefully.";

View File

@@ -6,7 +6,7 @@ using Robust.Shared.IoC;
namespace Robust.Client.Console.Commands
{
[UsedImplicitly]
public class SetInputContextCommand : IConsoleCommand
public sealed class SetInputContextCommand : IConsoleCommand
{
public string Command => "setinputcontext";
public string Description => "Sets the active input context.";

View File

@@ -4,7 +4,7 @@ using Robust.Shared.GameObjects;
namespace Robust.Client.Console.Commands
{
public class VelocitiesCommand : IConsoleCommand
public sealed class VelocitiesCommand : IConsoleCommand
{
public string Command => "showvelocities";
public string Description => "Displays your angular and linear velocities";

View File

@@ -11,7 +11,7 @@ using static Robust.Shared.Network.Messages.MsgScriptCompletionResponse;
namespace Robust.Client.Console
{
public class Completions : SS14Window
public sealed class Completions : DefaultWindow
{
private HistoryLineEdit _textBar;
private ScrollContainer _suggestPanel = new()
@@ -75,7 +75,7 @@ namespace Robust.Client.Console
}
// Label and ghetto button.
public class Entry : RichTextLabel
public sealed class Entry : RichTextLabel
{
public readonly LiteResult Result;

View File

@@ -6,7 +6,7 @@ using Robust.Shared.Network.Messages;
namespace Robust.Client.Console
{
public partial class ScriptClient : IScriptClient
public sealed partial class ScriptClient : IScriptClient
{
[Dependency] private readonly IClientConGroupController _conGroupController = default!;
[Dependency] private readonly IClientNetManager _netManager = default!;

View File

@@ -210,6 +210,23 @@ namespace Robust.Client.Console
vvm.OpenVV(a);
}
protected override void WriteSyntax(object toString)
{
var code = toString.ToString();
if (code == null)
return;
var options = ScriptInstanceShared.GetScriptOptions(_owner._reflectionManager).AddReferences(typeof(Image).Assembly);
var script = CSharpScript.Create(code, options, typeof(ScriptGlobals));
script.Compile();
var syntax = new FormattedMessage();
ScriptInstanceShared.AddWithSyntaxHighlighting(script, syntax, code, _owner._highlightWorkspace);
_owner.OutputPanel.AddMessage(syntax);
}
public override void write(object toString)
{
_owner.OutputPanel.AddText(toString?.ToString() ?? "");

View File

@@ -15,7 +15,7 @@ using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Robust.Client.Console
{
public class WatchWindow : SS14Window
public sealed class WatchWindow : DefaultWindow
{
private readonly IReflectionManager _reflectionManager;
@@ -155,6 +155,11 @@ namespace Robust.Client.Console
IoCManager.InjectDependencies(this);
}
protected override void WriteSyntax(object toString)
{
// No-op: nothing to write to.
}
public override void write(object toString)
{
// No-op: nothing to write to.

View File

@@ -7,7 +7,7 @@ using Robust.Shared.Maths;
namespace Robust.Client.Debugging
{
/// <inheritdoc />
public class DebugDrawing : IDebugDrawing
public sealed class DebugDrawing : IDebugDrawing
{
[Dependency] private readonly IOverlayManager _overlayManager = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!;

View File

@@ -207,10 +207,10 @@ namespace Robust.Client.Debugging
const float AlphaModifier = 0.2f;
foreach (var fixture in physBody.Fixtures)
foreach (var fixture in _entityManager.GetComponent<FixturesComponent>(physBody.Owner).Fixtures.Values)
{
// Invalid shape - Box2D doesn't check for IsSensor
if (physBody.BodyType == BodyType.Dynamic && fixture.Mass == 0f)
// Invalid shape - Box2D doesn't check for IsSensor but we will for sanity.
if (physBody.BodyType == BodyType.Dynamic && fixture.Mass == 0f && fixture.Hard)
{
DrawShape(worldHandle, fixture, xform, Color.Red.WithAlpha(AlphaModifier));
}
@@ -274,7 +274,7 @@ namespace Robust.Client.Debugging
const float AlphaModifier = 0.2f;
Box2? aabb = null;
foreach (var fixture in physBody.Fixtures)
foreach (var fixture in _entityManager.GetComponent<FixturesComponent>(physBody.Owner).Fixtures.Values)
{
for (var i = 0; i < fixture.Shape.ChildCount; i++)
{

View File

@@ -7,7 +7,7 @@ namespace Robust.Client
{
internal partial class GameController
{
internal class LoaderEntryPoint : ILoaderEntryPoint
internal sealed class LoaderEntryPoint : ILoaderEntryPoint
{
public void Main(IMainArgs args)
{

View File

@@ -1,5 +1,7 @@
using System;
using System.IO;
using System.Reflection;
using System.Runtime.Loader;
using Robust.Client.WebViewHook;
using Robust.Shared.Log;
using Robust.Shared.Utility;
@@ -8,12 +10,8 @@ namespace Robust.Client
{
internal sealed partial class GameController
{
private void LoadOptionalRobustModules(GameController.DisplayMode mode)
private void LoadOptionalRobustModules(DisplayMode mode, ResourceManifestData manifest)
{
// In the future, this manifest should be loaded somewhere else and used for more parts of init.
// For now, this is fine.
var manifest = LoadResourceManifest();
foreach (var module in manifest.Modules)
{
switch (module)
@@ -32,7 +30,8 @@ namespace Robust.Client
{
Logger.Debug("Loading Robust.Client.WebView");
var assembly = LoadRobustModuleAssembly("Robust.Client.WebView");
var alc = CreateModuleLoadContext("Robust.Client.WebView");
var assembly = alc.LoadFromAssemblyName(new AssemblyName("Robust.Client.WebView"));
var attribute = assembly.GetCustomAttribute<WebViewManagerImplAttribute>()!;
DebugTools.AssertNotNull(attribute);
@@ -43,10 +42,52 @@ namespace Robust.Client
Logger.Debug("Done initializing Robust.Client.WebView");
}
private Assembly LoadRobustModuleAssembly(string assemblyName)
/// <summary>
/// Creates an <see cref="AssemblyLoadContext"/> that loads from an engine module directory.
/// </summary>
private AssemblyLoadContext CreateModuleLoadContext(string moduleName)
{
// TODO: Launcher distribution and all that stuff.
return Assembly.Load(assemblyName);
var sawmill = _logManager.GetSawmill("robust.mod");
var alc = new AssemblyLoadContext(moduleName);
var envVarName = $"ROBUST_MODULE_{moduleName.ToUpperInvariant().Replace('.', '_')}";
var envVar = Environment.GetEnvironmentVariable(envVarName);
if (string.IsNullOrEmpty(envVar))
{
sawmill.Debug("Module {ModuleName} has no path override specified", moduleName);
return alc;
}
sawmill.Debug("Path for module {ModuleName} is {ModulePath}", moduleName, envVar);
alc.Resolving += (_, name) =>
{
sawmill.Debug("Loading {AssemblyName} from module {ModuleName}", name.ToString(), moduleName);
var assemblyPath = Path.Combine(envVar, $"{name.Name}.dll");
if (!File.Exists(assemblyPath))
return null;
return alc.LoadFromAssemblyPath(assemblyPath);
};
_modLoader.ExtraModuleLoaders += name =>
{
foreach (var assembly in alc.Assemblies)
{
var assemblyName = assembly.GetName();
if (assemblyName.Name == name.Name)
{
sawmill.Debug("Resolved {ResolvingAssembly} as assembly {ResolvedAssembly} from {ModuleName}", name.ToString(), assemblyName.ToString(), moduleName);
return assembly;
}
}
return null;
};
_modLoader.AddEngineModuleDirectory(envVar);
return alc;
}
}
}

View File

@@ -79,6 +79,8 @@ namespace Robust.Client
public GameControllerOptions Options { get; private set; } = new();
public InitialLaunchState LaunchState { get; private set; } = default!;
private ResourceManifestData? _resourceManifest;
public void SetCommandLineArgs(CommandLineArgs args)
{
_commandLineArgs = args;
@@ -86,19 +88,25 @@ namespace Robust.Client
internal bool StartupContinue(DisplayMode displayMode)
{
DebugTools.AssertNotNull(_resourceManifest);
_clyde.InitializePostWindowing();
_clydeAudio.InitializePostWindowing();
_clyde.SetWindowTitle(Options.DefaultWindowTitle);
_clyde.SetWindowTitle(Options.DefaultWindowTitle ?? _resourceManifest!.DefaultWindowTitle ?? "RobustToolbox");
_taskManager.Initialize();
_fontManager.SetFontDpi((uint)_configurationManager.GetCVar(CVars.DisplayFontDpi));
// Load optional Robust modules.
LoadOptionalRobustModules(displayMode, _resourceManifest!);
// Disable load context usage on content start.
// This prevents Content.Client being loaded twice and things like csi blowing up because of it.
_modLoader.SetUseLoadContext(!ContentStart);
_modLoader.SetEnableSandboxing(Options.Sandboxing);
if (!_modLoader.TryLoadModulesFrom(Options.AssemblyDirectory, Options.ContentModulePrefix))
var assemblyPrefix = Options.ContentModulePrefix ?? _resourceManifest!.AssemblyPrefix ?? "Content.";
if (!_modLoader.TryLoadModulesFrom(Options.AssemblyDirectory, assemblyPrefix))
{
Logger.Fatal("Errors while loading content assemblies.");
return false;
@@ -111,9 +119,6 @@ namespace Robust.Client
IoCManager.Resolve<ISerializationManager>().Initialize();
// Load optional Robust modules.
LoadOptionalRobustModules(displayMode);
// Call Init in game assemblies.
_modLoader.BroadcastRunLevel(ModRunLevel.PreInit);
_modLoader.BroadcastRunLevel(ModRunLevel.Init);
@@ -129,8 +134,8 @@ namespace Robust.Client
_prototypeManager.Initialize();
_prototypeManager.LoadDirectory(Options.PrototypeDirectory);
_prototypeManager.Resync();
_mapManager.Initialize();
_entityManager.Initialize();
_mapManager.Initialize();
_gameStateManager.Initialize();
_placementManager.Initialize();
_viewVariablesManager.Initialize();
@@ -209,7 +214,7 @@ namespace Robust.Client
{
// Parses /manifest.yml for game-specific settings that cannot be exclusively set up by content code.
if (!_resourceCache.TryContentFileRead("/manifest.yml", out var stream))
return new ResourceManifestData(Array.Empty<string>());
return new ResourceManifestData(Array.Empty<string>(), null, null, null, null);
var yamlStream = new YamlStream();
using (stream)
@@ -218,6 +223,9 @@ namespace Robust.Client
yamlStream.Load(streamReader);
}
if (yamlStream.Documents.Count == 0)
return new ResourceManifestData(Array.Empty<string>(), null, null, null, null);
if (yamlStream.Documents.Count != 1 || yamlStream.Documents[0].RootNode is not YamlMappingNode mapping)
{
throw new InvalidOperationException(
@@ -235,7 +243,23 @@ namespace Robust.Client
}
}
return new ResourceManifestData(modules);
string? assemblyPrefix = null;
if (mapping.TryGetNode("assemblyPrefix", out var prefixNode))
assemblyPrefix = prefixNode.AsString();
string? defaultWindowTitle = null;
if (mapping.TryGetNode("defaultWindowTitle", out var winTitleNode))
defaultWindowTitle = winTitleNode.AsString();
string? windowIconSet = null;
if (mapping.TryGetNode("windowIconSet", out var iconSetNode))
windowIconSet = iconSetNode.AsString();
string? splashLogo = null;
if (mapping.TryGetNode("splashLogo", out var splashNode))
splashLogo = splashNode.AsString();
return new ResourceManifestData(modules, assemblyPrefix, defaultWindowTitle, windowIconSet, splashLogo);
}
internal bool StartupSystemSplash(GameControllerOptions options, Func<ILogHandler>? logHandlerFactory)
@@ -301,15 +325,6 @@ namespace Robust.Client
_configurationManager.OverrideConVars(_commandLineArgs.CVars);
}
{
// Handle GameControllerOptions implicit CVar overrides.
_configurationManager.OverrideConVars(new[]
{
(CVars.DisplayWindowIconSet.Name, options.WindowIconSet.ToString()),
(CVars.DisplaySplashLogo.Name, options.SplashLogo.ToString())
});
}
ProfileOptSetup.Setup(_configurationManager);
_resourceCache.Initialize(Options.LoadConfigAndUserData ? userDataDir : null);
@@ -324,11 +339,32 @@ namespace Robust.Client
if (_loaderArgs != null)
{
if (_loaderArgs.ApiMounts is { } mounts)
{
foreach (var (api, prefix) in mounts)
{
_resourceCache.MountLoaderApi(api, "", new ResourcePath(prefix));
}
}
_stringSerializer.EnableCaching = false;
_resourceCache.MountLoaderApi(_loaderArgs.FileApi, "Resources/");
_modLoader.VerifierExtraLoadHandler = VerifierExtraLoadHandler;
}
_resourceManifest = LoadResourceManifest();
{
// Handle GameControllerOptions implicit CVar overrides.
_configurationManager.OverrideConVars(new[]
{
(CVars.DisplayWindowIconSet.Name,
options.WindowIconSet?.ToString() ?? _resourceManifest.WindowIconSet ?? ""),
(CVars.DisplaySplashLogo.Name,
options.SplashLogo?.ToString() ?? _resourceManifest.SplashLogo ?? "")
});
}
_clyde.TextEntered += TextEntered;
_clyde.MouseMove += MouseMove;
_clyde.KeyUp += KeyUp;
@@ -431,7 +467,9 @@ namespace Robust.Client
// In singleplayer, however, we're in full control instead.
else if (_client.RunLevel == ClientRunLevel.SinglePlayerGame)
{
_entityManager.TickUpdate(frameEventArgs.DeltaSeconds);
// The last real tick is the current tick! This way we won't be in "prediction" mode.
_gameTiming.LastRealTick = _gameTiming.CurTick;
_entityManager.TickUpdate(frameEventArgs.DeltaSeconds, noPredictions: false);
_lookup.Update();
}
@@ -543,6 +581,12 @@ namespace Robust.Client
_clydeAudio.Shutdown();
}
private sealed record ResourceManifestData(string[] Modules);
private sealed record ResourceManifestData(
string[] Modules,
string? AssemblyPrefix,
string? DefaultWindowTitle,
string? WindowIconSet,
string? SplashLogo
);
}
}

View File

@@ -3,7 +3,7 @@ using Robust.Shared.Utility;
namespace Robust.Client
{
public class GameControllerOptions
public sealed class GameControllerOptions
{
/// <summary>
/// Whether content sandboxing will be enabled & enforced.
@@ -30,12 +30,18 @@ namespace Robust.Client
/// <summary>
/// Default window title.
/// </summary>
public string DefaultWindowTitle { get; init; } = "Space Station 14";
/// <remarks>
/// Defaults to <c>RobustToolbox</c> if unset.
/// </remarks>
public string? DefaultWindowTitle { get; init; }
/// <summary>
/// Assemblies with this prefix will be loaded.
/// </summary>
public string ContentModulePrefix { get; init; } = "Content.";
/// <remarks>
/// Defaults to <c>Content.</c> if unset.
/// </remarks>
public string? ContentModulePrefix { get; init; }
/// <summary>
/// Name of the content build directory, for game pack mounting purposes.
@@ -55,12 +61,12 @@ namespace Robust.Client
/// <summary>
/// Directory resource path containing window icons to load.
/// </summary>
public ResourcePath WindowIconSet { get; init; } = new("/Textures/Logo/icon");
public ResourcePath? WindowIconSet { get; init; }
/// <summary>
/// Resource path for splash image to show when the game starts up.
/// </summary>
public ResourcePath SplashLogo { get; init; } = new("/Textures/Logo/logo.png");
public ResourcePath? SplashLogo { get; init; }
/// <summary>
/// Whether to disable mounting the "Resources/" folder on FULL_RELEASE.

View File

@@ -6,7 +6,7 @@ using Robust.Shared.Reflection;
namespace Robust.Client.GameObjects
{
internal class ClientComponentFactory : ComponentFactory
internal sealed class ClientComponentFactory : ComponentFactory
{
public ClientComponentFactory(IDynamicTypeFactoryInternal typeFactory, IReflectionManager reflectionManager, IConsoleHost conHost)
: base(typeFactory, reflectionManager, conHost)
@@ -29,13 +29,9 @@ namespace Robust.Client.GameObjects
RegisterClass<EyeComponent>();
RegisterClass<AnimationPlayerComponent>();
RegisterClass<TimerComponent>();
#if DEBUG
RegisterClass<DebugExceptionOnAddComponent>();
RegisterClass<DebugExceptionInitializeComponent>();
RegisterClass<DebugExceptionStartupComponent>();
#endif
}
}
}

View File

@@ -67,7 +67,7 @@ namespace Robust.Client.GameObjects
_networkManager.RegisterNetMessage<MsgEntity>(HandleEntityNetworkMessage);
}
public override void TickUpdate(float frameTime, Histogram? histogram)
public override void TickUpdate(float frameTime, bool noPredictions, Histogram? histogram)
{
using (histogram?.WithLabels("EntityNet").NewTimer())
{
@@ -79,7 +79,7 @@ namespace Robust.Client.GameObjects
}
}
base.TickUpdate(frameTime, histogram);
base.TickUpdate(frameTime, noPredictions, histogram);
}
/// <inheritdoc />
@@ -109,10 +109,11 @@ namespace Robust.Client.GameObjects
[Obsolete("Component Messages are deprecated, use Entity Events instead.")]
public void SendComponentNetworkMessage(INetChannel? channel, EntityUid entity, IComponent component, ComponentMessage message)
{
var netId = ComponentFactory.GetRegistration(component.GetType()).NetID;
var componentType = component.GetType();
var netId = ComponentFactory.GetRegistration(componentType).NetID;
if (!netId.HasValue)
throw new ArgumentException($"Component {component.Name} does not have a NetID.", nameof(component));
throw new ArgumentException($"Component {componentType} does not have a NetID.", nameof(component));
var msg = _networkManager.CreateNetMessage<MsgEntity>();
msg.Type = EntityMessageType.ComponentMessage;

View File

@@ -4,6 +4,7 @@ using System.Runtime.Serialization;
namespace Robust.Client.GameObjects
{
[Serializable]
[Virtual]
public class ComponentStateApplyException : Exception
{
public ComponentStateApplyException()

View File

@@ -13,8 +13,6 @@ namespace Robust.Client.GameObjects
{
// TODO: Give this component a friend someday. Way too much content shit to change atm ._.
public override string Name => "AnimationPlayer";
public int PlayingAnimationCount => PlayingAnimations.Count;
internal readonly Dictionary<string, AnimationPlayback> PlayingAnimations

View File

@@ -1,4 +1,5 @@
using Robust.Shared.GameObjects;
using System;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Robust.Client.GameObjects;
@@ -14,6 +15,7 @@ public abstract class AppearanceVisualizer
/// Initializes an entity to be managed by this appearance controller.
/// DO NOT assume this is your only entity. Visualizers are shared.
/// </summary>
[Obsolete("Subscribe to your component being initialised instead.")]
public virtual void InitializeEntity(EntityUid entity)
{
}
@@ -23,6 +25,7 @@ public abstract class AppearanceVisualizer
/// Update its visuals here.
/// </summary>
/// <param name="component">The appearance component of the entity that might need updating.</param>
[Obsolete("Subscribe to AppearanceChangeEvent instead.")]
public virtual void OnChangeData(AppearanceComponent component)
{
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using Robust.Shared.Analyzers;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
@@ -9,39 +10,10 @@ namespace Robust.Client.GameObjects;
/// This is the client instance of <see cref="AppearanceComponent"/>.
/// </summary>
[RegisterComponent]
[ComponentReference(typeof(AppearanceComponent))]
[ComponentReference(typeof(AppearanceComponent)), Friend(typeof(AppearanceSystem))]
public sealed class ClientAppearanceComponent : AppearanceComponent
{
[ViewVariables]
private bool _appearanceDirty;
[ViewVariables]
[DataField("visuals")]
internal List<AppearanceVisualizer> Visualizers = new();
protected override void MarkDirty()
{
if (_appearanceDirty)
return;
EntitySystem.Get<AppearanceSystem>().EnqueueUpdate(this);
_appearanceDirty = true;
}
protected override void Initialize()
{
base.Initialize();
foreach (var visual in Visualizers)
{
visual.InitializeEntity(Owner);
}
MarkDirty();
}
internal void UnmarkDirty()
{
_appearanceDirty = false;
}
}

View File

@@ -9,14 +9,11 @@ using Robust.Shared.ViewVariables;
namespace Robust.Client.GameObjects
{
[ComponentReference(typeof(SharedEyeComponent))]
public class EyeComponent : SharedEyeComponent
public sealed class EyeComponent : SharedEyeComponent
{
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
/// <inheritdoc />
public override string Name => "Eye";
[ViewVariables]
private Eye? _eye = default!;

View File

@@ -1,4 +1,4 @@
using Robust.Client.Graphics;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Client.Utility;
using Robust.Shared.GameObjects;
@@ -12,9 +12,8 @@ using Robust.Shared.Utility;
namespace Robust.Client.GameObjects
{
[RegisterComponent]
public class IconComponent : Component, ISerializationHooks
public sealed class IconComponent : Component, ISerializationHooks
{
public override string Name => "Icon";
public IDirectionalTextureProvider? Icon { get; private set; }
[DataField("sprite")]

View File

@@ -1,4 +1,4 @@
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Input;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
@@ -8,11 +8,8 @@ namespace Robust.Client.GameObjects
/// <summary>
/// Defines data fields used in the <see cref="InputSystem"/>.
/// </summary>
public class InputComponent : Component
public sealed class InputComponent : Component
{
/// <inheritdoc />
public override string Name => "Input";
/// <summary>
/// The context that will be made active for a client that attaches to this entity.
/// </summary>

View File

@@ -40,13 +40,14 @@ namespace Robust.Client.GameObjects
public void AnchorStateChanged()
{
SendDirty();
var xform = _entityManager.GetComponent<TransformComponent>(Owner);
SendDirty(xform);
if(!_entityManager.GetComponent<TransformComponent>(Owner).Anchored)
if(!xform.Anchored)
return;
var grid = _mapManager.GetGrid(_entityManager.GetComponent<TransformComponent>(Owner).GridID);
_lastPosition = (_entityManager.GetComponent<TransformComponent>(Owner).GridID, grid.TileIndicesFor(_entityManager.GetComponent<TransformComponent>(Owner).Coordinates));
var grid = _mapManager.GetGrid(xform.GridID);
_lastPosition = (xform.GridID, grid.TileIndicesFor(xform.Coordinates));
}
protected override void Shutdown()
@@ -56,9 +57,10 @@ namespace Robust.Client.GameObjects
SendDirty();
}
private void SendDirty()
private void SendDirty(TransformComponent? xform = null)
{
if (_entityManager.GetComponent<TransformComponent>(Owner).Anchored)
xform ??= _entityManager.GetComponent<TransformComponent>(Owner);
if (xform.Anchored)
{
_entityManager.EventBus.RaiseEvent(EventSource.Local,
new OccluderDirtyEvent(Owner, _lastPosition));

View File

@@ -11,7 +11,7 @@ namespace Robust.Client.GameObjects
{
[RegisterComponent]
[ComponentReference(typeof(SharedPointLightComponent))]
public class PointLightComponent : SharedPointLightComponent, ISerializationHooks
public sealed class PointLightComponent : SharedPointLightComponent, ISerializationHooks
{
[Dependency] private readonly IEntityManager _entityManager = default!;
@@ -96,26 +96,6 @@ namespace Robust.Client.GameObjects
[ViewVariables(VVAccess.ReadWrite)]
public Texture? Mask { get; set; }
[ViewVariables(VVAccess.ReadWrite)]
[Animatable]
public float Energy
{
get => _energy;
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
{
@@ -134,10 +114,7 @@ namespace Robust.Client.GameObjects
[DataField("autoRot")]
private bool _maskAutoRotate;
private Angle _rotation;
[DataField("energy")]
private float _energy = 1f;
[DataField("softness")]
private float _softness = 1f;
[DataField("mask")]
internal string? _maskPath;
@@ -162,7 +139,7 @@ namespace Robust.Client.GameObjects
internal RenderingTreeComponent? RenderTree { get; set; }
}
public class PointLightRadiusChangedEvent : EntityEventArgs
public sealed class PointLightRadiusChangedEvent : EntityEventArgs
{
public PointLightComponent PointLightComponent { get; }

View File

@@ -57,7 +57,7 @@ namespace Robust.Client.GameObjects
private bool _enabled;
}
public class SpriteBoundsOverlay : Overlay
public sealed class SpriteBoundsOverlay : Overlay
{
public override OverlaySpace Space => OverlaySpace.WorldSpace;

View File

@@ -1257,7 +1257,10 @@ namespace Robust.Client.GameObjects
if (worldRotation.Theta < 0)
worldRotation = new Angle(worldRotation.Theta + Math.Tau);
var spriteMatrix = GetLocalMatrix();
// sprite matrix, WITHOUT offset.
// offset is applied after sprite numDirs snapping/rotation correction
// --> apply at same time as layer offset
var spriteMatrix = Matrix3.CreateTransform(Vector2.Zero, rotation, scale);
foreach (var layer in Layers)
{
@@ -1268,7 +1271,7 @@ namespace Robust.Client.GameObjects
var numDirs = GetLayerDirectionCount(layer);
var layerRotation = worldRotation + layer.Rotation;
var layerPosition = worldPosition + layerRotation.RotateVec(layer._offset);
var layerPosition = worldPosition + layerRotation.RotateVec(layer._offset + offset);
CalcModelMatrix(numDirs, eyeRotation, layerRotation, layerPosition, out var modelMatrix);
Matrix3.Multiply(ref spriteMatrix, ref modelMatrix, out var transformMatrix);
@@ -1474,30 +1477,6 @@ namespace Robust.Client.GameObjects
}
}
private RSI.State.Direction GetDir(RSI.State.DirectionType rsiDirectionType, Angle worldRotation)
{
var dir = rsiDirectionType switch
{
RSI.State.DirectionType.Dir1 => Direction.South,
RSI.State.DirectionType.Dir4 => worldRotation.GetCardinalDir(),
RSI.State.DirectionType.Dir8 => worldRotation.GetDir(),
_ => throw new ArgumentException($"Unknown RSI DirectionType: {rsiDirectionType}.", nameof(rsiDirectionType))
};
return dir switch
{
Direction.North => RSI.State.Direction.North,
Direction.South => RSI.State.Direction.South,
Direction.East => RSI.State.Direction.East,
Direction.West => RSI.State.Direction.West,
Direction.SouthEast => RSI.State.Direction.SouthEast,
Direction.SouthWest => RSI.State.Direction.SouthWest,
Direction.NorthEast => RSI.State.Direction.NorthEast,
Direction.NorthWest => RSI.State.Direction.NorthWest,
_ => throw new ArgumentOutOfRangeException(nameof(dir), dir, null)
};
}
private void QueueUpdateIsInert()
{
// Look this was an easy way to get bounds checks for layer updates.
@@ -1547,58 +1526,13 @@ namespace Robust.Client.GameObjects
return rsi["error"];
}
private static RSI.State.Direction OffsetRsiDir(RSI.State.Direction dir, DirectionOffset offset)
{
// There is probably a better way to do this.
// Eh.
switch (offset)
{
case DirectionOffset.None:
return dir;
case DirectionOffset.Clockwise:
return dir switch
{
RSI.State.Direction.North => RSI.State.Direction.East,
RSI.State.Direction.East => RSI.State.Direction.South,
RSI.State.Direction.South => RSI.State.Direction.West,
RSI.State.Direction.West => RSI.State.Direction.North,
_ => throw new NotImplementedException()
};
case DirectionOffset.CounterClockwise:
return dir switch
{
RSI.State.Direction.North => RSI.State.Direction.West,
RSI.State.Direction.East => RSI.State.Direction.North,
RSI.State.Direction.South => RSI.State.Direction.East,
RSI.State.Direction.West => RSI.State.Direction.South,
_ => throw new NotImplementedException()
};
case DirectionOffset.Flip:
switch (dir)
{
case RSI.State.Direction.North:
return RSI.State.Direction.South;
case RSI.State.Direction.East:
return RSI.State.Direction.West;
case RSI.State.Direction.South:
return RSI.State.Direction.North;
case RSI.State.Direction.West:
return RSI.State.Direction.East;
default:
throw new NotImplementedException();
}
default:
throw new NotImplementedException();
}
}
public string GetDebugString()
{
var builder = new StringBuilder();
builder.AppendFormat(
"vis/depth/scl/rot/ofs/col/norot/override/dir: {0}/{1}/{2}/{3}/{4}/{5}/{6}/{8}/{7}\n",
Visible, DrawDepth, Scale, Rotation, Offset,
Color, NoRotation, GetDir(RSI.State.DirectionType.Dir8, entities.GetComponent<TransformComponent>(Owner).WorldRotation),
Color, NoRotation, entities.GetComponent<TransformComponent>(Owner).WorldRotation.ToRsiDirection(RSI.State.DirectionType.Dir8),
DirectionOverride
);
@@ -1681,7 +1615,7 @@ namespace Robust.Client.GameObjects
Flip = 3,
}
public class Layer : ISpriteLayer
public sealed class Layer : ISpriteLayer
{
[ViewVariables] private readonly SpriteComponent _parent;
@@ -1839,10 +1773,10 @@ namespace Robust.Client.GameObjects
}
else
{
dir = _parent.GetDir(state.Directions, worldRotation);
dir = worldRotation.ToRsiDirection(state.Directions);
}
return OffsetRsiDir(dir, DirOffset);
return dir.OffsetRsiDir(DirOffset);
}
}
@@ -2073,6 +2007,7 @@ namespace Robust.Client.GameObjects
var entityManager = IoCManager.Resolve<IEntityManager>();
var dummy = entityManager.SpawnEntity(prototype.ID, MapCoordinates.Nullspace);
var spriteComponent = entityManager.EnsureComponent<SpriteComponent>(dummy);
EntitySystem.Get<AppearanceSystem>().OnChangeData(dummy);
var anyTexture = false;
foreach (var layer in spriteComponent.AllLayers)

View File

@@ -6,8 +6,6 @@ namespace Robust.Client.GameObjects
[RegisterComponent]
public sealed class RenderingTreeComponent : Component
{
public override string Name => "RenderingTree";
internal DynamicTree<SpriteComponent> SpriteTree { get; set; } = default!;
internal DynamicTree<PointLightComponent> LightTree { get; set; } = default!;
}

View File

@@ -11,7 +11,7 @@ using Robust.Shared.ViewVariables;
namespace Robust.Client.GameObjects
{
[ComponentReference(typeof(SharedUserInterfaceComponent))]
public class ClientUserInterfaceComponent : SharedUserInterfaceComponent, ISerializationHooks
public sealed class ClientUserInterfaceComponent : SharedUserInterfaceComponent, ISerializationHooks
{
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
[Dependency] private readonly IDynamicTypeFactory _dynamicTypeFactory = default!;

View File

@@ -62,6 +62,12 @@ namespace Robust.Client.GameObjects
Play(component, animation, key);
}
public void Play(EntityUid uid, AnimationPlayerComponent? component, Animation animation, string key)
{
component ??= EntityManager.EnsureComponent<AnimationPlayerComponent>(uid);
Play(component, animation, key);
}
/// <summary>
/// Start playing an animation.
/// </summary>
@@ -79,6 +85,14 @@ namespace Robust.Client.GameObjects
component.PlayingAnimations.ContainsKey(key);
}
public bool HasRunningAnimation(EntityUid uid, AnimationPlayerComponent? component, string key)
{
if (component == null)
TryComp(uid, out component);
return component != null && component.PlayingAnimations.ContainsKey(key);
}
public bool HasRunningAnimation(AnimationPlayerComponent component, string key)
{
return component.PlayingAnimations.ContainsKey(key);
@@ -88,6 +102,18 @@ namespace Robust.Client.GameObjects
{
component.PlayingAnimations.Remove(key);
}
public void Stop(EntityUid uid, string key)
{
if (!TryComp<AnimationPlayerComponent>(uid, out var player)) return;
player.PlayingAnimations.Remove(key);
}
public void Stop(EntityUid uid, AnimationPlayerComponent? component, string key)
{
if (!Resolve(uid, ref component, false)) return;
component.PlayingAnimations.Remove(key);
}
}
public sealed class AnimationCompletedEvent : EntityEventArgs

View File

@@ -1,17 +1,71 @@
using System.Collections.Generic;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.GameStates;
namespace Robust.Client.GameObjects
{
[UsedImplicitly]
internal sealed class AppearanceSystem : EntitySystem
internal sealed class AppearanceSystem : SharedAppearanceSystem
{
private readonly Queue<ClientAppearanceComponent> _queuedUpdates = new();
public void EnqueueUpdate(ClientAppearanceComponent component)
public override void Initialize()
{
_queuedUpdates.Enqueue(component);
base.Initialize();
SubscribeLocalEvent<ClientAppearanceComponent, ComponentInit>(OnAppearanceInit);
SubscribeLocalEvent<ClientAppearanceComponent, ComponentHandleState>(OnAppearanceHandleState);
}
private void OnAppearanceInit(EntityUid uid, ClientAppearanceComponent component, ComponentInit args)
{
foreach (var visual in component.Visualizers)
{
visual.InitializeEntity(uid);
}
MarkDirty(component);
}
private void OnAppearanceHandleState(EntityUid uid, ClientAppearanceComponent component, ref ComponentHandleState args)
{
if (args.Current is not AppearanceComponentState actualState)
return;
var stateDiff = component.AppearanceData.Count != actualState.Data.Count;
if (!stateDiff)
{
foreach (var (key, value) in component.AppearanceData)
{
if (!actualState.Data.TryGetValue(key, out var stateValue) ||
!value.Equals(stateValue))
{
stateDiff = true;
break;
}
}
}
if (!stateDiff) return;
component.AppearanceData = actualState.Data;
MarkDirty(component);
}
public override void MarkDirty(AppearanceComponent component)
{
if (component.AppearanceDirty)
return;
_queuedUpdates.Enqueue((ClientAppearanceComponent) component);
component.AppearanceDirty = true;
}
internal void UnmarkDirty(ClientAppearanceComponent component)
{
component.AppearanceDirty = false;
}
public override void FrameUpdate(float frameTime)
@@ -19,15 +73,41 @@ namespace Robust.Client.GameObjects
while (_queuedUpdates.TryDequeue(out var appearance))
{
if (appearance.Deleted)
return;
continue;
foreach (var visualizer in appearance.Visualizers)
{
visualizer.OnChangeData(appearance);
}
OnChangeData(appearance.Owner, appearance);
UnmarkDirty(appearance);
}
}
appearance.UnmarkDirty();
public void OnChangeData(EntityUid uid, ClientAppearanceComponent? appearanceComponent = null)
{
if (!Resolve(uid, ref appearanceComponent, false)) return;
var ev = new AppearanceChangeEvent
{
Component = appearanceComponent,
AppearanceData = appearanceComponent.AppearanceData,
};
// Give it AppearanceData so we can still keep the friend attribute on the component.
EntityManager.EventBus.RaiseLocalEvent(uid, ref ev);
// Eventually visualizers would be nuked and we'd just make them components instead.
foreach (var visualizer in appearanceComponent.Visualizers)
{
visualizer.OnChangeData(appearanceComponent);
}
}
}
/// <summary>
/// Raised whenever the appearance data for an entity changes.
/// </summary>
[ByRefEvent]
public struct AppearanceChangeEvent
{
public AppearanceComponent Component = default!;
public IReadOnlyDictionary<object, object> AppearanceData = default!;
}
}

View File

@@ -17,7 +17,7 @@ using Robust.Shared.Utility;
namespace Robust.Client.GameObjects
{
[UsedImplicitly]
public class AudioSystem : SharedAudioSystem, IAudioSystem
public sealed class AudioSystem : SharedAudioSystem, IAudioSystem
{
[Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
@@ -253,9 +253,15 @@ namespace Robust.Client.GameObjects
/// </summary>
/// <param name="stream">The audio stream to play.</param>
/// <param name="audioParams"></param>
private IPlayingAudioStream Play(AudioStream stream, AudioParams? audioParams = null)
private IPlayingAudioStream? Play(AudioStream stream, AudioParams? audioParams = null)
{
var source = _clyde.CreateAudioSource(stream);
if (source == null)
{
return null;
}
ApplyAudioParams(audioParams, source);
source.SetGlobal();
@@ -303,6 +309,12 @@ namespace Robust.Client.GameObjects
AudioParams? audioParams = null)
{
var source = _clyde.CreateAudioSource(stream);
if (source == null)
{
return null;
}
if (!source.SetPosition(EntityManager.GetComponent<TransformComponent>(entity).WorldPosition))
{
return Play(stream, fallbackCoordinates, fallbackCoordinates, audioParams);
@@ -356,6 +368,12 @@ namespace Robust.Client.GameObjects
EntityCoordinates fallbackCoordinates, AudioParams? audioParams = null)
{
var source = _clyde.CreateAudioSource(stream);
if (source == null)
{
return null;
}
if (!source.SetPosition(fallbackCoordinates.Position))
{
source.Dispose();
@@ -402,7 +420,7 @@ namespace Robust.Client.GameObjects
source.IsLooping = audioParams.Value.Loop;
}
private class PlayingStream : IPlayingAudioStream
private sealed class PlayingStream : IPlayingAudioStream
{
public uint? NetIdentifier;
public IClydeAudioSource Source = default!;

View File

@@ -72,10 +72,13 @@ namespace Robust.Client.GameObjects
var sender = ev.Sender;
if (EntityManager.EntityExists(sender) &&
EntityManager.TryGetComponent(sender, out ClientOccluderComponent? iconSmooth)
&& iconSmooth.Running)
&& iconSmooth.Initialized)
{
var grid1 = _mapManager.GetGrid(EntityManager.GetComponent<TransformComponent>(sender).GridID);
var coords = EntityManager.GetComponent<TransformComponent>(sender).Coordinates;
var xform = EntityManager.GetComponent<TransformComponent>(sender);
if (!_mapManager.TryGetGrid(xform.GridID, out var grid1))
return;
var coords = xform.Coordinates;
_dirtyEntities.Enqueue(sender);
AddValidEntities(grid1.GetInDir(coords, Direction.North));
@@ -85,7 +88,7 @@ namespace Robust.Client.GameObjects
}
// Entity is no longer valid, update around the last position it was at.
if (ev.LastPosition.HasValue && _mapManager.TryGetGrid(ev.LastPosition.Value.grid, out var grid))
else if (ev.LastPosition.HasValue && _mapManager.TryGetGrid(ev.LastPosition.Value.grid, out var grid))
{
var pos = ev.LastPosition.Value.pos;

View File

@@ -5,12 +5,14 @@ using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.GameStates;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Serialization;
using static Robust.Shared.Containers.ContainerManagerComponent;
namespace Robust.Client.GameObjects
{
public class ContainerSystem : SharedContainerSystem
public sealed class ContainerSystem : SharedContainerSystem
{
[Dependency] private readonly IRobustSerializer _serializer = default!;
[Dependency] private readonly IDynamicTypeFactoryInternal _dynFactory = default!;
@@ -59,7 +61,7 @@ namespace Robust.Client.GameObjects
{
if (!cast.ContainerSet.Any(data => data.Id == id))
{
container.EmptyContainer(true);
container.EmptyContainer(true, entMan: EntityManager);
container.Shutdown();
toDelete ??= new List<string>();
toDelete.Add(id);
@@ -131,12 +133,51 @@ namespace Robust.Client.GameObjects
continue;
}
// If an entity is currently in the shadow realm, it means we probably left PVS and are now getting
// back into range. We do not want to directly insert this entity, as IF the container and entity
// transform states did not get sent simultaneously, the entity's transform will be modified by the
// insert operation. This means it will then be reset to the shadow realm, causing it to be ejected
// from the container. It would then subsequently be parented to the container without ever being
// re-inserted, leading to the client seeing what should be hidden entities attached to
// containers/players.
if (Transform(entity).MapID == MapId.Nullspace)
{
AddExpectedEntity(entity, container);
continue;
}
if (!container.ContainedEntities.Contains(entity))
container.Insert(entity);
}
}
}
protected override void HandleParentChanged(ref EntParentChangedMessage message)
{
base.HandleParentChanged(ref message);
// If an entity warped in from null-space (i.e., re-entered PVS) and got attached to a container, do the same checks as for newly initialized entities.
if (message.OldParent != null && message.OldParent.Value.IsValid())
return;
if (!ExpectedEntities.TryGetValue(message.Entity, out var container))
return;
if (Transform(message.Entity).ParentUid != container.Owner)
{
// This container is expecting an entity... but it got parented to some other entity???
// Ah well, the sever should send a new container state that updates expected entities so just ignore it for now.
return;
}
RemoveExpectedEntity(message.Entity);
if (container.Deleted)
return;
container.Insert(message.Entity);
}
private IContainer ContainerFactory(ContainerManagerComponent component, string containerType, string id)
{
var type = _serializer.FindSerializedType(typeof(IContainer), containerType);

View File

@@ -1,133 +0,0 @@
#if DEBUG
using System;
using System.Text;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Console;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
namespace Robust.Client.GameObjects
{
internal sealed class DebugGridTileLookupSystem : EntitySystem
{
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IInputManager _inputManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
public bool Enabled
{
get => _enabled;
set
{
if (_enabled == value) return;
_enabled = value;
if (_enabled)
{
_label.Visible = true;
LastTile = default;
}
else
{
_label.Text = null;
_label.Visible = false;
}
}
}
private bool _enabled;
private (GridId Grid, Vector2i Indices) LastTile;
// Label and shit that follows cursor
private Label _label = new()
{
Visible = false,
};
public override void Initialize()
{
base.Initialize();
SubscribeNetworkEvent<SendGridTileLookupMessage>(HandleSentEntities);
IoCManager.Resolve<IUserInterfaceManager>().StateRoot.AddChild(_label);
}
public override void Shutdown()
{
base.Shutdown();
IoCManager.Resolve<IUserInterfaceManager>().StateRoot.RemoveChild(_label);
}
private void RequestEntities(GridId gridId, Vector2i indices)
{
if (gridId == GridId.Invalid) return;
RaiseNetworkEvent(new RequestGridTileLookupMessage(gridId, indices));
}
private void HandleSentEntities(SendGridTileLookupMessage message)
{
if (!Enabled) return;
var text = new StringBuilder();
text.AppendLine($"GridId: {LastTile.Grid}, Tile: {LastTile.Indices}");
for (var i = 0; i < message.Entities.Count; i++)
{
var entity = message.Entities[i];
if (!EntityManager.EntityExists(entity)) continue;
text.AppendLine((string) EntityManager.ToPrettyString(entity));
}
_label.Text = text.ToString();
}
public override void FrameUpdate(float frameTime)
{
base.FrameUpdate(frameTime);
if (!Enabled) return;
var mousePos = _inputManager.MouseScreenPosition;
var worldPos = _eyeManager.ScreenToMap(mousePos);
GridId gridId;
Vector2i tile;
if (_mapManager.TryFindGridAt(worldPos, out var grid))
{
gridId = grid.Index;
tile = grid.WorldToTile(worldPos.Position);
}
else
{
gridId = GridId.Invalid;
tile = new Vector2i((int) MathF.Floor(worldPos.Position.X), (int) MathF.Floor(worldPos.Position.Y));
}
LayoutContainer.SetPosition(_label, mousePos.Position);
if ((gridId, tile).Equals(LastTile)) return;
_label.Text = null;
LastTile = (gridId, tile);
RequestEntities(gridId, tile);
}
}
internal sealed class RequestTileEntities : IConsoleCommand
{
public string Command => "tilelookup";
public string Description => "Used for debugging GridTileLookupSystem";
public string Help => $"{Command}";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
EntitySystem.Get<DebugGridTileLookupSystem>().Enabled ^= true;
}
}
}
#endif

View File

@@ -15,7 +15,7 @@ using Robust.Shared.Enums;
namespace Robust.Client.GameObjects
{
public class EffectSystem : EntitySystem
public sealed class EffectSystem : EntitySystem
{
[Dependency] private readonly IGameTiming gameTiming = default!;
[Dependency] private readonly IResourceCache resourceCache = default!;
@@ -94,7 +94,7 @@ namespace Robust.Client.GameObjects
}
}
private class Effect
private sealed class Effect
{
/// <summary>
/// Effect Sprite
@@ -347,11 +347,17 @@ namespace Robust.Client.GameObjects
if (_playerManager.LocalPlayer?.ControlledEntity is not {} playerEnt)
return;
var playerXform = _entityManager.GetComponent<TransformComponent>(playerEnt);
foreach (var effect in _owner._Effects)
{
if(effect.AttachedEntityUid is {} attached
&& _entityManager.GetComponent<TransformComponent>(attached).MapID != _entityManager.GetComponent<TransformComponent>(playerEnt).MapID
&& effect.Coordinates.GetMapId(_entityManager) != map)
TransformComponent? attachedXform = null;
if ((effect.AttachedEntityUid is {} attached &&
_entityManager.TryGetComponent(attached, out attachedXform) &&
attachedXform.MapID != playerXform.MapID) ||
(effect.AttachedEntityUid == null &&
effect.Coordinates.GetMapId(_entityManager) != map))
{
continue;
}
@@ -367,16 +373,17 @@ namespace Robust.Client.GameObjects
// TODO: Should be doing matrix transformations
var effectSprite = effect.EffectSprite;
var tempQualifier1 = effect.AttachedEntityUid;
var coordinates =
(tempQualifier1 != null ? _entityManager.GetComponent<TransformComponent>(tempQualifier1.Value).Coordinates : effect.Coordinates)
(attachedXform?.Coordinates ?? effect.Coordinates)
.Offset(effect.AttachedOffset);
var rotation = _entityManager.GetComponent<TransformComponent>(coordinates.EntityId).WorldRotation;
// ???
var rotation = attachedXform?.WorldRotation ?? _entityManager.GetComponent<TransformComponent>(coordinates.EntityId).WorldRotation;
var effectOrigin = coordinates.ToMapPos(_entityManager);
var effectArea = Box2.CenteredAround(effectOrigin, effect.Size);
var rotatedBox = new Box2Rotated(effectArea, effect.Rotation - rotation, effectOrigin);
var rotatedBox = new Box2Rotated(effectArea, effect.Rotation + rotation, effectOrigin);
worldHandle.DrawTextureRect(effectSprite, rotatedBox, ToColor(effect.Color));
}

View File

@@ -7,8 +7,10 @@ using Robust.Shared.GameObjects;
using Robust.Shared.Input;
using Robust.Shared.Input.Binding;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Timing;
#nullable enable
@@ -18,26 +20,8 @@ namespace Robust.Client.GameObjects
/// Updates the position of every Eye every frame, so that the camera follows the player around.
/// </summary>
[UsedImplicitly]
internal class EyeUpdateSystem : EntitySystem
public sealed class EyeUpdateSystem : EntitySystem
{
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
private TransformComponent? _lastParent;
private TransformComponent? _lerpTo;
private Angle LerpStartRotation;
private float _accumulator;
public bool IsLerping { get => _lerpTo != null; }
// How fast the camera rotates in radians / s
private const float CameraRotateSpeed = MathF.PI;
// PER THIS AMOUNT OF TIME MILLISECONDS
private const float CameraRotateTimeUnit = 1.2f;
// Safety override
private const float _lerpTimeMax = CameraRotateTimeUnit + 0.4f;
/// <inheritdoc />
public override void Initialize()
{
@@ -65,77 +49,6 @@ namespace Robust.Client.GameObjects
/// <inheritdoc />
public override void FrameUpdate(float frameTime)
{
var currentEye = _eyeManager.CurrentEye;
// TODO: Content should have its own way of handling this. We should have a default behavior that they can overwrite.
EntityUid tempQualifier = _playerManager.LocalPlayer?.ControlledEntity ?? EntityUid.Invalid;
var playerTransform = (tempQualifier != EntityUid.Invalid ? EntityManager.GetComponent<TransformComponent>(tempQualifier) : null);
if (playerTransform == null) return;
var gridId = playerTransform.GridID;
TransformComponent parent;
if (gridId != GridId.Invalid &&
_mapManager.GetGrid(gridId).GridEntityId is var gridEnt &&
EntityManager.EntityExists(gridEnt))
parent = EntityManager.GetComponent<TransformComponent>(gridEnt);
else
{
parent = EntityManager.GetComponent<TransformComponent>(
_mapManager.GetMapEntityId(playerTransform.MapID));
}
// Make sure that we don't fire the vomit carousel when we spawn in
if (_lastParent is null)
_lastParent = parent;
// Set a default for target rotation
var parentRotation = -parent.WorldRotation;
// Reuse current rotation when stepping into space
if (parent.GridID == GridId.Invalid)
parentRotation = currentEye.Rotation;
// Handle grid change in general
if (_lastParent != parent)
_lerpTo = parent;
// And we are up and running!
if (_lerpTo is not null)
{
// Handle a case where we have beeing spinning around, but suddenly got off onto a different grid
if (parent != _lerpTo) {
LerpStartRotation = currentEye.Rotation;
_lerpTo = parent;
_accumulator = 0f;
}
_accumulator += frameTime;
var changeNeeded = (float) (LerpStartRotation - parentRotation).Theta;
var changeLerp = _accumulator / (Math.Abs(changeNeeded % MathF.PI) / CameraRotateSpeed * CameraRotateTimeUnit);
currentEye.Rotation = Angle.Lerp(LerpStartRotation, parentRotation, changeLerp);
// Either we have overshot, or we have taken way too long on this, emergency reset time
if (changeLerp > 1.0f || _accumulator >= _lerpTimeMax)
{
_lastParent = parent;
_lerpTo = null;
_accumulator = 0f;
}
}
// We are just fine, or we finished a lerp (and probably overshot)
if (_lerpTo is null)
{
currentEye.Rotation = parentRotation;
LerpStartRotation = parentRotation;
}
foreach (var eyeComponent in EntityManager.EntityQuery<EyeComponent>(true))
{
eyeComponent.UpdateEyePosition();

View File

@@ -1,4 +1,3 @@
using System;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.GameObjects;
@@ -11,8 +10,12 @@ using Robust.Shared.Utility;
namespace Robust.Client.GameObjects
{
public class GridChunkBoundsDebugSystem : EntitySystem
public sealed class GridChunkBoundsDebugSystem : EntitySystem
{
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IOverlayManager _overlayManager = default!;
private GridChunkBoundsOverlay? _overlay;
public bool Enabled
@@ -29,14 +32,14 @@ namespace Robust.Client.GameObjects
DebugTools.Assert(_overlay == null);
_overlay = new GridChunkBoundsOverlay(
EntityManager,
IoCManager.Resolve<IEyeManager>(),
IoCManager.Resolve<IMapManager>());
_eyeManager,
_mapManager);
IoCManager.Resolve<IOverlayManager>().AddOverlay(_overlay);
_overlayManager.AddOverlay(_overlay);
}
else
{
IoCManager.Resolve<IOverlayManager>().RemoveOverlay(_overlay!);
_overlayManager.RemoveOverlay(_overlay!);
_overlay = null;
}
}
@@ -63,7 +66,7 @@ namespace Robust.Client.GameObjects
protected internal override void Draw(in OverlayDrawArgs args)
{
var currentMap = _eyeManager.CurrentMap;
var viewport = _eyeManager.GetWorldViewport();
var viewport = args.WorldBounds;
var worldHandle = args.WorldHandle;
foreach (var grid in _mapManager.FindGridsIntersecting(currentMap, viewport))

View File

@@ -2,6 +2,8 @@ using System;
using Robust.Client.GameStates;
using Robust.Client.Input;
using Robust.Client.Player;
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
using Robust.Shared.Input;
using Robust.Shared.IoC;
@@ -14,7 +16,7 @@ namespace Robust.Client.GameObjects
/// <summary>
/// Client-side processing of all input commands through the simulation.
/// </summary>
public class InputSystem : SharedInputSystem
public sealed class InputSystem : SharedInputSystem
{
[Dependency] private readonly IInputManager _inputManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
@@ -62,6 +64,9 @@ namespace Robust.Client.GameObjects
// handle local binds before sending off
foreach (var handler in BindRegistry.GetHandlers(function))
{
if (!_stateManager.IsPredictionEnabled && !handler.FireOutsidePrediction)
continue;
// local handlers can block sending over the network.
if (handler.HandleCmdMessage(session, message))
{
@@ -158,7 +163,7 @@ namespace Robust.Client.GameObjects
/// <summary>
/// Entity system message that is raised when the player changes attached entities.
/// </summary>
public class PlayerAttachSysMessage : EntityEventArgs
public sealed class PlayerAttachSysMessage : EntityEventArgs
{
/// <summary>
/// New entity the player is attached to.
@@ -175,7 +180,7 @@ namespace Robust.Client.GameObjects
}
}
public class PlayerAttachedEvent : EntityEventArgs
public sealed class PlayerAttachedEvent : EntityEventArgs
{
public PlayerAttachedEvent(EntityUid entity)
{
@@ -185,7 +190,7 @@ namespace Robust.Client.GameObjects
public EntityUid Entity { get; }
}
public class PlayerDetachedEvent : EntityEventArgs
public sealed class PlayerDetachedEvent : EntityEventArgs
{
public PlayerDetachedEvent(EntityUid entity)
{

View File

@@ -4,7 +4,7 @@ using Robust.Shared.IoC;
namespace Robust.Client.GameObjects
{
public class MidiSystem : EntitySystem
public sealed class MidiSystem : EntitySystem
{
[Dependency] private readonly IMidiManager _midiManager = default!;

View File

@@ -8,6 +8,7 @@ namespace Robust.Client.GameObjects
public sealed class PointLightSystem : SharedPointLightSystem
{
[Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly RenderingTreeSystem _renderingTreeSystem = default!;
public override void Initialize()
{
@@ -19,16 +20,14 @@ namespace Robust.Client.GameObjects
private void HandleInit(EntityUid uid, PointLightComponent component, ComponentInit args)
{
UpdateMask(component);
RaiseLocalEvent(uid, new PointLightUpdateEvent());
}
private void HandleRemove(EntityUid uid, PointLightComponent component, ComponentRemove args)
{
var map = EntityManager.GetComponent<TransformComponent>(uid).MapID;
// TODO: Just make this update the tree directly and not allocate
if (map != MapId.Nullspace)
if (Transform(uid).MapID != MapId.Nullspace)
{
EntityManager.EventBus.RaiseEvent(EventSource.Local,
new RenderTreeRemoveLightEvent(component, map));
_renderingTreeSystem.ClearLight(component);
}
}

View File

@@ -84,7 +84,6 @@ namespace Robust.Client.GameObjects
SubscribeLocalEvent<PointLightComponent, EntMapIdChangedMessage>(LightMapChanged);
SubscribeLocalEvent<PointLightComponent, EntParentChangedMessage>(LightParentChanged);
SubscribeLocalEvent<PointLightComponent, PointLightRadiusChangedEvent>(PointLightRadiusChanged);
SubscribeLocalEvent<PointLightComponent, RenderTreeRemoveLightEvent>(RemoveLight);
SubscribeLocalEvent<PointLightComponent, PointLightUpdateEvent>(HandleLightUpdate);
SubscribeLocalEvent<RenderingTreeComponent, ComponentInit>(OnTreeInit);
@@ -114,28 +113,31 @@ namespace Robust.Client.GameObjects
private void AnythingMoved(ref MoveEvent args)
{
AnythingMovedSubHandler(EntityManager.GetComponent<TransformComponent>(args.Sender));
var xforms = EntityManager.GetEntityQuery<TransformComponent>();
AnythingMovedSubHandler(args.Sender, xforms);
}
private void AnythingMovedSubHandler(TransformComponent sender)
private void AnythingMovedSubHandler(EntityUid uid, EntityQuery<TransformComponent> xforms)
{
// To avoid doing redundant updates (and we don't need to update a grid's children ever)
if (!_checkedChildren.Add(sender.Owner) ||
EntityManager.HasComponent<RenderingTreeComponent>(sender.Owner)) return;
if (!_checkedChildren.Add(uid) || EntityManager.HasComponent<RenderingTreeComponent>(uid)) return;
// This recursive search is needed, as MoveEvent is defined to not care about indirect events like children.
// WHATEVER YOU DO, DON'T REPLACE THIS WITH SPAMMING EVENTS UNLESS YOU HAVE A GUARANTEE IT WON'T LAG THE GC.
// (Struct-based events ok though)
// Ironically this was lagging the GC lolz
if (EntityManager.TryGetComponent(sender.Owner, out SpriteComponent? sprite))
if (EntityManager.TryGetComponent(uid, out SpriteComponent? sprite))
QueueSpriteUpdate(sprite);
if (EntityManager.TryGetComponent(sender.Owner, out PointLightComponent? light))
if (EntityManager.TryGetComponent(uid, out PointLightComponent? light))
QueueLightUpdate(light);
foreach (TransformComponent child in sender.Children)
if (!xforms.TryGetComponent(uid, out var xform)) return;
foreach (var child in xform.ChildEntities)
{
AnythingMovedSubHandler(child);
AnythingMovedSubHandler(child, xforms);
}
}
@@ -193,12 +195,7 @@ namespace Robust.Client.GameObjects
QueueLightUpdate(component);
}
private void RemoveLight(EntityUid uid, PointLightComponent component, RenderTreeRemoveLightEvent args)
{
ClearLight(component);
}
private void ClearLight(PointLightComponent component)
public void ClearLight(PointLightComponent component)
{
if (component.RenderTree == null) return;
@@ -253,23 +250,21 @@ namespace Robust.Client.GameObjects
EntityManager.EnsureComponent<RenderingTreeComponent>(_mapManager.GetGrid(gridId).GridEntityId);
}
// TODO: Pass in TransformComponent directly: mainly interested in getting this shit working atm.
private RenderingTreeComponent? GetRenderTree(EntityUid entity)
private RenderingTreeComponent? GetRenderTree(EntityUid entity, EntityQuery<TransformComponent> xforms)
{
var lookups = EntityManager.GetEntityQuery<RenderingTreeComponent>();
if (!EntityManager.EntityExists(entity) ||
!EntityManager.TryGetComponent(entity, out TransformComponent? xform) ||
!xforms.TryGetComponent(entity, out var xform) ||
xform.MapID == MapId.Nullspace ||
EntityManager.HasComponent<RenderingTreeComponent>(entity)) return null;
lookups.HasComponent(entity)) return null;
var parent = xform.ParentUid;
while (true)
while (parent.IsValid())
{
if (!parent.IsValid())
break;
if (EntityManager.TryGetComponent(parent, out RenderingTreeComponent? comp)) return comp;
parent = EntityManager.GetComponent<TransformComponent>(parent).ParentUid;
if (lookups.TryGetComponent(parent, out var comp)) return comp;
parent = xforms.GetComponent(parent).ParentUid;
}
return null;
@@ -284,6 +279,8 @@ namespace Robust.Client.GameObjects
{
_checkedChildren.Clear();
var xforms = EntityManager.GetEntityQuery<TransformComponent>();
foreach (var sprite in _spriteQueue)
{
sprite.TreeUpdateQueued = false;
@@ -294,9 +291,9 @@ namespace Robust.Client.GameObjects
}
var oldMapTree = sprite.RenderTree;
var newMapTree = GetRenderTree(sprite.Owner);
var newMapTree = GetRenderTree(sprite.Owner, xforms);
// TODO: Temp PVS guard
var xform = EntityManager.GetComponent<TransformComponent>(sprite.Owner);
var xform = xforms.GetComponent(sprite.Owner);
var (worldPos, worldRot) = xform.GetWorldPositionRotation();
if (float.IsNaN(worldPos.X) || float.IsNaN(worldPos.Y))
@@ -305,7 +302,7 @@ namespace Robust.Client.GameObjects
continue;
}
var aabb = SpriteAabbFunc(sprite, worldPos, worldRot);
var aabb = SpriteAabbFunc(sprite, worldPos, worldRot, xforms);
// If we're on a new map then clear the old one.
if (oldMapTree != newMapTree)
@@ -332,9 +329,9 @@ namespace Robust.Client.GameObjects
}
var oldMapTree = light.RenderTree;
var newMapTree = GetRenderTree(light.Owner);
var newMapTree = GetRenderTree(light.Owner, xforms);
// TODO: Temp PVS guard
var worldPos = EntityManager.GetComponent<TransformComponent>(light.Owner).WorldPosition;
var worldPos = xforms.GetComponent(light.Owner).WorldPosition;
if (float.IsNaN(worldPos.X) || float.IsNaN(worldPos.Y))
{
@@ -349,7 +346,7 @@ namespace Robust.Client.GameObjects
Logger.WarningS(LoggerSawmill, $"Light radius for {light.Owner} set above max radius of {MaxLightRadius}. This may lead to pop-in.");
}
var aabb = LightAabbFunc(light, worldPos);
var aabb = LightAabbFunc(light, worldPos, xforms);
// If we're on a new map then clear the old one.
if (oldMapTree != newMapTree)
@@ -371,82 +368,44 @@ namespace Robust.Client.GameObjects
private Box2 SpriteAabbFunc(in SpriteComponent value)
{
var xform = EntityManager.GetComponent<TransformComponent>(value.Owner);
var xforms = EntityManager.GetEntityQuery<TransformComponent>();
var xform = xforms.GetComponent(value.Owner);
var (worldPos, worldRot) = xform.GetWorldPositionRotation();
var bounds = new Box2Rotated(value.CalculateBoundingBox(worldPos), worldRot, worldPos);
var tree = GetRenderTree(value.Owner);
var tree = GetRenderTree(value.Owner, xforms);
if (tree == null)
{
return bounds.CalcBoundingBox();
}
else
{
return EntityManager.GetComponent<TransformComponent>(tree.Owner).InvWorldMatrix.TransformBox(bounds);
}
return tree == null ? bounds.CalcBoundingBox() : xforms.GetComponent(tree.Owner).InvWorldMatrix.TransformBox(bounds);
}
private Box2 LightAabbFunc(in PointLightComponent value)
{
var worldPos = EntityManager.GetComponent<TransformComponent>(value.Owner).WorldPosition;
var tree = GetRenderTree(value.Owner);
var xforms = EntityManager.GetEntityQuery<TransformComponent>();
var worldPos = xforms.GetComponent(value.Owner).WorldPosition;
var tree = GetRenderTree(value.Owner, xforms);
var boxSize = value.Radius * 2;
Vector2 localPos;
if (tree == null)
{
localPos = worldPos;
}
else
{
// TODO: Need a way to just cache this InvWorldMatrix
localPos = EntityManager.GetComponent<TransformComponent>(tree.Owner).InvWorldMatrix.Transform(worldPos);
}
var localPos = tree == null ? worldPos : xforms.GetComponent(tree.Owner).InvWorldMatrix.Transform(worldPos);
return Box2.CenteredAround(localPos, (boxSize, boxSize));
}
private Box2 SpriteAabbFunc(SpriteComponent value, Vector2 worldPos, Angle worldRot)
private Box2 SpriteAabbFunc(SpriteComponent value, Vector2 worldPos, Angle worldRot, EntityQuery<TransformComponent> xforms)
{
var bounds = new Box2Rotated(value.CalculateBoundingBox(worldPos), worldRot, worldPos);
var tree = GetRenderTree(value.Owner);
var tree = GetRenderTree(value.Owner, xforms);
if (tree == null)
{
return bounds.CalcBoundingBox();
}
else
{
return EntityManager.GetComponent<TransformComponent>(tree.Owner).InvWorldMatrix.TransformBox(bounds);
}
return tree == null ? bounds.CalcBoundingBox() : xforms.GetComponent(tree.Owner).InvWorldMatrix.TransformBox(bounds);
}
private Box2 LightAabbFunc(PointLightComponent value, Vector2 worldPos)
private Box2 LightAabbFunc(PointLightComponent value, Vector2 worldPos, EntityQuery<TransformComponent> xforms)
{
// Lights are circles so don't need entity's rotation
var tree = GetRenderTree(value.Owner);
var tree = GetRenderTree(value.Owner, xforms);
var boxSize = value.Radius * 2;
Vector2 localPos;
if (tree == null)
{
localPos = worldPos;
} else
{
localPos = EntityManager.GetComponent<TransformComponent>(tree.Owner).InvWorldMatrix.Transform(worldPos);
}
var localPos = tree == null ? worldPos : xforms.GetComponent(tree.Owner).InvWorldMatrix.Transform(worldPos);
return Box2.CenteredAround(localPos, (boxSize, boxSize));
}
}
internal class RenderTreeRemoveLightEvent : EntityEventArgs
{
public RenderTreeRemoveLightEvent(PointLightComponent light, MapId map)
{
Light = light;
Map = map;
}
public PointLightComponent Light { get; }
public MapId Map { get; }
}
}

View File

@@ -11,7 +11,7 @@ namespace Robust.Client.GameObjects
/// Updates the layer animation for every visible sprite.
/// </summary>
[UsedImplicitly]
public class SpriteSystem : EntitySystem
public sealed class SpriteSystem : EntitySystem
{
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly RenderingTreeSystem _treeSystem = default!;
@@ -53,9 +53,11 @@ namespace Robust.Client.GameObjects
return;
}
var xforms = EntityManager.GetEntityQuery<TransformComponent>();
foreach (var comp in _treeSystem.GetRenderTrees(currentMap, pvsBounds))
{
var bounds = EntityManager.GetComponent<TransformComponent>(comp.Owner).InvWorldMatrix.TransformBox(pvsBounds);
var bounds = xforms.GetComponent(comp.Owner).InvWorldMatrix.TransformBox(pvsBounds);
comp.SpriteTree.QueryAabb(ref frameTime, (ref float state, in SpriteComponent value) =>
{

View File

@@ -14,7 +14,7 @@ namespace Robust.Client.GameObjects
/// Handles interpolation of transform positions.
/// </summary>
[UsedImplicitly]
internal sealed class TransformSystem : SharedTransformSystem
public 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.

View File

@@ -8,7 +8,7 @@ using Robust.Shared.Maths;
namespace Robust.Client.GameObjects
{
public class VelocityDebugSystem : EntitySystem
public sealed class VelocityDebugSystem : EntitySystem
{
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;

View File

@@ -0,0 +1,20 @@
using Robust.Shared.GameObjects;
namespace Robust.Client.GameObjects;
/// <summary>
/// An abstract entity system inheritor for systems that deal with
/// appearance data, replacing <see cref="AppearanceVisualizer"/>.
/// </summary>
public abstract class VisualizerSystem<T> : EntitySystem
where T: Component
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<T, AppearanceChangeEvent>(OnAppearanceChange);
}
protected virtual void OnAppearanceChange(EntityUid uid, T component, ref AppearanceChangeEvent args) {}
}

Some files were not shown because too many files have changed in this diff Show More