Compare commits

...

276 Commits

Author SHA1 Message Date
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
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
Vera Aguilera Puerto
1032f10d85 Version 0.8.5 2021-12-11 15:32:31 +01:00
Vera Aguilera Puerto
4fc46ac814 Transform DetachParentToNull sets map to nullspace before raising the event. 2021-12-11 15:32:10 +01:00
Vera Aguilera Puerto
1611fb00d8 Version 0.8.4 2021-12-11 14:19:40 +01:00
Vera Aguilera Puerto
57a1f2743e Some minor PVS optimizations (#2324) 2021-12-11 14:17:38 +01:00
metalgearsloth
fd1a1d326c Fix broadphase RemoveBody issue (#2318) 2021-12-11 14:08:57 +01:00
metalgearsloth
ca7fdacfeb Make RunDeferred use worldpos+rot method (#2314) 2021-12-11 14:02:43 +01:00
Vera Aguilera Puerto
80f05d7467 Fix botched delete inline in EntityLookup 2021-12-11 12:38:32 +01:00
Paul Ritter
e84604f7e3 Fixes pvs culling & make budgets more granular (#2322) 2021-12-11 12:11:16 +01:00
Vera Aguilera Puerto
66c3013e39 VV EntityUid Name/Description setter.
For all your adminbus needs!
2021-12-10 11:53:00 +01:00
Vera Aguilera Puerto
717802fe54 Fix wrong grid placement direction when grid is rotated
Something to note is that grid placement is still very scuffed. On certain rotations, it begins acting weird.
2021-12-10 11:24:39 +01:00
Paul
977a840253 version bump 2021-12-10 10:17:25 +01:00
Paul
6051d4d358 removes statecache 2021-12-10 10:16:22 +01:00
Vera Aguilera Puerto
0a00a8a109 Fix build 2021-12-09 21:30:50 +01:00
wrexbe
9d1aff3a75 Fix NextMultipleOf for int/long (#2289) 2021-12-09 12:27:08 -08:00
E F R
3332279e75 SharedPhysicsSystem: convert parents' angular velocity to linear when leaving (#2208)
* SharedPhysicsSystem: convert parents' angular velocity to linear when leaving

Co-authored-by: ElectroJr <60421075+ElectroJr@users.noreply.github.com>
Co-authored-by: Tomeno <Tomeno@users.noreply.github.com>

* SharedPhysicsSystem: Use Center of Mass now that it supposedly works

* SharedPhysicsSystem: Use REAL MATH™ to handle rotation when reparenting

* SharedPhysicsSystem: Cache some reused matrices

Addresses:
https://github.com/space-wizards/RobustToolbox/pull/2208#discussion_r762503056
https://github.com/space-wizards/RobustToolbox/pull/2208#discussion_r762502704

* SharedPhysicsSystem: More caching, I guess

* SharedPhysicsSystem: save ONE WHOLE ACCESS

What's next, shortening variable names to make it load faster?

Co-authored-by: ElectroJr <60421075+ElectroJr@users.noreply.github.com>
Co-authored-by: Tomeno <Tomeno@users.noreply.github.com>
2021-12-09 12:18:37 -08:00
353 changed files with 8348 additions and 6862 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.2</Version></PropertyGroup>
<PropertyGroup><Version>0.8.45</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,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

@@ -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);
}
}

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

@@ -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;
@@ -40,6 +43,8 @@ namespace Robust.Client.Console
/// <inheritdoc cref="IClientConsoleHost" />
internal 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);

View File

@@ -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");
@@ -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();

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

@@ -11,7 +11,7 @@ using static Robust.Shared.Network.Messages.MsgScriptCompletionResponse;
namespace Robust.Client.Console
{
public class Completions : SS14Window
public class Completions : DefaultWindow
{
private HistoryLineEdit _textBar;
private ScrollContainer _suggestPanel = new()

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 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

@@ -207,7 +207,7 @@ 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)
@@ -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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -14,9 +14,6 @@ namespace Robust.Client.GameObjects
[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;
@@ -14,7 +14,6 @@ namespace Robust.Client.GameObjects
[RegisterComponent]
public 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;
@@ -10,9 +10,6 @@ namespace Robust.Client.GameObjects
/// </summary>
public 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

@@ -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;

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
);
@@ -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

@@ -19,15 +19,21 @@ namespace Robust.Client.GameObjects
while (_queuedUpdates.TryDequeue(out var appearance))
{
if (appearance.Deleted)
return;
foreach (var visualizer in appearance.Visualizers)
{
visualizer.OnChangeData(appearance);
}
continue;
OnChangeData(appearance.Owner, appearance);
appearance.UnmarkDirty();
}
}
public void OnChangeData(EntityUid uid, ClientAppearanceComponent? appearanceComponent = null)
{
if (!Resolve(uid, ref appearanceComponent, false)) return;
foreach (var visualizer in appearanceComponent.Visualizers)
{
visualizer.OnChangeData(appearanceComponent);
}
}
}
}

View File

@@ -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();

View File

@@ -72,7 +72,7 @@ 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;
@@ -85,7 +85,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

@@ -59,7 +59,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);

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

@@ -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 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;
@@ -13,6 +12,10 @@ namespace Robust.Client.GameObjects
{
public 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;
@@ -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))
{

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

@@ -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

@@ -7,7 +7,6 @@ using System.Linq;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.Input;
using Robust.Client.Map;
using Robust.Client.Player;
using Robust.Client.Timing;
using Robust.Shared;
@@ -50,7 +49,7 @@ namespace Robust.Client.GameStates
[Dependency] private readonly IPlayerManager _players = default!;
[Dependency] private readonly IClientNetManager _network = default!;
[Dependency] private readonly IBaseClient _client = default!;
[Dependency] private readonly IClientMapManager _mapManager = default!;
[Dependency] private readonly INetworkedMapManager _mapManager = default!;
[Dependency] private readonly IClientGameTiming _timing = default!;
[Dependency] private readonly INetConfigurationManager _config = default!;
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
@@ -60,6 +59,8 @@ namespace Robust.Client.GameStates
[Dependency] private readonly IRuntimeLog _runtimeLog = default!;
#endif
private ISawmill _sawmill = default!;
/// <inheritdoc />
public int MinBufferSize => _processor.MinBufferSize;
@@ -69,7 +70,7 @@ namespace Robust.Client.GameStates
/// <inheritdoc />
public int CurrentBufferSize => _processor.CalculateBufferSize(CurServerTick);
public bool Predicting { get; private set; }
public bool IsPredictionEnabled { get; private set; }
public int PredictTickBias { get; private set; }
public float PredictLagBias { get; private set; }
@@ -87,6 +88,7 @@ namespace Robust.Client.GameStates
/// <inheritdoc />
public void Initialize()
{
_sawmill = Logger.GetSawmill(CVars.NetPredict.Name);
_processor = new GameStateProcessor(_timing);
_network.RegisterNetMessage<MsgState>(HandleStateMessage);
@@ -96,7 +98,7 @@ namespace Robust.Client.GameStates
_config.OnValueChanged(CVars.NetInterp, b => _processor.Interpolation = b, true);
_config.OnValueChanged(CVars.NetInterpRatio, i => _processor.InterpRatio = i, true);
_config.OnValueChanged(CVars.NetLogging, b => _processor.Logging = b, true);
_config.OnValueChanged(CVars.NetPredict, b => Predicting = b, true);
_config.OnValueChanged(CVars.NetPredict, b => IsPredictionEnabled = b, true);
_config.OnValueChanged(CVars.NetPredictTickBias, i => PredictTickBias = i, true);
_config.OnValueChanged(CVars.NetPredictLagBias, i => PredictLagBias = i, true);
_config.OnValueChanged(CVars.NetStateBufMergeThreshold, i => StateBufferMergeThreshold = i, true);
@@ -104,7 +106,7 @@ namespace Robust.Client.GameStates
_processor.Interpolation = _config.GetCVar(CVars.NetInterp);
_processor.InterpRatio = _config.GetCVar(CVars.NetInterpRatio);
_processor.Logging = _config.GetCVar(CVars.NetLogging);
Predicting = _config.GetCVar(CVars.NetPredict);
IsPredictionEnabled = _config.GetCVar(CVars.NetPredict);
PredictTickBias = _config.GetCVar(CVars.NetPredictTickBias);
PredictLagBias = _config.GetCVar(CVars.NetPredictLagBias);
@@ -135,7 +137,7 @@ namespace Robust.Client.GameStates
public void InputCommandDispatched(FullInputCmdMessage message)
{
if (!Predicting)
if (!IsPredictionEnabled)
{
return;
}
@@ -144,14 +146,14 @@ namespace Robust.Client.GameStates
_pendingInputs.Enqueue(message);
_inputManager.NetworkBindMap.TryGetKeyFunction(message.InputFunctionId, out var boundFunc);
Logger.DebugS(CVars.NetPredict.Name,
_sawmill.Debug(
$"CL> SENT tick={_timing.CurTick}, sub={_timing.TickFraction}, seq={_nextInputCmdSeq}, func={boundFunc.FunctionName}, state={message.State}");
_nextInputCmdSeq++;
}
public uint SystemMessageDispatched<T>(T message) where T : EntityEventArgs
{
if (!Predicting)
if (!IsPredictionEnabled)
{
return default;
}
@@ -214,7 +216,7 @@ namespace Robust.Client.GameStates
// TODO: If Predicting gets disabled *while* the world state is dirty from a prediction,
// this won't run meaning it could potentially get stuck dirty.
if (Predicting && i == 0)
if (IsPredictionEnabled && i == 0)
{
// Disable IsFirstTimePredicted while re-running HandleComponentState here.
// Helps with debugging.
@@ -238,7 +240,7 @@ namespace Robust.Client.GameStates
if (_lastProcessedSeq < curState.LastProcessedInput)
{
Logger.DebugS(CVars.NetPredict.Name, $"SV> RCV tick={_timing.CurTick}, seq={_lastProcessedSeq}");
_sawmill.Debug($"SV> RCV tick={_timing.CurTick}, seq={_lastProcessedSeq}");
_lastProcessedSeq = curState.LastProcessedInput;
}
}
@@ -257,8 +259,7 @@ namespace Robust.Client.GameStates
var inCmd = _pendingInputs.Dequeue();
_inputManager.NetworkBindMap.TryGetKeyFunction(inCmd.InputFunctionId, out var boundFunc);
Logger.DebugS(CVars.NetPredict.Name,
$"SV> seq={inCmd.InputSequence}, func={boundFunc.FunctionName}, state={inCmd.State}");
_sawmill.Debug($"SV> seq={inCmd.InputSequence}, func={boundFunc.FunctionName}, state={inCmd.State}");
}
while (_pendingSystemMessages.Count > 0 && _pendingSystemMessages.Peek().sequence <= _lastProcessedSeq)
@@ -268,13 +269,13 @@ namespace Robust.Client.GameStates
DebugTools.Assert(_timing.InSimulation);
if (Predicting)
if (IsPredictionEnabled)
{
using var _ = _timing.StartPastPredictionArea();
if (_pendingInputs.Count > 0)
{
Logger.DebugS(CVars.NetPredict.Name, "CL> Predicted:");
_sawmill.Debug("CL> Predicted:");
}
var pendingInputEnumerator = _pendingInputs.GetEnumerator();
@@ -299,7 +300,7 @@ namespace Robust.Client.GameStates
_inputManager.NetworkBindMap.TryGetKeyFunction(inputCmd.InputFunctionId, out var boundFunc);
Logger.DebugS(CVars.NetPredict.Name,
_sawmill.Debug(
$" seq={inputCmd.InputSequence}, sub={inputCmd.SubTick}, dTick={tick}, func={boundFunc.FunctionName}, " +
$"state={inputCmd.State}");
@@ -324,28 +325,34 @@ namespace Robust.Client.GameStates
// Don't run EntitySystemManager.TickUpdate if this is the target tick,
// because the rest of the main loop will call into it with the target tick later,
// and it won't be a past prediction.
_entitySystemManager.TickUpdate((float) _timing.TickPeriod.TotalSeconds);
_entitySystemManager.TickUpdate((float) _timing.TickPeriod.TotalSeconds, noPredictions: false);
((IBroadcastEventBusInternal) _entities.EventBus).ProcessEventQueue();
}
}
}
_entities.TickUpdate((float) _timing.TickPeriod.TotalSeconds);
_entities.TickUpdate((float) _timing.TickPeriod.TotalSeconds, noPredictions: !IsPredictionEnabled);
_lookup.Update();
}
private void ResetPredictedEntities(GameTick curTick)
{
foreach (var entity in _entities.GetEntities())
foreach (var meta in _entityManager.EntityQuery<MetaDataComponent>(true))
{
var entity = meta.Owner;
// TODO: 99% there's an off-by-one here.
if (entity.IsClientSide() || _entityManager.GetComponent<MetaDataComponent>(entity).EntityLastModifiedTick < curTick)
if (entity.IsClientSide() || meta.EntityLastModifiedTick < curTick)
{
continue;
}
Logger.DebugS(CVars.NetPredict.Name, $"Entity {entity} was made dirty.");
// Check log level first to avoid the string alloc.
if (_sawmill.Level <= LogLevel.Debug)
{
_sawmill.Debug($"Entity {entity} was made dirty.");
}
if (!_processor.TryGetLastServerStates(entity, out var last))
{
@@ -363,7 +370,7 @@ namespace Robust.Client.GameStates
continue;
}
Logger.DebugS(CVars.NetPredict.Name, $" And also its component {comp.Name}");
_sawmill.Debug($" And also its component {comp.GetType()}");
// TODO: Handle interpolation.
var handleState = new ComponentHandleState(compState, null);
_entities.EventBus.RaiseComponentEvent(comp, ref handleState);
@@ -429,8 +436,6 @@ namespace Robust.Client.GameStates
var toApply = new Dictionary<EntityUid, (EntityState?, EntityState?)>();
var toInitialize = new List<EntityUid>();
var created = new List<EntityUid>();
var toHide = new List<EntityUid>();
var toShow = new List<EntityUid>();
foreach (var es in curEntStates)
{
@@ -440,9 +445,6 @@ namespace Robust.Client.GameStates
{
// Logger.Debug($"[{IGameTiming.TickStampStatic}] MOD {es.Uid}");
toApply.Add(uid, (es, null));
if(_hiddenEntities.ContainsKey(uid))
toShow.Add(uid);
uid = es.Uid;
}
else //Unknown entities
{
@@ -456,10 +458,7 @@ namespace Robust.Client.GameStates
toApply.Add(newEntity, (es, null));
toInitialize.Add(newEntity);
created.Add(newEntity);
uid = newEntity;
}
if(es.Hide)
toHide.Add(uid);
}
foreach (var es in nextEntStates)
@@ -542,21 +541,6 @@ namespace Robust.Client.GameStates
}
#endif
foreach (var entityUid in toHide)
{
if(_entityManager.HasComponent<MapGridComponent>(entityUid)) continue;
var xform = _entityManager.GetComponent<TransformComponent>(entityUid);
_hiddenEntities.Add(entityUid, xform.MapID);
xform.ChangeMapId(MapId.Nullspace);
}
foreach (var entityUid in toShow)
{
_entityManager.GetComponent<TransformComponent>(entityUid).ChangeMapId(_hiddenEntities[entityUid]);
_hiddenEntities.Remove(entityUid);
}
return created;
}
@@ -626,7 +610,7 @@ namespace Robust.Client.GameStates
catch (Exception e)
{
var wrapper = new ComponentStateApplyException(
$"Failed to apply comp state: entity={component.Owner}, comp={component.Name}", e);
$"Failed to apply comp state: entity={component.Owner}, comp={component.GetType()}", e);
#if EXCEPTION_TOLERANCE
_runtimeLog.LogException(wrapper, "Component state apply");
#else

View File

@@ -1,4 +1,5 @@
using System;
using Robust.Shared;
using Robust.Shared.GameObjects;
using Robust.Shared.Input;
using Robust.Shared.Timing;
@@ -44,6 +45,13 @@ namespace Robust.Client.GameStates
/// </summary>
int StateBufferMergeThreshold { get; }
/// <summary>
/// Whether prediction is currently enabled on the client entirely.
/// This is NOT equal to <see cref="IGameTiming.InPrediction"/> or <see cref="IGameTiming.IsFirstTimePredicted"/>.
/// </summary>
/// <remarks>This is effectively an alias of <see cref="CVars.NetPredict"/>.</remarks>
bool IsPredictionEnabled { get; }
/// <summary>
/// This is called after the game state has been applied for the current tick.
/// </summary>

View File

@@ -38,7 +38,7 @@ namespace Robust.Client.GameStates
var transform = _entityManager.GetComponent<TransformComponent>(boundingBox.Owner);
// if not on the same map, continue
if (transform.MapID != _eyeManager.CurrentMap || boundingBox.Owner.IsInContainer())
if (transform.MapID != _eyeManager.CurrentMap || boundingBox.Owner.IsInContainer(_entityManager))
continue;
// This entity isn't lerping, no need to draw debug info for it

View File

@@ -1,4 +1,4 @@
using JetBrains.Annotations;
using JetBrains.Annotations;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
@@ -31,5 +31,14 @@ namespace Robust.Client.Graphics
/// Our sub region within our source, in pixel coordinates.
/// </summary>
public UIBox2 SubRegion { get; }
public override Color GetPixel(int x, int y)
{
DebugTools.Assert(x < SubRegion.Right);
DebugTools.Assert(y < SubRegion.Top);
int xTranslated = x + (int) SubRegion.Left;
int yTranslated = y + (int) SubRegion.Top;
return this.SourceTexture[xTranslated, yTranslated];
}
}
}

View File

@@ -215,9 +215,16 @@ namespace Robust.Client.Graphics.Audio
_openALSawmill.Info($"Set audio attenuation to {attToString.ToString()}");
}
public IClydeAudioSource CreateAudioSource(AudioStream stream)
public IClydeAudioSource? CreateAudioSource(AudioStream stream)
{
var source = AL.GenSource();
if (!AL.IsSource(source))
{
_openALSawmill.Error("Failed to generate source. Too many simultaneous audio streams?");
return null;
}
// ReSharper disable once PossibleInvalidOperationException
// TODO: This really shouldn't be indexing based on the ClydeHandle...
AL.Source(source, ALSourcei.Buffer, _audioSampleBuffers[(int) stream.ClydeHandle!.Value.Value].BufferHandle);

View File

@@ -54,7 +54,7 @@ namespace Robust.Client.Graphics.Audio
return ActualImplementation.LoadAudioRaw(samples, channels, sampleRate, name);
}
public IClydeAudioSource CreateAudioSource(AudioStream stream)
public IClydeAudioSource? CreateAudioSource(AudioStream stream)
{
return ActualImplementation.CreateAudioSource(stream);
}

View File

@@ -32,14 +32,20 @@ namespace Robust.Client.Graphics
public IEye CurrentEye
{
get => _currentEye ?? _defaultEye;
set => _currentEye = value;
set
{
var old = _currentEye;
_currentEye = value;
_entityManager.EventBus.RaiseEvent(EventSource.Local, new CurrentEyeChangedEvent(old, _currentEye));
}
}
public IViewportControl MainViewport { get; set; } = default!;
public void ClearCurrentEye()
{
_currentEye = _defaultEye;
CurrentEye = _defaultEye;
}
void IEyeManager.Initialize()
@@ -146,4 +152,16 @@ namespace Robust.Client.Graphics
return MainViewport.ScreenToMap(point);
}
}
public class CurrentEyeChangedEvent : EntityEventArgs
{
public IEye? Old { get; }
public IEye New { get; }
public CurrentEyeChangedEvent(IEye? oldEye, IEye newEye)
{
Old = oldEye;
New = newEye;
}
}
}

View File

@@ -31,7 +31,6 @@ namespace Robust.Client.Graphics.Clyde
}
}
/*
if (_cfg.GetCVar(CVars.DisplayEgl))
{
_sawmillOgl.Debug("Trying EGL");
@@ -40,7 +39,6 @@ namespace Robust.Client.Graphics.Clyde
_glContext = ctxEgl;
return;
}
*/
}
/*

View File

@@ -38,6 +38,7 @@ namespace Robust.Client.Graphics.Clyde
// These are set from Clyde.Windowing.
private bool _isGLES;
private bool _isGLES2;
private bool _isCore;
[SuppressMessage("ReSharper", "UnusedParameter.Local")]

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;

View File

@@ -372,22 +372,24 @@ namespace Robust.Client.Graphics.Clyde
private void ProcessSpriteEntities(MapId map, Matrix3 eyeMatrix, Box2Rotated worldBounds,
RefList<(SpriteComponent sprite, Matrix3 matrix, Angle worldRot, float yWorldPos)> list)
{
var xforms = _entityManager.GetEntityQuery<TransformComponent>();
foreach (var comp in _entitySystemManager.GetEntitySystem<RenderingTreeSystem>().GetRenderTrees(map, worldBounds))
{
var bounds = _entityManager.GetComponent<TransformComponent>(comp.Owner).InvWorldMatrix.TransformBox(worldBounds);
var bounds = xforms.GetComponent(comp.Owner).InvWorldMatrix.TransformBox(worldBounds);
comp.SpriteTree.QueryAabb(ref list, (
ref RefList<(SpriteComponent sprite, Matrix3 matrix, Angle worldRot, float yWorldPos)> state,
in SpriteComponent value) =>
{
var entity = value.Owner;
var transform = _entityManager.GetComponent<TransformComponent>(entity);
var transform = xforms.GetComponent(entity);
ref var entry = ref state.AllocAdd();
entry.sprite = value;
entry.worldRot = transform.WorldRotation;
entry.matrix = transform.WorldMatrix;
var eyePos = eyeMatrix.Transform(new Vector2(entry.matrix.R0C2, entry.matrix.R1C2));
Vector2 worldPos;
(worldPos, entry.worldRot, entry.matrix) = transform.GetWorldPositionRotationMatrix();
var eyePos = eyeMatrix.Transform(worldPos);
// Didn't use the bounds from the query as that has to be re-calculated (and is probably more expensive than this).
var bounds = value.CalculateBoundingBox(eyePos);
entry.yWorldPos = eyePos.Y - bounds.Extents.Y;
@@ -403,12 +405,15 @@ namespace Robust.Client.Graphics.Clyde
ClearFramebuffer(Color.Black);
var splashTex = _cfg.GetCVar(CVars.DisplaySplashLogo);
if (string.IsNullOrEmpty(splashTex))
return;
var texture = _resourceCache.GetResource<TextureResource>(splashTex).Texture;
handle.DrawingHandleScreen.DrawTexture(texture, (ScreenSize - texture.Size) / 2);
}
private void RenderInRenderTarget(RenderTargetBase rt, Action a, Color clearColor=default)
private void RenderInRenderTarget(RenderTargetBase rt, Action a, Color? clearColor=default)
{
// TODO: for the love of god all this state pushing/popping needs to be cleaned up.
@@ -422,7 +427,8 @@ namespace Robust.Client.Graphics.Clyde
{
BindRenderTargetFull(RtToLoaded(rt));
ClearFramebuffer(clearColor);
if (clearColor is not null)
ClearFramebuffer(clearColor.Value);
SetViewportImmediate(Box2i.FromDimensions(Vector2i.Zero, rt.Size));
_updateUniformConstants(rt.Size);
CalcScreenMatrices(rt.Size, out var proj, out var view);
@@ -524,7 +530,7 @@ namespace Robust.Client.Graphics.Clyde
RenderOverlays(viewport, OverlaySpace.WorldSpace, worldAABB, worldBounds);
_currentViewport = oldVp;
});
}, viewport.ClearColor);
}
private static Box2 CalcWorldAABB(Viewport viewport)

View File

@@ -62,7 +62,7 @@ namespace Robust.Client.Graphics.Clyde
PixelInternalFormat.Srgb8Alpha8 => 4,
PixelInternalFormat.R11fG11fB10f => 4,
PixelInternalFormat.R32f => 4,
PixelInternalFormat.Rg32f => 4,
PixelInternalFormat.Rg32f => 8,
PixelInternalFormat.R8 => 1,
_ => 0
};

View File

@@ -515,10 +515,11 @@ namespace Robust.Client.Graphics.Clyde
// Use worldbounds for this one as we only care if the light intersects our actual bounds
var state = (this, worldAABB, count: 0);
var xforms = _entityManager.GetEntityQuery<TransformComponent>();
foreach (var comp in renderingTreeSystem.GetRenderTrees(map, enlargedBounds))
{
var bounds = _entityManager.GetComponent<TransformComponent>(comp.Owner).InvWorldMatrix.TransformBox(worldBounds);
var bounds = xforms.GetComponent(comp.Owner).InvWorldMatrix.TransformBox(worldBounds);
comp.LightTree.QueryAabb(ref state, (ref (Clyde clyde, Box2 worldAABB, int count) state, in PointLightComponent light) =>
{
@@ -528,7 +529,7 @@ namespace Robust.Client.Graphics.Clyde
return false;
}
var transform = _entityManager.GetComponent<TransformComponent>(light.Owner);
var transform = xforms.GetComponent(light.Owner);
if (float.IsNaN(transform.LocalPosition.X) || float.IsNaN(transform.LocalPosition.Y)) return true;
@@ -871,21 +872,24 @@ namespace Robust.Client.Graphics.Clyde
var ii = 0;
var imi = 0;
var xforms = _entityManager.GetEntityQuery<TransformComponent>();
foreach (var comp in occluderSystem.GetOccluderTrees(map, expandedBounds))
{
var treeBounds = _entityManager.GetComponent<TransformComponent>(comp.Owner).InvWorldMatrix.TransformBox(expandedBounds);
var treeBounds = xforms.GetComponent(comp.Owner).InvWorldMatrix.TransformBox(expandedBounds);
comp.Tree.QueryAabb((in OccluderComponent sOccluder) =>
{
var occluder = (ClientOccluderComponent)sOccluder;
var transform = _entityManager.GetComponent<TransformComponent>(occluder.Owner);
if (!occluder.Enabled)
var transform = xforms.GetComponent(sOccluder.Owner);
if (!sOccluder.Enabled)
{
return true;
}
var occluder = (ClientOccluderComponent)sOccluder;
var worldTransform = transform.WorldMatrix;
var box = occluder.BoundingBox;
var box = sOccluder.BoundingBox;
var tl = worldTransform.Transform(box.TopLeft);
var tr = worldTransform.Transform(box.TopRight);

View File

@@ -44,7 +44,8 @@ namespace Robust.Client.Graphics.Clyde
// Cache currently bound framebuffers
// so if somebody creates a framebuffer while drawing it won't ruin everything.
// Note that this means _currentBoundRenderTarget goes temporarily out of sync here
var boundDrawBuffer = GL.GetInteger(GetPName.DrawFramebufferBinding);
var boundDrawBuffer = GL.GetInteger(
_isGLES2 ? GetPName.FramebufferBinding : GetPName.DrawFramebufferBinding);
var boundReadBuffer = 0;
if (_hasGLReadFramebuffer)
{
@@ -102,18 +103,29 @@ namespace Robust.Client.Graphics.Clyde
// Make sure to specify the correct pixel type and formats even if we're not uploading any data.
// Not doing this (just sending red/byte) is fine on desktop GL but illegal on ES.
// @formatter:off
var (internalFormat, pixFormat, pixType) = colorFormat switch
{
// using block comments to force formatters to not fuck this up.
RTCF.Rgba8 => /* */(PIF.Rgba8, /* */PF.Rgba, /**/PT.UnsignedByte),
RTCF.Rgba16F => /* */(PIF.Rgba16f, /* */PF.Rgba, /**/PT.Float),
RTCF.Rgba8Srgb => /* */(PIF.Srgb8Alpha8, /* */PF.Rgba, /**/PT.UnsignedByte),
RTCF.R11FG11FB10F => /**/(PIF.R11fG11fB10f, /**/PF.Rgb, /* */PT.Float),
RTCF.R32F => /* */(PIF.R32f, /* */PF.Red, /* */PT.Float),
RTCF.RG32F => /* */(PIF.Rg32f, /* */PF.Rg, /* */PT.Float),
RTCF.R8 => /* */(PIF.R8, /* */PF.Red, /* */PT.UnsignedByte),
RTCF.Rgba8 => (PIF.Rgba8, PF.Rgba, PT.UnsignedByte),
RTCF.Rgba16F => (PIF.Rgba16f, PF.Rgba, PT.Float),
RTCF.Rgba8Srgb => (PIF.Srgb8Alpha8, PF.Rgba, PT.UnsignedByte),
RTCF.R11FG11FB10F => (PIF.R11fG11fB10f, PF.Rgb, PT.Float),
RTCF.R32F => (PIF.R32f, PF.Red, PT.Float),
RTCF.RG32F => (PIF.Rg32f, PF.Rg, PT.Float),
RTCF.R8 => (PIF.R8, PF.Red, PT.UnsignedByte),
_ => throw new ArgumentOutOfRangeException(nameof(format.ColorFormat), format.ColorFormat, null)
};
// @formatter:on
if (_isGLES2)
{
(internalFormat, pixFormat, pixType) = colorFormat switch
{
RTCF.Rgba8 => (PIF.Rgba, PF.Rgba, PT.UnsignedByte),
RTCF.R8 => (PIF.Rgba, PF.Rgba, PT.UnsignedByte),
_ => throw new ArgumentOutOfRangeException(nameof(format.ColorFormat), format.ColorFormat, null)
};
}
estPixSize += EstPixelSize(internalFormat);
@@ -169,7 +181,9 @@ namespace Robust.Client.Graphics.Clyde
$"new framebuffer has bad status {status}");
// Re-bind previous framebuffers (thus _currentBoundRenderTarget is back in sync)
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, boundDrawBuffer);
GL.BindFramebuffer(
_isGLES2 ? FramebufferTarget.Framebuffer : FramebufferTarget.DrawFramebuffer,
boundDrawBuffer);
CheckGlError();
if (_hasGLReadFramebuffer)
{
@@ -273,11 +287,7 @@ namespace Robust.Client.Graphics.Clyde
public Vector2i Size;
public bool IsSrgb;
#pragma warning disable 649
// Gets assigned by (currently commented out) GLContextAngle.
// It's fine don't worry about it.
public bool FlipY;
#pragma warning restore 649
public RTCF ColorFormat;

View File

@@ -52,11 +52,11 @@ namespace Robust.Client.Graphics.Clyde
public StencilParameters Stencil = StencilParameters.Default;
}
public ClydeHandle LoadShader(ParsedShader shader, string? name = null)
public ClydeHandle LoadShader(ParsedShader shader, string? name = null, Dictionary<string,string>? defines = null)
{
var (vertBody, fragBody) = GetShaderCode(shader);
var program = _compileProgram(vertBody, fragBody, BaseShaderAttribLocations, name);
var program = _compileProgram(vertBody, fragBody, BaseShaderAttribLocations, name, defines: defines);
if (_hasGLUniformBuffers)
{
@@ -141,7 +141,7 @@ namespace Robust.Client.Graphics.Clyde
}
private GLShaderProgram _compileProgram(string vertexSource, string fragmentSource,
(string, uint)[] attribLocations, string? name = null, bool includeLib=true)
(string, uint)[] attribLocations, string? name = null, bool includeLib=true, Dictionary<string,string>? defines=null)
{
GLShader? vertexShader = null;
GLShader? fragmentShader = null;
@@ -186,6 +186,14 @@ namespace Robust.Client.Graphics.Clyde
versionHeader += "#define HAS_UNIFORM_BUFFERS\n";
}
if (defines is not null)
{
foreach (var k in defines.Keys)
{
versionHeader += $"#define {k} {defines[k]}\n";
}
}
var lib = includeLib ? _shaderLibrary : "";
vertexSource = versionHeader + "#define VERTEX_SHADER\n" + lib + vertexSource;
fragmentSource = versionHeader + "#define FRAGMENT_SHADER\n" + lib + fragmentSource;

View File

@@ -2,6 +2,7 @@ using System;
using System.Buffers;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
@@ -11,6 +12,7 @@ using Robust.Shared.Maths;
using Robust.Shared.Utility;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using Color = Robust.Shared.Maths.Color;
using OGLTextureWrapMode = OpenToolkit.Graphics.OpenGL.TextureWrapMode;
using PIF = OpenToolkit.Graphics.OpenGL4.PixelInternalFormat;
using PF = OpenToolkit.Graphics.OpenGL4.PixelFormat;
@@ -146,7 +148,7 @@ namespace Robust.Client.Graphics.Clyde
CheckGlError();
ApplySampleParameters(loadParams.SampleParameters);
var (pif, _, _) = PixelEnums<T>(loadParams.Srgb);
var (pif, pf, pt) = PixelEnums<T>(loadParams.Srgb);
var pixelType = typeof(T);
var texPixType = GetTexturePixelType<T>();
var isActuallySrgb = false;
@@ -255,6 +257,16 @@ namespace Robust.Client.Graphics.Clyde
private (PIF pif, PF pf, PT pt) PixelEnums<T>(bool srgb)
where T : unmanaged, IPixel<T>
{
if (_isGLES2)
{
return default(T) switch
{
Rgba32 => (PIF.Rgba, PF.Rgba, PT.UnsignedByte),
L8 => (PIF.Luminance, PF.Red, PT.UnsignedByte),
_ => throw new NotSupportedException("Unsupported pixel type."),
};
}
return default(T) switch
{
// Note that if _hasGLSrgb is off, we import an sRGB texture as non-sRGB.
@@ -633,6 +645,25 @@ namespace Robust.Client.Graphics.Clyde
return $"ClydeTexture: ({TextureId})";
}
public override Color GetPixel(int x, int y)
{
if (!_clyde._loadedTextures.TryGetValue(TextureId, out var loaded))
{
throw new DataException("Texture not found");
}
Span<byte> rgba = stackalloc byte[4];
unsafe
{
fixed (byte* p = rgba)
{
GL.GetTextureImage(loaded.OpenGLObject.Handle, 0, PF.Rgba, PT.UnsignedByte, 4, (IntPtr) p);
}
}
return new Color(rgba[0], rgba[1], rgba[2], rgba[3]);
}
}
public Texture GetStockTexture(ClydeStockTexture stockTexture)

View File

@@ -112,6 +112,7 @@ namespace Robust.Client.Graphics.Clyde
}
public Vector2i Size { get; set; }
public Color? ClearColor { get; set; } = Color.Black;
public Vector2 RenderScale { get; set; } = Vector2.One;
public bool AutomaticRender { get; set; }
@@ -143,7 +144,7 @@ namespace Robust.Client.Graphics.Clyde
if (Eye == null)
return default;
var eye = (IEye) Eye;
var eye = Eye;
var newPoint = point;
eye.GetViewMatrix(out var viewMatrix, RenderScale);

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Threading.Tasks;
using OpenToolkit.Graphics.OpenGL4;
using Robust.Client.Input;
using Robust.Client.UserInterface;
using Robust.Shared;
@@ -13,8 +12,9 @@ using Robust.Shared.Maths;
using Robust.Shared.Utility;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using static Robust.Client.Utility.Win32;
using TerraFX.Interop.Windows;
using FrameEventArgs = Robust.Shared.Timing.FrameEventArgs;
using GL = OpenToolkit.Graphics.OpenGL4.GL;
namespace Robust.Client.Graphics.Clyde
{
@@ -204,10 +204,14 @@ namespace Robust.Client.Graphics.Clyde
"or enable compatibility mode in the launcher if that fails.\n" +
$"The exact error is: {lastError}";
MessageBoxW(null,
msgBoxContent,
"Space Station 14: Failed to create window",
MB_OK | MB_ICONERROR);
fixed (char* pText = msgBoxContent)
fixed (char* pCaption = "RobustToolbox: Failed to create window")
{
Windows.MessageBoxW(HWND.NULL,
(ushort*) pText,
(ushort*) pCaption,
MB.MB_OK | MB.MB_ICONERROR);
}
}
Logger.FatalS("clyde.win",

View File

@@ -159,6 +159,7 @@ namespace Robust.Client.Graphics.Clyde
private void InitOpenGL()
{
_isGLES = _openGLVersion is RendererOpenGLVersion.GLES2 or RendererOpenGLVersion.GLES3;
_isGLES2 = _openGLVersion is RendererOpenGLVersion.GLES2;
_isCore = _openGLVersion is RendererOpenGLVersion.GL33;
GLInitBindings(_isGLES);

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
@@ -221,7 +221,7 @@ namespace Robust.Client.Graphics.Clyde
return window;
}
public ClydeHandle LoadShader(ParsedShader shader, string? name = null)
public ClydeHandle LoadShader(ParsedShader shader, string? name = null, Dictionary<string,string>? defines = null)
{
return default;
}
@@ -383,6 +383,11 @@ namespace Robust.Client.Graphics.Clyde
{
// Just do nothing on mutate.
}
public override Color GetPixel(int x, int y)
{
return Color.Black;
}
}
private sealed class DummyShaderInstance : ShaderInstance
@@ -540,6 +545,7 @@ namespace Robust.Client.Graphics.Clyde
public IEye? Eye { get; set; }
public Vector2i Size { get; }
public Color? ClearColor { get; set; } = Color.Black;
public Vector2 RenderScale { get; set; }
public bool AutomaticRender { get; set; }

View File

@@ -40,7 +40,6 @@ namespace Robust.Client.Graphics.Clyde
private IDXGIFactory1* _factory;
private IDXGIAdapter1* _adapter;
private ID3D11Device* _device;
private ID3D11DeviceContext* _deviceContext;
private D3D_FEATURE_LEVEL _deviceFl;
private void* _eglDevice;
private void* _eglDisplay;
@@ -320,6 +319,7 @@ namespace Robust.Client.Graphics.Clyde
}
#pragma warning disable CA1416
#pragma warning disable CS0162
IDXGIFactory6* factory6;
if (_adapter == null && _factory->QueryInterface(__uuidof<IDXGIFactory6>(), (void**) &factory6) == 0)
{
@@ -349,6 +349,7 @@ namespace Robust.Client.Graphics.Clyde
factory6->Release();
}
#pragma warning restore CS0162
#pragma warning restore CA1416
Span<D3D_FEATURE_LEVEL> featureLevels = stackalloc D3D_FEATURE_LEVEL[]
@@ -363,6 +364,16 @@ namespace Robust.Client.Graphics.Clyde
D3D_FEATURE_LEVEL_9_1
};
if (Clyde._cfg.GetCVar(CVars.DisplayAngleForceEs2))
{
featureLevels = stackalloc D3D_FEATURE_LEVEL[]
{
// Don't allow FL 11_0 so ANGLE is forced to init GLES2.
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_1
};
}
fixed (ID3D11Device** device = &_device)
fixed (D3D_FEATURE_LEVEL* fl = &featureLevels[0])
{

View File

@@ -2,10 +2,10 @@
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using OpenToolkit;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using TerraFX.Interop.Windows;
using static Robust.Client.Graphics.Clyde.Egl;
namespace Robust.Client.Graphics.Clyde
@@ -106,7 +106,7 @@ namespace Robust.Client.Graphics.Clyde
if (OperatingSystem.IsWindows())
{
// Setting up ANGLE without manually selecting a D3D11 device requires a windows DC.
mainWindow.DC = GetDC(Clyde._windowing!.WindowGetWin32Window(mainWindow.Reg)!.Value);
mainWindow.DC = Windows.GetDC((HWND)Clyde._windowing!.WindowGetWin32Window(mainWindow.Reg)!.Value);
_eglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, (void*) mainWindow.DC, null);
if (_eglDisplay == null)
@@ -272,25 +272,6 @@ namespace Robust.Client.Graphics.Clyde
public void* EglSurface;
}
[DllImport("user32.dll")]
private static extern nint GetDC(nint hWnd);
private sealed class EglBindingsContext : IBindingsContext
{
public IntPtr GetProcAddress(string procName)
{
Span<byte> buf = stackalloc byte[128];
buf.Clear();
Encoding.UTF8.GetBytes(procName, buf);
fixed (byte* b = &buf.GetPinnableReference())
{
return (nint) eglGetProcAddress(b);
}
}
}
}
}
}

View File

@@ -53,6 +53,8 @@ namespace Robust.Client.Graphics.Clyde
adapter3->Release();
}
dxgiFactory->Release();
}
private static void ThrowIfFailed(string methodName, HRESULT hr)

View File

@@ -8,6 +8,7 @@ using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
using SixLabors.ImageSharp.PixelFormats;
using TerraFX.Interop.Windows;
using GlfwImage = OpenToolkit.GraphicsLibraryFramework.Image;
using Monitor = OpenToolkit.GraphicsLibraryFramework.Monitor;
@@ -360,12 +361,12 @@ namespace Robust.Client.Graphics.Clyde
// On Windows, closing the child window causes the owner to be minimized, apparently.
// Clear owner on close to avoid this.
var hWnd = (void*) GLFW.GetWin32Window(window);
DebugTools.Assert(hWnd != null);
var hWnd = (HWND) GLFW.GetWin32Window(window);
DebugTools.Assert(hWnd != HWND.NULL);
Win32.SetWindowLongPtrW(
Windows.SetWindowLongPtrW(
hWnd,
Win32.GWLP_HWNDPARENT,
GWLP.GWLP_HWNDPARENT,
0);
}
@@ -378,8 +379,8 @@ namespace Robust.Client.Graphics.Clyde
Window* contextShare,
Window* ownerWindow)
{
GLFW.WindowHint(WindowHintString.X11ClassName, "SS14");
GLFW.WindowHint(WindowHintString.X11InstanceName, "SS14");
GLFW.WindowHint(WindowHintString.X11ClassName, "RobustToolbox");
GLFW.WindowHint(WindowHintString.X11InstanceName, "RobustToolbox");
GLFW.WindowHint(WindowHintBool.ScaleToMonitor, true);
if (spec == null)
@@ -481,14 +482,14 @@ namespace Robust.Client.Graphics.Clyde
{
if (OperatingSystem.IsWindows())
{
var hWnd = (void*) GLFW.GetWin32Window(window);
DebugTools.Assert(hWnd != null);
var hWnd = (HWND) GLFW.GetWin32Window(window);
DebugTools.Assert(hWnd != HWND.NULL);
Win32.SetWindowLongPtrW(
Windows.SetWindowLongPtrW(
hWnd,
Win32.GWL_STYLE,
GWL.GWL_STYLE,
// Cast to long here to work around a bug in rider with nint bitwise operators.
(nint)((long)Win32.GetWindowLongPtrW(hWnd, Win32.GWL_STYLE) & ~Win32.WS_SYSMENU));
(nint)((long)Windows.GetWindowLongPtrW(hWnd, GWL.GWL_STYLE) & ~WS.WS_SYSMENU));
}
else
{
@@ -500,13 +501,13 @@ namespace Robust.Client.Graphics.Clyde
{
if (OperatingSystem.IsWindows())
{
var hWnd = (void*) GLFW.GetWin32Window(window);
var ownerHWnd = GLFW.GetWin32Window(ownerWindow);
DebugTools.Assert(hWnd != null);
var hWnd = (HWND) GLFW.GetWin32Window(window);
var ownerHWnd = (HWND) GLFW.GetWin32Window(ownerWindow);
DebugTools.Assert(hWnd != HWND.NULL);
Win32.SetWindowLongPtrW(
Windows.SetWindowLongPtrW(
hWnd,
Win32.GWLP_HWNDPARENT,
GWLP.GWLP_HWNDPARENT,
ownerHWnd);
}
else

View File

@@ -13,7 +13,7 @@ namespace Robust.Client.Graphics
void SetMasterVolume(float newVolume);
IClydeAudioSource CreateAudioSource(AudioStream stream);
IClydeAudioSource? CreateAudioSource(AudioStream stream);
IClydeBufferedAudioSource CreateBufferedAudioSource(int buffers, bool floatAudio=false);
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Robust.Client.Input;
using Robust.Client.UserInterface;
using Robust.Shared.Map;
@@ -31,7 +32,7 @@ namespace Robust.Client.Graphics
event Action<WindowRequestClosedEventArgs> CloseWindow;
event Action<WindowDestroyedEventArgs> DestroyWindow;
ClydeHandle LoadShader(ParsedShader shader, string? name = null);
ClydeHandle LoadShader(ParsedShader shader, string? name = null, Dictionary<string,string>? defines = null);
void ReloadShader(ClydeHandle handle, ParsedShader newShader);

View File

@@ -18,6 +18,11 @@ namespace Robust.Client.Graphics
IEye? Eye { get; set; }
Vector2i Size { get; }
/// <summary>
/// Color to clear the render target to before rendering. If null, no clearing will happen.
/// </summary>
Color? ClearColor { get; set; }
/// <summary>
/// This is, effectively, a multiplier to the eye's zoom.
/// </summary>

View File

@@ -7,6 +7,7 @@ using Robust.Shared.Utility;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using YamlDotNet.RepresentationModel;
using Color = Robust.Shared.Maths.Color;
namespace Robust.Client.Graphics
{
@@ -31,6 +32,8 @@ namespace Robust.Client.Graphics
/// </summary>
public Vector2i Size { get; /*protected set;*/ }
public Color this[int x, int y] => this.GetPixel(x, y);
protected Texture(Vector2i size)
{
Size = size;
@@ -104,6 +107,8 @@ namespace Robust.Client.Graphics
return this;
}
public abstract Color GetPixel(int x, int y);
}
/// <summary>

View File

@@ -154,7 +154,7 @@ namespace Robust.Client.Input
mapping.Add("leaveEmpty", serializationManager.WriteValue(leaveEmpty));
var path = new ResourcePath(KeybindsPath);
using var writer = new StreamWriter(_resourceMan.UserData.Create(path));
using var writer = _resourceMan.UserData.OpenWriteText(path);
var stream = new YamlStream {new(mapping.ToYaml())};
stream.Save(new YamlMappingFix(new Emitter(writer)), false);
}

View File

@@ -1,184 +0,0 @@
using System;
using System.Collections.Generic;
using Robust.Shared.GameObjects;
using Robust.Shared.GameStates;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
namespace Robust.Client.Map
{
internal class ClientMapManager : MapManager, IClientMapManager
{
public void ApplyGameStatePre(GameStateMapData? data, ReadOnlySpan<EntityState> entityStates)
{
// There was no map data this tick, so nothing to do.
if(data == null)
return;
// First we need to figure out all the NEW MAPS.
if(data.CreatedMaps != null)
{
DebugTools.Assert(!entityStates.IsEmpty, "Received new maps, but no entity state.");
foreach (var mapId in data.CreatedMaps)
{
// map already exists from a previous state.
if (_maps.Contains(mapId))
continue;
EntityUid mapEuid = default;
//get shared euid of map comp entity
foreach (var entityState in entityStates!)
{
foreach (var compChange in entityState.ComponentChanges.Span)
{
if (compChange.State is not MapComponentState mapCompState || mapCompState.MapId != mapId)
continue;
mapEuid = entityState.Uid;
goto BreakMapEntSearch;
}
}
BreakMapEntSearch:
DebugTools.Assert(mapEuid != default, $"Could not find corresponding entity state for new map {mapId}.");
CreateMap(mapId, mapEuid);
}
}
// Then make all the grids.
if(data.CreatedGrids != null)
{
DebugTools.Assert(data.GridData is not null, "Received new grids, but GridData was null.");
foreach (var (gridId, creationDatum) in data.CreatedGrids)
{
if (_grids.ContainsKey(gridId))
continue;
EntityUid gridEuid = default;
//get shared euid of map comp entity
foreach (var entityState in entityStates!)
{
foreach (var compState in entityState.ComponentChanges.Span)
{
if (compState.State is not MapGridComponentState gridCompState || gridCompState.GridIndex != gridId)
continue;
gridEuid = entityState.Uid;
goto BreakGridEntSearch;
}
}
BreakGridEntSearch:
DebugTools.Assert(gridEuid != default, $"Could not find corresponding entity state for new grid {gridId}.");
MapId gridMapId = default;
foreach (var kvData in data.GridData!)
{
if (kvData.Key != gridId)
continue;
gridMapId = kvData.Value.Coordinates.MapId;
break;
}
DebugTools.Assert(gridMapId != default, $"Could not find corresponding gridData for new grid {gridId}.");
CreateGrid(gridMapId, gridId, creationDatum.ChunkSize, gridEuid);
}
}
// Process all grid updates.
if(data.GridData != null)
{
SuppressOnTileChanged = true;
// Ok good all the grids and maps exist now.
foreach (var (gridId, gridDatum) in data.GridData)
{
var grid = _grids[gridId];
if (grid.ParentMapId != gridDatum.Coordinates.MapId)
{
throw new NotImplementedException("Moving grids between maps is not yet implemented");
}
grid.WorldPosition = gridDatum.Coordinates.Position;
var modified = new List<(Vector2i position, Tile tile)>();
foreach (var chunkData in gridDatum.ChunkData)
{
var chunk = grid.GetChunk(chunkData.Index);
chunk.SuppressCollisionRegeneration = true;
DebugTools.Assert(chunkData.TileData.Length == grid.ChunkSize * grid.ChunkSize);
var counter = 0;
for (ushort x = 0; x < grid.ChunkSize; x++)
{
for (ushort y = 0; y < grid.ChunkSize; y++)
{
var tile = chunkData.TileData[counter++];
if (chunk.GetTileRef(x, y).Tile != tile)
{
chunk.SetTile(x, y, tile);
modified.Add((new Vector2i(chunk.X * grid.ChunkSize + x, chunk.Y * grid.ChunkSize + y), tile));
}
}
}
}
if (modified.Count != 0)
{
InvokeGridChanged(this, new GridChangedEventArgs(grid, modified));
}
foreach (var chunkData in gridDatum.ChunkData)
{
var chunk = grid.GetChunk(chunkData.Index);
chunk.SuppressCollisionRegeneration = false;
chunk.RegenerateCollision();
}
foreach (var chunkData in gridDatum.DeletedChunkData)
{
grid.RemoveChunk(chunkData.Index);
}
}
SuppressOnTileChanged = false;
}
}
public void ApplyGameStatePost(GameStateMapData? data)
{
if(data == null) // if there is no data, there is nothing to do!
return;
if(data.DeletedGrids != null)
{
foreach (var grid in data.DeletedGrids)
{
if (_grids.ContainsKey(grid))
{
DeleteGrid(grid);
}
}
}
if(data.DeletedMaps != null)
{
foreach (var map in data.DeletedMaps)
{
if (_maps.Contains(map))
{
DeleteMap(map);
}
}
}
}
}
}

View File

@@ -1,15 +0,0 @@
using System;
using Robust.Shared.GameObjects;
using Robust.Shared.GameStates;
using Robust.Shared.Map;
namespace Robust.Client.Map
{
internal interface IClientMapManager : IMapManagerInternal
{
// Two methods here, so that new grids etc can be made BEFORE entities get states applied,
// but old ones can be deleted after.
void ApplyGameStatePre(GameStateMapData? data, ReadOnlySpan<EntityState> entityStates);
void ApplyGameStatePost(GameStateMapData? data);
}
}

View File

@@ -12,12 +12,16 @@ namespace Robust.Client.Physics
public sealed class PhysicsMapComponent : SharedPhysicsMapComponent
{
private float _timeToSleep;
private float _linSleepTolerance;
private float _angSleepTolerance;
protected override void Initialize()
{
base.Initialize();
var configManager = IoCManager.Resolve<IConfigurationManager>();
configManager.OnValueChanged(CVars.TimeToSleep, SetTimeToSleep);
configManager.OnValueChanged(CVars.TimeToSleep, SetTimeToSleep, true);
configManager.OnValueChanged(CVars.LinearSleepTolerance, SetLinearSleepTolerance, true);
configManager.OnValueChanged(CVars.AngularSleepTolerance, SetAngularSleepTolerance, true);
}
protected override void OnRemove()
@@ -25,10 +29,16 @@ namespace Robust.Client.Physics
base.OnRemove();
var configManager = IoCManager.Resolve<IConfigurationManager>();
configManager.UnsubValueChanged(CVars.TimeToSleep, SetTimeToSleep);
configManager.UnsubValueChanged(CVars.LinearSleepTolerance, SetLinearSleepTolerance);
configManager.UnsubValueChanged(CVars.AngularSleepTolerance, SetAngularSleepTolerance);
}
private void SetTimeToSleep(float value) => _timeToSleep = value;
private void SetLinearSleepTolerance(float value) => _linSleepTolerance = value;
private void SetAngularSleepTolerance(float value) => _angSleepTolerance = value;
protected override void Cleanup(float frameTime)
{
var toRemove = new List<PhysicsComponent>();
@@ -36,9 +46,10 @@ namespace Robust.Client.Physics
// Because we're not predicting 99% of bodies its sleep timer never gets incremented so we'll just do it ourselves.
// (and serializing it over the network isn't necessary?)
// This is a client-only problem.
// Also need to suss out having the client build the island anyway and just... not solving it?
foreach (var body in AwakeBodies)
{
if (body.Island || body.LinearVelocity.Length > 0.0001f || body.AngularVelocity != 0f) continue;
if (body.Island || body.LinearVelocity.Length > _linSleepTolerance / 2f || body.AngularVelocity > _angSleepTolerance / 2f) continue;
body.SleepTime += frameTime;
if (body.SleepTime > _timeToSleep)
{

View File

@@ -1,5 +1,6 @@
using System;
using JetBrains.Annotations;
using Robust.Client.GameStates;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
@@ -11,6 +12,7 @@ namespace Robust.Client.Physics
public class PhysicsSystem : SharedPhysicsSystem
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IClientGameStateManager _gameState = default!;
private TimeSpan _lastRem;
@@ -22,6 +24,9 @@ namespace Robust.Client.Physics
public override void FrameUpdate(float frameTime)
{
if (!_gameState.IsPredictionEnabled)
return;
if (_lastRem > _gameTiming.TickRemainder)
{
_lastRem = TimeSpan.Zero;

View File

@@ -1,10 +1,11 @@
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.GameObjects;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
@@ -125,7 +126,7 @@ namespace Robust.Client.Placement
public IEnumerable<EntityCoordinates> LineCoordinates()
{
var (x, y) = MouseCoords.ToMapPos(pManager.EntityManager) - pManager.StartPoint.ToMapPos(pManager.EntityManager);
var (_, (x, y)) = MouseCoords.WithEntityId(pManager.StartPoint.EntityId) - pManager.StartPoint;
float iterations;
Vector2 distance;
if (Math.Abs(x) > Math.Abs(y))
@@ -148,7 +149,7 @@ namespace Robust.Client.Placement
// This name is a nice reminder of our origins. Never forget.
public IEnumerable<EntityCoordinates> GridCoordinates()
{
var placementdiff = MouseCoords.ToMapPos(pManager.EntityManager) - pManager.StartPoint.ToMapPos(pManager.EntityManager);
var placementdiff = MouseCoords.WithEntityId(pManager.StartPoint.EntityId) - pManager.StartPoint;
var distanceX = new Vector2(placementdiff.X > 0 ? 1 : -1, 0) * GridDistancing;
var distanceY = new Vector2(0, placementdiff.Y > 0 ? 1 : -1) * GridDistancing;

View File

@@ -2,6 +2,7 @@
using System.Diagnostics.CodeAnalysis;
using System.IO;
using Robust.LoaderApi;
using Robust.Shared.ContentPack;
using Robust.Shared.Utility;
namespace Robust.Client.ResourceManagement

View File

@@ -17,7 +17,6 @@
<PackageReference Include="Microsoft.Data.Sqlite" Version="5.0.3" />
<PackageReference Include="nfluidsynth" Version="0.3.1" />
<PackageReference Include="NVorbis" Version="0.10.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.4" />
<PackageReference Include="OpenToolkit.Graphics" Version="4.0.0-pre9.1" />
<PackageReference Include="OpenToolkit.OpenAL" Version="4.0.0-pre9.1" />
@@ -50,6 +49,11 @@
<RobustLinkAssemblies Include="TerraFX.Interop.Windows" />
<RobustLinkAssemblies Include="OpenToolkit.Graphics" />
</ItemGroup>
<ItemGroup>
<Compile Update="UserInterface\CustomControls\DefaultWindow.xaml.cs">
<DependentUpon>DefaultWindow.xaml</DependentUpon>
</Compile>
</ItemGroup>
<Import Project="..\MSBuild\Robust.Engine.targets" />
<PropertyGroup>
<RobustToolsPath>../Tools</RobustToolsPath>

View File

@@ -186,6 +186,8 @@ namespace Robust.Client.UserInterface.Controls
private void Select(int idx)
{
if(SelectMode != ItemListSelectMode.Multiple)
ClearSelected(idx);
OnItemSelected?.Invoke(new ItemListSelectedEventArgs(idx, this));
}
@@ -208,18 +210,19 @@ namespace Robust.Client.UserInterface.Controls
Deselect(idx);
}
public void ClearSelected()
public void ClearSelected(int? except = null)
{
foreach (var item in GetSelected())
{
if(IndexOf(item) == except) continue;
item.Selected = false;
}
}
public void SortItemsByText()
{
_itemList.Sort((p, q) => string.Compare(p.Text, q.Text, StringComparison.Ordinal));
}
public void SortItemsByText() => Sort((p, q) => string.Compare(p.Text, q.Text, StringComparison.Ordinal));
public void Sort(Comparison<Item> comparison) => _itemList.Sort(comparison);
public void EnsureCurrentIsVisible()
{
@@ -447,8 +450,6 @@ namespace Robust.Client.UserInterface.Controls
return;
}
if(SelectMode != ItemListSelectMode.Multiple)
ClearSelected();
item.Selected = true;
if (SelectMode == ItemListSelectMode.Button)
Timer.Spawn(ButtonDeselectDelay, () => { item.Selected = false; } );

View File

@@ -33,6 +33,16 @@ namespace Robust.Client.UserInterface.Controls
private bool Vertical => Orientation == SplitOrientation.Vertical;
public SplitState State
{
get => _splitState;
set
{
_splitState = value;
InvalidateMeasure();
}
}
[ViewVariables(VVAccess.ReadWrite)]
public SplitOrientation Orientation
{
@@ -266,7 +276,7 @@ namespace Robust.Client.UserInterface.Controls
/// <summary>
/// Defines how the split position should be determined
/// </summary>
private enum SplitState : byte
public enum SplitState : byte
{
/// <summary>
/// Automatically adjust the split based on the width of the children

View File

@@ -216,7 +216,7 @@ namespace Robust.Client.UserInterface.CustomControls
if (!Visible)
{
Visible = true;
Logger.WarningS("ui", $"Window {this} had visibility false. Do not use visibility on SS14Window.");
Logger.WarningS("ui", $"Window {this} had visibility false. Do not use visibility on DefaultWindow.");
}
if (!IsOpen)

View File

@@ -313,13 +313,13 @@ namespace Robust.Client.UserInterface.CustomControls
await Task.Run(async () =>
{
Stream? stream = null;
StreamWriter? writer = null;
for (var i = 0; i < 3; i++)
{
try
{
stream = _resourceManager.UserData.Create(HistoryPath);
writer = _resourceManager.UserData.OpenWriteText(HistoryPath);
break;
}
catch (IOException)
@@ -329,16 +329,18 @@ namespace Robust.Client.UserInterface.CustomControls
}
}
if (stream == null)
if (writer == null)
{
sawmill.Warning("Failed to save debug console history!");
return;
}
// ReSharper disable once UseAwaitUsing
using var writer = new StreamWriter(stream, EncodingHelpers.UTF8);
// ReSharper disable once MethodHasAsyncOverload
writer.Write(newHistory);
using (writer)
{
// ReSharper disable once MethodHasAsyncOverload
writer.Write(newHistory);
}
});
}
}

View File

@@ -1,13 +1,13 @@
<SS14Window xmlns="https://spacestation14.io" MinWidth="100" MinHeight="50">
<DefaultWindow xmlns="https://spacestation14.io" MinWidth="100" MinHeight="50">
<PanelContainer StyleClasses="windowPanel" />
<BoxContainer Orientation="Vertical" SeparationOverride="0">
<PanelContainer Name="WindowHeader" StyleClasses="windowHeader">
<BoxContainer Orientation="Horizontal">
<Label Margin="5 0 0 0" HorizontalExpand="true" Name="TitleLabel" StyleIdentifier="foo" ClipText="True"
Text="{Loc 'ss14window-placeholder-title'}" VAlign="Center" StyleClasses="windowTitle" />
Text="{Loc 'defaultwindow-placeholder-title'}" VAlign="Center" StyleClasses="windowTitle" />
<TextureButton Name="CloseButton" StyleClasses="windowCloseButton" VerticalAlignment="Center" />
</BoxContainer>
</PanelContainer>
<Control Name="ContentsContainer" Margin="10" RectClipContent="True" VerticalExpand="true" />
</BoxContainer>
</SS14Window>
</DefaultWindow>

View File

@@ -9,9 +9,15 @@ using Robust.Shared.Utility;
namespace Robust.Client.UserInterface.CustomControls
{
/// <summary>
/// Simple window implementation that can be resized and has a title bar.
/// </summary>
/// <remarks>
/// Warning: ugly.
/// </remarks>
[GenerateTypedNameReferences]
// ReSharper disable once InconsistentNaming
public partial class SS14Window : BaseWindow
public partial class DefaultWindow : BaseWindow
{
public const string StyleClassWindowTitle = "windowTitle";
public const string StyleClassWindowPanel = "windowPanel";
@@ -21,7 +27,7 @@ namespace Robust.Client.UserInterface.CustomControls
private string? _headerClass;
private string? _titleClass;
public SS14Window()
public DefaultWindow()
{
RobustXamlLoader.Load(this);
MouseFilter = MouseFilterMode.Stop;
@@ -171,9 +177,9 @@ namespace Robust.Client.UserInterface.CustomControls
public class SS14ContentCollection : ICollection<Control>, IReadOnlyCollection<Control>
{
private readonly SS14Window Owner;
private readonly DefaultWindow Owner;
public SS14ContentCollection(SS14Window owner)
public SS14ContentCollection(DefaultWindow owner)
{
Owner = owner;
}
@@ -229,9 +235,9 @@ namespace Robust.Client.UserInterface.CustomControls
{
private OrderedChildCollection.Enumerator _enumerator;
internal Enumerator(SS14Window ss14Window)
internal Enumerator(DefaultWindow DefaultWindow)
{
_enumerator = ss14Window.Contents.Children.GetEnumerator();
_enumerator = DefaultWindow.Contents.Children.GetEnumerator();
}
public bool MoveNext()

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