Compare commits

..

821 Commits

Author SHA1 Message Date
metalgearsloth
b6cadfedd5 Update arch (#4605) 2023-11-25 14:56:56 +11:00
metalgearsloth
9f57b705d7 Version: 182.0.0 2023-11-24 00:21:00 +11:00
metalgearsloth
68be9712ad Add entity gen to hashcode (#4601) 2023-11-24 00:19:58 +11:00
metalgearsloth
aaa446254c Version: 181.0.2 2023-11-23 23:43:47 +11:00
metalgearsloth
5e2d2ab317 Fix too many pointlights causing blackscreen (#4599) 2023-11-23 23:39:51 +11:00
metalgearsloth
20ae63fbbd Replace tile intersecting with enumerator (#4595) 2023-11-23 22:36:40 +11:00
metalgearsloth
a92c0cbef4 Fix nullable comps being raised for client gamestates (#4596) 2023-11-23 22:07:27 +11:00
metalgearsloth
95649a2dd0 Version: 181.0.1 2023-11-23 16:53:03 +11:00
metalgearsloth
861807f8b4 Fix HasComp(uid, Type) (#4594) 2023-11-23 16:52:31 +11:00
metalgearsloth
bd73f1c05a Version: 181.0.0 2023-11-23 15:28:35 +11:00
metalgearsloth
7dce51e2cf Arch PR two electric boogaloo (#4388)
Co-authored-by: DrSmugleaf <drsmugleaf@gmail.com>
Co-authored-by: ElectroJr <leonsfriedrich@gmail.com>
2023-11-23 14:29:37 +11:00
DrSmugleaf
d9b0f3a227 Version: 180.2.1 2023-11-22 17:02:13 -08:00
Vasilis
05766a2eaa Fix not using dotnet 7 for actions in engine (#4591) 2023-11-23 00:43:15 +01:00
metalgearsloth
a761fbc09e Version: 180.2.0 2023-11-22 22:00:05 +11:00
metalgearsloth
f69440b3f2 Minor PVS stuff (#4573)
Co-authored-by: ElectroJr <leonsfriedrich@gmail.com>
2023-11-22 21:54:07 +11:00
Leon Friedrich
b459d2ce21 Add more map system helper methods. (#4589) 2023-11-22 21:51:46 +11:00
Leon Friedrich
202182e3d4 Add new EnsureEntity variants (#4586) 2023-11-20 17:44:36 +11:00
metalgearsloth
96cb52e5d2 Version: 180.1.0 2023-11-20 16:31:41 +11:00
metalgearsloth
82e0c0baeb Add cvar for lidgren pool size (#4585) 2023-11-20 16:28:13 +11:00
Leon Friedrich
54d6552164 Fix shape lookups for non-hard fixtures (#4583) 2023-11-20 16:15:27 +11:00
Jordan Dominion
c21b6c993c Fix potential error when writing runtime log (#4575) 2023-11-19 15:47:53 +01:00
metalgearsloth
2fe4a8b859 Add map name to lsmap (#4576) 2023-11-19 15:47:19 +01:00
metalgearsloth
8325966dbb Fix contact constraints allocs (#4581) 2023-11-19 15:47:07 +01:00
metalgearsloth
2459a9d688 Version: 180.0.0 2023-11-19 15:09:59 +11:00
Leon Friedrich
2cd2d1edd6 Add misc helpful methods (#4577) 2023-11-19 15:05:26 +11:00
metalgearsloth
b982350851 Use NetEntities for F3 panel (#4571) 2023-11-16 20:53:23 +11:00
DrSmugleaf
4a50bc2154 Add AddEntitiesIntersecting for phys shapes, change float range overload to use circles, remove obsolete methods (#4572) 2023-11-16 20:44:21 +11:00
metalgearsloth
4c85e205b9 Add chain support to TryGetNearest (#4567) 2023-11-16 20:40:23 +11:00
ElectroJr
0b447d9d82 Version: 179.0.0 2023-11-12 13:35:17 -05:00
Leon Friedrich
ceb205ad52 Allow per-eye lighting toggling. (#4569) 2023-11-13 05:30:00 +11:00
Leon Friedrich
a48ff3dbf1 Fix PlacementManager bug (#4568) 2023-11-13 05:29:18 +11:00
DrSmugleaf
2b85fa88c1 Print stack trace when adding a component while iterating net comps in ResetPredictedEntities (#4541) 2023-11-13 05:26:13 +11:00
Leon Friedrich
19564a421b Fix deserialization of empty grid chunks (#4565) 2023-11-13 05:22:20 +11:00
Leon Friedrich
b3f0e467ee Improve UnknownPrototypeException error message (#4566) 2023-11-13 05:22:05 +11:00
Leon Friedrich
216292c849 Make EyeComponent.Eye not nullable (#4564) 2023-11-13 04:20:09 +11:00
Jerry
68753d15e0 Fix stack overflow error on planet station (#4563) 2023-11-12 13:28:35 +11:00
ElectroJr
2a357051ae Version: 178.0.0 2023-11-10 20:58:35 -05:00
Leon Friedrich
58e0b62145 Merge ActorSystem and IPlayerManager (#4530) 2023-11-11 12:50:21 +11:00
Leon Friedrich
14cc273997 Add NetListAsArray<T>.Value to sandbox whitelist (#4537) 2023-11-11 11:57:58 +11:00
DrSmugleaf
93f4428635 Version: 177.0.0 2023-11-08 00:21:12 -08:00
DrSmugleaf
164bf68aca Move TryGetUi/TryToggleUi/ToggleUi/TryOpen/OpenUi/TryClose/CloseUi to SharedUserInterfaceSystem (#4562) 2023-11-08 16:52:38 +11:00
Leon Friedrich
773b87672b Fix terminating entity reparenting bug (#4549) 2023-11-08 15:39:08 +11:00
metalgearsloth
eecf834039 Fix PlacementManager warnings (#4557) 2023-11-08 15:34:54 +11:00
Leon Friedrich
325fe46aa3 Add More Entity<T> query methods (#4550) 2023-11-07 20:24:42 -08:00
metalgearsloth
2f6c29ab43 Add GetMapCoordinates to TransformSystem (#4556) 2023-11-07 20:23:05 -08:00
metalgearsloth
aab1a2dba9 Fix transform test warnings (#4558) 2023-11-07 20:22:07 -08:00
DrSmugleaf
f36fbd9c83 Fix inverted GetAllMapGrids mapid check (#4561) 2023-11-07 14:26:01 -08:00
metalgearsloth
126c863f45 Hotfix containersystem.remove (#4560) 2023-11-07 16:18:08 +11:00
Leon Friedrich
618a8491bf Add BeforeApplyState event to replay playback (#4536) 2023-11-07 15:07:26 +11:00
Leon Friedrich
2743b64a2b Mark container methods as obsolete (#4551) 2023-11-07 15:05:32 +11:00
Leon Friedrich
28cc91934c Change PVS error log into warning (#4548) 2023-11-07 15:02:13 +11:00
metalgearsloth
eadfcd4c09 Specify RichTextLabel VAlignment as Center (#4520) 2023-11-07 10:27:49 +11:00
metalgearsloth
7871b0010e Version: 176.0.0 2023-11-07 09:51:32 +11:00
metalgearsloth
3da04ed17e Robust.Packaging updates (#4547) 2023-11-07 09:36:33 +11:00
metalgearsloth
170d192791 Revert audio rework (#4554) 2023-11-07 09:34:09 +11:00
Leon Friedrich
dcd9939554 Fix PVS initial list capacity bug (#4546) 2023-11-06 04:41:56 +11:00
Leon Friedrich
98ef58eca6 Add max game state buffer size cvar (#4543) 2023-11-05 02:58:48 +11:00
metalgearsloth
ab1e99a0df Add GetEntitiesInRange that takes in a set (#4544) 2023-11-04 15:02:20 +11:00
Leon Friedrich
499c236798 Fix replay lerp error spam (#4534) 2023-10-30 04:29:47 +11:00
metalgearsloth
8dc2345ceb Fix audio position on first tick (#4533) 2023-10-29 15:30:59 +11:00
metalgearsloth
9b04270178 Version: 175.0.0 2023-10-29 15:03:09 +11:00
metalgearsloth
d75dbc901f Audio rework (#4421) 2023-10-29 14:58:19 +11:00
Leon Friedrich
19a3e82848 Cache prototype data for IEntityManager.IsDefault() (#4531) 2023-10-29 12:54:52 +11:00
Leon Friedrich
911abf2693 Remove empty planet-map chunks (#4529) 2023-10-29 12:52:03 +11:00
ElectroJr
f5874ea402 Version: 174.0.0 2023-10-28 13:26:49 -04:00
metalgearsloth
b486ef885c Add NextAngle for System.Random (#4522) 2023-10-29 04:22:32 +11:00
metalgearsloth
9d55d77e48 Sprite GetFrame (#4528) 2023-10-29 04:21:52 +11:00
Leon Friedrich
5af3cb969c Move ActorComponent to shared (#4527) 2023-10-29 04:21:09 +11:00
metalgearsloth
429bc806dc Version: 173.1.0 2023-10-28 15:36:26 +11:00
metalgearsloth
81484699a8 Add chain shapes (#4523)
* Add chain shapes

* rar only

* that too

* weh

* a

* Update Robust.Shared/Physics/Dynamics/Contacts/Contact.cs

Co-authored-by: Moony <moony@hellomouse.net>

* Update Robust.Shared/Physics/Dynamics/Contacts/Contact.cs

Co-authored-by: Moony <moony@hellomouse.net>

---------

Co-authored-by: Moony <moony@hellomouse.net>
2023-10-28 15:29:30 +11:00
metalgearsloth
7cad8d5ba3 Version: 173.0.0 2023-10-28 14:02:06 +11:00
Leon Friedrich
3aa04a3c86 Fix grid chunk bugs (#4525)
* Fix grid rendering

* Use TileChangedEvent

* Other empty chunk fixes

* Remove assert

Good ol integration tests at it again, adding invalid components
2023-10-28 13:57:54 +11:00
metalgearsloth
9750b113c8 Version: 172.0.0 2023-10-24 20:22:31 +11:00
Leon Friedrich
5a6c4220fc IPlayerManager refactor (#4518) 2023-10-24 20:18:58 +11:00
Leon Friedrich
b2d389f184 Remove TryLifestage() helpers (#4519) 2023-10-24 18:46:46 +11:00
Leon Friedrich
ad0cb05dd6 Add EnsureComponent(ref Entity<T?>) (#4516) 2023-10-24 17:19:38 +11:00
Leon Friedrich
ad134d9e4e Fix game state logging spam (#4517) 2023-10-24 14:09:55 +11:00
Leon Friedrich
be33bc2219 Re-add force ack threshold (#4423) and fix bugs. (#4438)
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
2023-10-22 23:27:15 +11:00
metalgearsloth
aa2fd2107d Add mgs to physics codeowners (#4510)
Please ping me for this is creates more work if you do not ping me.
2023-10-22 05:03:47 -07:00
metalgearsloth
554e0777b1 Version: 171.0.0 2023-10-22 16:58:48 +11:00
metalgearsloth
21b7c5f93e Cleanup relays on joint deletion (#4497) 2023-10-22 16:53:10 +11:00
Leon Friedrich
9e5c1e9c95 Change place-next-to helper methods (#4506) 2023-10-22 16:52:58 +11:00
Leon Friedrich
6825f09fb9 Set EntityLastModifiedTick when an entity spawns (#4509) 2023-10-22 16:51:40 +11:00
DrSmugleaf
58e3a4eb4a Version: 170.0.0 2023-10-21 14:31:08 -07:00
DrSmugleaf
9a342f0d11 Fix double delete entity command, fix not being able to delete individual entities (#4508) 2023-10-21 14:19:34 -07:00
DrSmugleaf
f754ddb96d Remove all usages of obsolete Dirty method, remove some obsoleted methods (#4500) 2023-10-21 14:19:07 -07:00
Leon Friedrich
7feede0d95 Fix duplicate command error (#4507) 2023-10-21 14:18:50 -07:00
Jordan Dominion
ea152366e3 Allow deletion of FileLogHandler logs while engine is running (#4501) 2023-10-21 15:07:10 +02:00
DrSmugleaf
ab47d4e009 Version: 169.0.1 2023-10-21 03:55:02 -07:00
DrSmugleaf
81b2a3825e Fix help command, let the client know about server toolshed commands (#4502) 2023-10-21 03:54:17 -07:00
DrSmugleaf
56d850f389 Version: 169.0.0 2023-10-19 12:27:27 -07:00
DrSmugleaf
b737ecf9b3 Add generic EntityUid, remove some usages of .Owner (#4498) 2023-10-19 12:23:48 -07:00
DrSmugleaf
ed5223b592 Remove by-refness subscription test (#4499) 2023-10-19 02:04:32 -07:00
DrSmugleaf
f87012e681 Allow handling by-value events by ref (#4373) 2023-10-18 18:37:43 -07:00
wixoa
54529fdbe3 Respect the manifest's assemblyPrefix value on the server (#4492) 2023-10-18 20:29:28 +02:00
DrSmugleaf
1745a12e5a Remove casts to Component (#4495) 2023-10-17 20:45:21 -07:00
DrSmugleaf
d201d787b7 Remove obsoletion from localized and console commands (#4496) 2023-10-17 20:18:30 -07:00
DrSmugleaf
904ddea274 Version: 168.0.0 2023-10-17 19:38:56 -07:00
DrSmugleaf
6b6ec844e8 Replace all T : Component constraints with T : IComponent (#4494) 2023-10-17 19:37:46 -07:00
Jordan Dominion
f24d18f470 Allow for ushort CVars (#4493) 2023-10-17 16:44:18 -07:00
metalgearsloth
77654a1628 Version: 167.0.0 2023-10-17 23:51:47 +11:00
Leon Friedrich
f3af813b57 Transform interpolation fixes (#4488) 2023-10-17 23:47:45 +11:00
Leon Friedrich
0623baedcf Fix PVS bug and add new test (#4444)
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
2023-10-17 23:33:42 +11:00
Leon Friedrich
2ade6c04c5 Adds more joint debug asserts (#4490) 2023-10-15 11:04:27 +11:00
Kara
a9df9097c1 Kill ContainerHelpers (#4486) 2023-10-15 03:58:25 +11:00
Kara
755dac719f Kill ComponentExt (#4485) 2023-10-15 03:58:04 +11:00
ElectroJr
7095a58685 Version: 166.0.0 2023-10-10 22:23:51 -04:00
Leon Friedrich
16e68a4351 Make PVS session overrides recursive (#4480) 2023-10-11 13:16:00 +11:00
DrSmugleaf
0152f9d1d8 Move Component lifecycle methods to EntityManager (#4483) 2023-10-10 17:34:40 -07:00
DrSmugleaf
16d916796a Add doc clarification to CopyByRef inheritance for the future coder (#4476) 2023-10-10 17:34:24 -07:00
Leon Friedrich
e865157432 Make AssertOwner() accept nullable components (#4475) 2023-10-10 04:41:26 +11:00
metalgearsloth
24d5ce4bd4 Make AddCompUninit obsolete (#4470) 2023-10-10 04:41:10 +11:00
deltanedas
662195e4ff add SortedSetSerializer (#4473) 2023-10-10 04:29:42 +11:00
DrSmugleaf
d00fd6f736 Make AnimationPlayerSystem only log a warning for networked components when the property is automatically networked (#4477) 2023-10-10 04:08:56 +11:00
Leon Friedrich
2d58c1071d Make ExpandPvsEvent lists nullable (#4479) 2023-10-10 04:07:59 +11:00
Leon Friedrich
a9db89d023 Fix nullable NetEntity conversion (#4481) 2023-10-10 04:07:30 +11:00
Leon Friedrich
684cabf3e6 Use metadata query in ToPrettyString() (#4478) 2023-10-09 19:07:31 +11:00
ElectroJr
a4f51f0cd9 Fix release notes 2023-10-08 12:41:45 -04:00
ElectroJr
a8ddd837c8 Version: 165.0.0 2023-10-08 12:39:03 -04:00
Leon Friedrich
82aace7997 Fix SplitContainer.MinDraggableWidth not working with mouse-blocking children. (#4439) 2023-10-09 03:28:23 +11:00
Leon Friedrich
01ce244b7b Validate default values of ProtoId and EntProtoId fields (#4462) 2023-10-02 03:49:45 +11:00
metalgearsloth
58aa6e5c75 Version: 164.0.0 2023-09-30 15:19:43 +10:00
DrSmugleaf
4818c3aab4 Make auto comp states infer when data should be cloned (#4461) 2023-09-30 15:14:10 +10:00
Leon Friedrich
3b6adeb5ff Reduce transform resolves in RecursiveDeleteEntity() (#4468) 2023-09-30 15:12:17 +10:00
metalgearsloth
889b8351be Version: 163.0.0 2023-09-30 14:40:55 +10:00
metalgearsloth
ac37b0a131 Move TimedDespawn to engine (#4448) 2023-09-30 14:35:28 +10:00
Leon Friedrich
f6f1fc425a Use ToPrettyString() in component resolve errors (#4467) 2023-09-30 14:31:40 +10:00
Leon Friedrich
7476628840 Give map and grid entities a default name (#4464) 2023-09-30 14:09:37 +10:00
Leon Friedrich
668cdbe76b Allow adding/removing of widgets in sub-controls (#4443) 2023-09-30 14:08:52 +10:00
Leon Friedrich
a0a6e9b111 Fix render error spam (#4463) 2023-09-30 14:07:27 +10:00
Leon Friedrich
06d28f04e6 Add ExecuteCommand() (#4466) 2023-09-30 14:07:07 +10:00
Leon Friedrich
57897161d0 Fix console backspace exception (#4465) 2023-09-30 14:05:29 +10:00
metalgearsloth
c4c528478e Use gamestate fields to avoid heap allocs (#4452) 2023-09-29 15:03:50 +10:00
DrSmugleaf
a6c295b89c Version: 162.2.1 2023-09-28 17:55:17 -07:00
DrSmugleaf
165913a4de Add IComparable to ProtoId, EntProtoId and LocId (#4460) 2023-09-28 17:53:23 -07:00
metalgearsloth
675dfdaabd Fix scroll containers invalidating on first scroll (#4449) 2023-09-28 16:58:18 -07:00
Kara
fab172d6f6 Allow force submitting line edits (#4455) 2023-09-28 11:07:55 -07:00
metalgearsloth
e75c1659f6 Version: 162.2.0 2023-09-28 20:25:52 +10:00
DrSmugleaf
0c440a8fc9 Localize "View Variables" (#4454) 2023-09-28 20:22:54 +10:00
DrSmugleaf
0c2c8f352a Add LocId and LocIdSerializer (#4456) 2023-09-28 20:22:17 +10:00
DrSmugleaf
0a4a2b7a36 Add nullable conversion operators to ProtoId and EntProtoId (#4447) 2023-09-28 20:18:45 +10:00
metalgearsloth
b5b59c1d2f Use CollectionsMarshal in clientgamestatemanager (#4453) 2023-09-28 20:13:38 +10:00
metalgearsloth
f4f0967fdc Fix double contact deletion throwing (#4450) 2023-09-28 20:12:45 +10:00
metalgearsloth
3d69766112 Use CollectionsMarshal for mergeimplicitdata (#4451) 2023-09-28 20:12:22 +10:00
DrSmugleaf
d1eb3438d5 Add support for automatically networking entity lists and sets (#4446) 2023-09-25 18:02:53 +10:00
ElectroJr
8f6b189d29 Version: 162.1.1 2023-09-19 17:59:16 -04:00
Leon Friedrich
ef8b278b47 Fix HideSpawnMenu (#4437) 2023-09-20 07:57:50 +10:00
metalgearsloth
c53ce2c907 Version: 162.1.0 2023-09-19 23:19:39 +10:00
Leon Friedrich
f063aa3ea1 Use CollectionsMarshal in RobustTree (#4429) 2023-09-19 23:17:27 +10:00
Leon Friedrich
30f63254ef Mark ProtoId<T> as serializable (#4430) 2023-09-19 23:13:14 +10:00
Leon Friedrich
30a5b6152c Slightly improve AddToChunkSetRecursively() (#4432) 2023-09-19 23:13:00 +10:00
Leon Friedrich
910a7f8bff Fix visibility layers not updating on children (#4431) 2023-09-19 23:12:52 +10:00
Leon Friedrich
526a88293e Use CollectionsMarshal in AddComponentInternal() (#4435) 2023-09-19 23:09:41 +10:00
metalgearsloth
22cd840b83 Revert "Add force ack threshold (#4423)" (#4436) 2023-09-19 18:36:41 +10:00
metalgearsloth
415c518bc7 Version: 162.0.0 2023-09-19 17:40:46 +10:00
Leon Friedrich
2417dbb0e0 Use CollectionsMarshal in DynamicTree (#4433) 2023-09-19 15:58:02 +10:00
Leon Friedrich
005673a957 Add force ack threshold (#4423) 2023-09-19 15:16:01 +10:00
Leon Friedrich
942db3120c Make entity system proxy methods use Metadata & Transform queries (#4434) 2023-09-19 15:11:21 +10:00
Leon Friedrich
c0a5fab19e Add missing EntitySystem - EntityManager proxy method (#4427) 2023-09-18 12:17:46 +10:00
Leon Friedrich
d16c62b132 Use CollectionsMarshal in PVS (#4428) 2023-09-18 12:17:32 +10:00
Leon Friedrich
7da22557fe Add entity categories (#4356) 2023-09-18 12:14:26 +10:00
metalgearsloth
92f47c0f20 Version: 161.1.0 2023-09-18 11:48:03 +10:00
Leon Friedrich
9576d0739f Add more DebugTools assert variants (#4425) 2023-09-18 11:18:35 +10:00
Leon Friedrich
10f25faabf Try fix oldest ack issues (#4426) 2023-09-18 11:17:49 +10:00
Leon Friedrich
74831a177e Don't attempt to insert entities into deleted containers (#4424) 2023-09-18 10:57:14 +10:00
ElectroJr
88d3168913 Version: 161.0.0 2023-09-17 13:56:34 -04:00
Leon Friedrich
902519093c Add PVS debug command (#4422) 2023-09-18 03:49:57 +10:00
Leon Friedrich
366266a8ae Fix light animations not working (#4413) 2023-09-18 03:49:47 +10:00
Leon Friedrich
a22cce7783 Fix metadata assert (#4419) 2023-09-17 17:18:44 +10:00
metalgearsloth
e5e738b8cd Maybe fix heisentest (#4418) 2023-09-17 16:13:37 +10:00
metalgearsloth
b8f6e83473 Use stackalloc Span<Vector2> in ComputeHull (#4417) 2023-09-17 12:41:53 +10:00
Artur
c5fb186c57 Add missing InvariantCulture to AngleTypeParser (#4411) 2023-09-17 11:32:01 +10:00
Leon Friedrich
131d7f5422 Add string formatting for client-side NetEntity ids (#4415) 2023-09-17 11:29:54 +10:00
Leon Friedrich
217996f1ed Use ToPrettyString() in state error logs. (#4416) 2023-09-17 11:29:02 +10:00
DrSmugleaf
fc718d68a5 Fix IClydeWindow resized xmldoc (#4414) 2023-09-17 11:28:43 +10:00
Leon Friedrich
d7d9578803 Mark EntPrototId as NetSerializable (#4412) 2023-09-17 11:25:40 +10:00
metalgearsloth
9bbeb54569 Version: 160.1.0 2023-09-17 11:20:03 +10:00
metalgearsloth
1ea7071ffb Backport some arch comp net changes (#4408)
Co-authored-by: ElectroJr <leonsfriedrich@gmail.com>
2023-09-17 11:03:11 +10:00
ElectroJr
196028b619 Version: 160.0.2 2023-09-16 14:50:34 -04:00
ElectroJr
c102da052f Make VV fields private 2023-09-16 14:47:27 -04:00
metalgearsloth
5d46cdcfa4 Add transform parent + container VVs (#4407) 2023-09-16 17:08:08 +10:00
metalgearsloth
cd646d3b07 Version: 160.0.0 2023-09-16 15:26:56 +10:00
Leon Friedrich
922165fa19 Include sensors in default entity lookups (#4406) 2023-09-16 15:22:54 +10:00
metalgearsloth
4879252e99 Remove comprefs entirely (#4367) 2023-09-15 21:52:47 +10:00
DrSmugleaf
0e21f5727a Version: 159.1.0 2023-09-15 03:41:17 -07:00
Leon Friedrich
3ce8a00389 Store metadata component in NetEntity lookup dictionary (#4400)
Co-authored-by: DrSmugleaf <drsmugleaf@gmail.com>
2023-09-15 02:01:44 -07:00
Leon Friedrich
9a283fe541 PVS NetEntity related changes (#4399) 2023-09-15 01:47:35 -07:00
Leon Friedrich
f3e3e64db3 Re-add entity check to fixture equality (#4397) 2023-09-15 18:44:24 +10:00
Leon Friedrich
4a4a135089 Make ToPrettyString() take in nullable EntityUids (#4396) 2023-09-15 01:43:39 -07:00
metalgearsloth
e323a67806 Remove 1 pvs getcomp (#4398) 2023-09-15 15:28:16 +10:00
Leon Friedrich
3a328ffdd5 More NetEntity VV fixes (#4395) 2023-09-15 13:37:18 +10:00
Leon Friedrich
bc5107e297 Misc NetEntity fixes for VV (#4390) 2023-09-15 10:11:28 +10:00
metalgearsloth
2abf33c9be Queue LightTree update on light states (#4385)
Might fix some more issues.
2023-09-15 06:03:25 +12:00
metalgearsloth
71c46828c2 Minor re-apply net state change (#4392)
Slightly faster than checking deleted first, at least for now.
2023-09-15 05:56:51 +12:00
DrSmugleaf
814d6fe2d0 Add ProtoId, EntProtoId and serializers (#4387) 2023-09-12 23:19:40 -07:00
DrSmugleaf
77b98b8308 Add ProtoId, EntProtoId and serializers (#4386) 2023-09-13 14:32:01 +10:00
metalgearsloth
34b0a7fc6d Fix tooltip bounds (#4384) 2023-09-13 13:23:34 +10:00
DrSmugleaf
1b6123c79f Make data field tags optional (#4382) 2023-09-13 12:58:46 +10:00
DrSmugleaf
1476f9d462 Make QueueDel work with nullable entity uids (#4381) 2023-09-13 12:58:03 +10:00
Leon Friedrich
d62efe7301 Add UnknownEntityDeleteTest (#4380) 2023-09-13 12:57:50 +10:00
metalgearsloth
6af0c88f27 Fix IEye not updating always (#4368) 2023-09-13 11:51:11 +10:00
metalgearsloth
5f05b0aa2a Version: 159.0.3 2023-09-13 11:43:34 +10:00
metalgearsloth
e6c335b6cd Fix nent deleted entity handling (#4379) 2023-09-13 11:22:21 +10:00
metalgearsloth
5cd8e8276e Version: 159.0.2 2023-09-13 00:33:43 +10:00
metalgearsloth
22aeec45f9 Minor resolve light update (#4366) 2023-09-13 00:32:02 +10:00
metalgearsloth
aed53fb63d Fix lights not updating (#4377) 2023-09-13 00:31:45 +10:00
metalgearsloth
5ebe97aec1 Version: 159.0.1 2023-09-12 13:30:52 +10:00
metalgearsloth
3ff374a4af Remove unnecessary meta getcomp (#4376) 2023-09-12 13:30:15 +10:00
metalgearsloth
c5bcf853ac Some netstate fixes (#4375) 2023-09-12 13:05:20 +10:00
metalgearsloth
0624ac36cd Remove PhysicsComponent ref from fixtures (#4374) 2023-09-12 12:49:33 +10:00
metalgearsloth
dd906e9b01 Version: 159.0.0 2023-09-11 21:26:25 +10:00
DrSmugleaf
7f99b44e5c Remove inactive reviewers from CODEOWNERS (#4365) 2023-09-11 20:51:55 +10:00
metalgearsloth
268eb862ea Refactor UI a bit more to shared (#4343) 2023-09-11 20:21:23 +10:00
Leon Friedrich
467f518421 Make entity-deletion take in nullables (#4363) 2023-09-11 20:19:04 +10:00
DrSmugleaf
4666a87aa5 Add obsoletion warnings to serialization source generated methods, xmldocs (#4364) 2023-09-11 20:15:07 +10:00
metalgearsloth
25007a743f Remove lights component reference (#4316) 2023-09-11 19:17:28 +10:00
metalgearsloth
8ce3a03136 Version: 158.0.0 2023-09-11 17:41:27 +10:00
metalgearsloth
c4d6690a71 Remove SharedEyeComponent (#4309) 2023-09-11 16:15:08 +10:00
Kara
5486bc7686 Add tile overlay edge priority (#4341) 2023-09-11 15:30:49 +10:00
ElectroJr
cdf44ef3d9 Version: 157.1.0 2023-09-11 01:27:55 -04:00
metalgearsloth
49ec5b9ca3 Use RichTextLabel for tooltips (#4331) 2023-09-11 13:55:13 +10:00
ElectroJr
8b53b89423 Version: 157.0.0 2023-09-10 19:46:20 -04:00
metalgearsloth
3fd731d917 Network entity ids (#4252) 2023-09-11 09:42:55 +10:00
metalgearsloth
cb1d4ae843 Version: 156.0.0 2023-09-10 21:48:19 +10:00
metalgearsloth
039b70f502 Revert "Remove IContainer and move some functions to the system (#4351)" (#4361) 2023-09-10 21:46:17 +10:00
metalgearsloth
7892cc895f Tooltip QoL (#4330) 2023-09-10 20:23:52 +10:00
ElectroJr
77108284b8 Version: 155.0.0 2023-09-09 22:26:10 -04:00
Leon Friedrich
5e21dbdd7f Remove IContainer and move some functions to the system (#4351) 2023-09-10 12:17:00 +10:00
ShadowCommander
8274623edb Add a command to hide replay UI (#4355) 2023-09-10 10:49:34 +10:00
Leon Friedrich
e923d69083 Miscellaneous replay related changes (#4354) 2023-09-10 10:48:42 +10:00
PrPleGoo
6e8ab5ce78 Ignore deleted components while raising events. (#4311) 2023-09-10 10:48:00 +10:00
metalgearsloth
f905ea631b Raise MapInitEvent on components added after spawn (#4290) 2023-09-10 10:47:18 +10:00
Pieter-Jan Briers
be54c41891 Fix localization file error formatting. 2023-09-09 20:10:55 +02:00
DrSmugleaf
33184ecfa5 Version: 154.2.0 2023-09-08 14:44:37 -07:00
Morb
11cf0c1703 Fix turn into Invalid direction (#4350) 2023-09-08 11:14:14 +10:00
DrSmugleaf
528544b7a2 Remove redundant new() constraint from EntitySystem.AddComp (#4353) 2023-09-07 11:10:35 +10:00
chromiumboy
8571d7e7b5 Added method to search nested containers for a specified component (#4337) 2023-09-06 10:24:14 +10:00
DrSmugleaf
0f06423b7a Remove RobustAutoGenerated from partials generated by serialization (#4338) 2023-09-06 10:23:28 +10:00
PrPleGoo
eb9e0ffefc Advertise to multiple hubs simultaneously (#4285) 2023-09-06 00:25:11 +02:00
metalgearsloth
903619ecef Version: 154.1.0 2023-09-05 00:14:15 +10:00
DrSmugleaf
879c6ea538 Make joint initialization only log under IsFirstTimePredicted (#4346) 2023-09-02 21:45:21 -07:00
metalgearsloth
5478545aeb Mark Dirty(comp) as obsolete (#4344) 2023-09-03 06:56:04 +10:00
Wrexbe (Josh)
650929dcbb Add Timespan helpers (#4342) 2023-08-31 11:51:06 -07:00
DrSmugleaf
a289659b49 Version: 154.0.0 2023-08-30 21:22:39 -07:00
DrSmugleaf
85d15c21e1 Move IPlayerData interface to shared (#4339) 2023-08-30 21:17:32 -07:00
DrSmugleaf
bcd1566440 Respect ignored prototypes even if the kind name is registered (#4340) 2023-08-30 21:01:47 -07:00
Julian Giebel
749ac2c364 Fix some multiline edit issues (#4332) 2023-08-30 09:36:36 +10:00
Pieter-Jan Briers
5eed3bc281 Make toolshed stuff oneOff IoC injections.
Removes a ton of IoC injector delegates.
2023-08-29 21:56:57 +02:00
Pieter-Jan Briers
d78f378493 More event sources 2023-08-29 21:43:02 +02:00
DrSmugleaf
eef44c15cf Version: 153.0.0 2023-08-28 16:00:34 -07:00
DrSmugleaf
3d1b2418f9 Remove redundant DebugTools.AssertNotNull(netId) in ClientGameStateManager (#4333) 2023-08-28 15:57:46 -07:00
DrSmugleaf
6b49a86ee5 Make EntityManager.AddComponent with a comp instance set the owner if its default, add system proxy (#4328) 2023-08-28 15:31:17 -07:00
metalgearsloth
cd13cd3cd8 Delete EntityDeletedMessage (#4329) 2023-08-29 05:21:29 +10:00
metalgearsloth
2b8d8d6636 Remove UI comprefs (#4320) 2023-08-28 03:49:57 +10:00
Pieter-Jan Briers
409fe1a125 Some warning fixes 2023-08-27 15:35:15 +02:00
Pieter-Jan Briers
ab5db4641c Update Lidgren to v0.2.6 2023-08-27 13:18:19 +02:00
metalgearsloth
064e8ee365 Minor CompAdd stuff (#4327) 2023-08-27 12:54:09 +02:00
metalgearsloth
02dcff7eae Remove CollisionWake comp removal sub (#4326) 2023-08-27 15:47:46 +10:00
metalgearsloth
e1e5f8de54 Fix master build (#4325) 2023-08-27 15:33:15 +10:00
Leon Friedrich
d5ba822a79 Remove redundant prototype resolving (#4322) 2023-08-27 15:24:25 +10:00
Leon Friedrich
f448c6b8fa Add RecursiveMoveBenchmark (#4323) 2023-08-27 15:24:04 +10:00
Pieter-Jan Briers
5e1d80be35 Attempts to fix replay recording performance issues.
Replays now use a dedicated thread (rather than thread pool) for write operations.

Moved batch operations to this thread as well. They were previously happening during PVS. Looking at some trace files these compression ops can easily take 5+ ms in some cases, so moving them somewhere else is appreciated.

Added EventSource instrumentation for PVS and replay recording.
2023-08-27 02:15:15 +02:00
DrSmugleaf
01546f32da Version: 152.0.0 2023-08-26 15:31:30 -07:00
DrSmugleaf
aeeaaaefc5 Fix not running hooks when copying non-byref data definition fields without a custom serializer (#4324) 2023-08-26 15:20:46 -07:00
Leon Friedrich
b6c8060af1 Add new PVS test (#4312) 2023-08-26 22:23:32 +10:00
DrSmugleaf
99685838da Fix entity spawn tests having instance per test lifecycle with non static setup and tear downs (#4321) 2023-08-26 22:16:47 +10:00
ike709
8917b29255 Convert Tile.TypeId to an int (#4307)
Co-authored-by: ike709 <ike709@github.com>
Co-authored-by: DrSmugleaf <drsmugleaf@gmail.com>
2023-08-26 22:16:14 +10:00
DrSmugleaf
f0c4d7c5eb Update CI to use setup-dotnet 3.2.0 and checkout 3.6.0 (#4319) 2023-08-25 15:45:19 -07:00
Pieter-Jan Briers
6a00c62d3c Allow content to implement own logic for BUI range checks. (#4301)
They were currently inconsistent with interaction logic in SS14. Please fix and thank.
2023-08-26 09:29:43 +12:00
metalgearsloth
fc3116fca5 Remove ComponentDeleted C# event (#4317)
No one's used it for 12 years probably no reason to obs first.
2023-08-26 09:24:33 +12:00
metalgearsloth
98c1397b3a Remove EntityStarted C# event (#4318) 2023-08-25 19:57:43 +02:00
Leon Friedrich
2464bb6c2f Remove and obsolete ComponentExt functions (#4313) 2023-08-25 23:20:39 +10:00
Leon Friedrich
709142acee Fix prototype manager not being initialized in tests (#4294) 2023-08-24 19:02:02 +02:00
Kevin Zheng
af4e3e5e1c Remove personally-identifiable file paths from client logs (#4267) 2023-08-24 18:56:48 +02:00
Kevin Zheng
d51a18c6ea Fix build with USE_SYSTEM_SQLITE (#4266) 2023-08-24 18:55:54 +02:00
metalgearsloth
d5c3d4c0c9 Add system to CompNetworkGenerator (#4310)
Robust doesn't global using this but content does so any automatic comp states on engine don't work.
2023-08-24 04:26:30 -07:00
metalgearsloth
a4474d8df8 Remove IContainerManager (#4308) 2023-08-24 16:39:35 +10:00
DrSmugleaf
d66f7c7c06 Disable obsoletion and inherited member hidden warnings in serialization source generated code (#4302) 2023-08-24 13:04:32 +10:00
DrSmugleaf
b6879869d6 Add support for long values in CVars (#4299) 2023-08-24 00:57:09 +02:00
Errant
815b8e0c48 removed warning for glibc (#4296) 2023-08-24 00:56:38 +02:00
Arimah Greene
ef4e3baa7f Fix Timer drift (#4300) 2023-08-24 00:54:30 +02:00
Moony
270ddb5a53 Update CODEOWNERS 2023-08-23 16:23:38 -05:00
moonheart08
6133fe0808 Version: 151.0.0 2023-08-23 16:05:56 -05:00
Moony
909fd326a0 Toolshed part 2 (#4256)
* Save work.

* three billion tweaks

* Rune-aware parser.

* a

* all shedded out for the night

* a

* oogh

* Publicizes a lot of common generic commands, so custom toolshed envs can include them.

* Implement parsing for all number types.

* i think i might implode

* a

* Tests.

* a

* Enum parser test.

* do u like parsers

* oopls

* ug fixes

* Toolshed is approaching a non-insignificant part of the engine's size.

* Pool toolshed's tests, also type tests.

* bwa

* tests pass :yay:

* Update Robust.Shared/CVars.cs

Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com>

* how did this not fail tests

* awa

* many levels of silly

---------

Co-authored-by: moonheart08 <moonheart08@users.noreply.github.com>
Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com>
2023-08-23 16:03:34 -05:00
metalgearsloth
876de4065a Version: 150.0.1 2023-08-23 19:16:17 +10:00
metalgearsloth
60e159f0d0 Fix some merge artifacts (#4297) 2023-08-23 19:15:29 +10:00
metalgearsloth
80f3aae30c Version: 150.0.0 2023-08-23 18:55:43 +10:00
Leon Friedrich
98b1862433 Add new spawn functions (#4280) 2023-08-23 18:54:55 +10:00
Leon Friedrich
d2311c193f Add AbstractDictionarySerializer (#4276) 2023-08-23 18:53:13 +10:00
metalgearsloth
f05ed96461 Remove FixtureId from fixtures (#4270) 2023-08-23 18:50:48 +10:00
DrSmugleaf
dc23dfaf4d Version: 149.0.1 2023-08-23 00:27:59 -07:00
DmitriyMX
62315f7c2e fix: crash client when window set maxsize (#4291) 2023-08-23 16:59:57 +10:00
DrSmugleaf
b2d121e780 Fix serialization sharing instances when copying data definitions and not assigning null when the source is null (#4295) 2023-08-22 23:59:03 -07:00
DrSmugleaf
fb4b029122 Version: 149.0.0 2023-08-22 18:07:35 -07:00
DrSmugleaf
66239d23ea Refactor serialization copying to use source generators (#4286) 2023-08-22 17:37:13 -07:00
DrSmugleaf
dbb45f1c13 Version: 148.4.0 2023-08-21 23:19:25 -07:00
Leon Friedrich
6284e16b64 Add recursive PVS overrides and remove IsOverride() (#4262) 2023-08-21 23:17:53 -07:00
DrSmugleaf
f6c55085fe Version: 148.3.0 2023-08-21 19:01:15 -07:00
DrSmugleaf
30eafd26e7 Fix test checking that Robust's and .NET's colors are equal (#4287) 2023-08-21 16:26:06 -07:00
Pieter-Jan Briers
63423d96b4 Fixes for new color PR (#4278)
Undo change to violet color

add to named color list
2023-08-21 23:06:20 +02:00
Morb
474334aff2 Make DiscordRichPresence icon CVars server-side with replication (#4272) 2023-08-21 10:44:40 +02:00
Leon Friedrich
be102f86bf Add IntegrationInstance fields for common dependencies (#4283) 2023-08-21 14:35:27 +10:00
Tom Leys
d7962c7190 Add implementation of Random.Pick(ValueList<T> ..) (#4257) 2023-08-21 13:56:18 +10:00
Leon Friedrich
7fe9385c3b Change default value of EntityLastModifiedTick from zero to one. (#4282)
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
2023-08-21 13:55:41 +10:00
Kara
a9d9d1348a Tile texture reload command (#4268) 2023-08-21 13:46:58 +10:00
Leon Friedrich
4eaf624555 Allow pre-startup components to be shut down. (#4281) 2023-08-21 13:45:57 +10:00
Leon Friedrich
e37c131fb4 Prevent invalid prototypes from being spawned (#4279) 2023-08-21 12:29:02 +10:00
PrPleGoo
9df4606492 Added colors (#4278) 2023-08-20 18:48:00 +02:00
Pieter-Jan Briers
3be8070274 Happy eyeballs delay can be configured. 2023-08-20 17:45:43 +02:00
metalgearsloth
8a440d705f Version: 148.2.0 2023-08-20 15:53:35 +10:00
metalgearsloth
5849474022 Add IsPaused to EntityManager (#4277) 2023-08-20 15:50:11 +10:00
c4llv07e
b7d67c0ece Fix UserInterface.SetActiveTheme didn't update theme (#4263) 2023-08-20 03:36:38 +10:00
Pieter-Jan Briers
b04cf71bc0 Expose SpinBox.LineEditControl 2023-08-19 16:32:05 +02:00
Leon Friedrich
ea87df649a Add readonly VV attributes to various fields. (#4265) 2023-08-20 00:13:18 +10:00
metalgearsloth
dab7a9112f Version: 148.1.0 2023-08-16 19:19:46 +10:00
DrSmugleaf
d3dc89832a Add component that lets entities ignore BUI range checks (#4264) 2023-08-16 15:41:01 +10:00
Leon Friedrich
3ade9ca447 Add support for f16-f24 keys (#4261) 2023-08-13 22:15:18 +10:00
Leon Friedrich
149e9a2613 Fix a gamestate bug. (#4260) 2023-08-13 11:22:15 +10:00
ElectroJr
d164148ce2 Version: 148.0.0 2023-08-12 19:40:55 -04:00
/ʊniɹɑː/
d898b52449 more richtext (#4187) 2023-08-13 09:34:44 +10:00
TemporalOroboros
dcf7a1e580 PixelToMap (#4188) 2023-08-13 09:34:33 +10:00
Pieter-Jan Briers
65c6bb74eb Mark a bunch of NuGet dependencies as private compile assets (#4258) 2023-08-13 07:22:14 +10:00
Leon Friedrich
d6d88bea91 Fix replay handling of bad prototype uploads (#4259) 2023-08-13 07:07:47 +10:00
Pieter-Jan Briers
d6467f768a Fix Logger calls in ComponentRegistrySerializer 2023-08-11 23:50:54 +02:00
ElectroJr
4f0f020f56 Version: 147.0.0 2023-08-10 00:40:01 -04:00
Leon Friedrich
5ce8369fb9 Rename a Dirty() proxy method to DirtyEntity() (#4253) 2023-08-10 14:17:57 +10:00
Pieter-Jan Briers
2446e64033 entitysystemupdateorder debug command 2023-08-08 21:36:14 +02:00
metalgearsloth
bdd65cda4b Version: 146.0.0 2023-08-08 17:26:42 +10:00
Leon Friedrich
77e949bfe8 More serialization related changes, (#4250) 2023-08-08 17:22:10 +10:00
metalgearsloth
d4171351f4 Metadata + cancollide stuff (#4247) 2023-08-08 12:03:27 +10:00
metalgearsloth
e67d0ad3d6 Xform stuff (#4246) 2023-08-08 11:55:56 +10:00
Artur
aff5711fde Add missing CultureInfo.InvariantCulture in angle validaton (#4248) 2023-08-08 11:52:24 +10:00
ElectroJr
a886222946 Version: 145.0.0 2023-08-06 21:45:09 -04:00
Leon Friedrich
5843f1087e Add ContentFileRead test and fix file reading on windows (#4242) 2023-08-07 11:39:09 +10:00
Leon Friedrich
93c0ce815f Add IPrototypeManager.EnumerateKinds() (#4244) 2023-08-07 11:24:34 +10:00
Leon Friedrich
1c64fa1f28 Fix TransformSystem.SetCoordinates() error logs. (#4245) 2023-08-07 11:24:26 +10:00
Leon Friedrich
c825c1e413 Remove IoCManager.Resolve calls in Resource.Load (#4243) 2023-08-07 11:24:15 +10:00
Chief-Engineer
f30fb47834 Add GetActorFromUserId to actor system (#4239) 2023-08-07 11:24:00 +10:00
Leon Friedrich
5d255e06c8 Fix SpriteSpecifier yaml validator (#4241) 2023-08-06 22:14:02 +10:00
metalgearsloth
80357c8ec4 Version: 144.0.1 2023-08-06 15:07:48 +10:00
metalgearsloth
ac3a434bdf Shrink entitylookup tile enlargement even further (#4240) 2023-08-06 15:06:08 +10:00
metalgearsloth
21719b8884 Version: 144.0.0 2023-08-06 12:45:49 +10:00
metalgearsloth
dbb6b90654 Tile enlargement + new flag for lookups (#4205) 2023-08-06 12:41:27 +10:00
ElectroJr
4b92be5324 Version: 143.3.0 2023-08-05 21:16:11 -04:00
Leon Friedrich
95169b7a71 Add temporary debug logs (#4237) 2023-08-06 11:11:23 +10:00
Leon Friedrich
b699e22c85 More serialization fixes (#4224) 2023-08-06 11:08:48 +10:00
Leon Friedrich
e48cc62d0b Clamp audio offset in ApplyAudioParams() (#4221) 2023-08-06 10:38:53 +10:00
Leon Friedrich
aade062a49 Allow replay loading to ignore some errors (#4236) 2023-08-06 10:33:31 +10:00
Chief-Engineer
e02166d5c4 add placement events (#4235) 2023-08-06 10:32:04 +10:00
Leon Friedrich
8037bfae14 Remove an incorrect assert (#4238) 2023-08-06 10:29:30 +10:00
metalgearsloth
49781791af Version: 143.2.0 2023-08-05 12:43:34 +10:00
metalgearsloth
92719aa29f Shutdown grid rendering events (#4234) 2023-08-05 11:38:16 +10:00
Chief-Engineer
1d47a9677d fix named toolshed command (#4230) 2023-08-04 14:51:06 +10:00
Leon Friedrich
14fe8eba6d Remove unnecessary dummy test prototypes (#4233) 2023-08-04 14:50:53 +10:00
Leon Friedrich
2ff99d4a62 Add support for tests to load extra prototypes from multiple "files" (#4232) 2023-08-04 14:50:08 +10:00
metalgearsloth
ce8b2d82a3 Version: 143.1.0 2023-08-04 12:40:21 +10:00
Leon Friedrich
f8f99450db Error on duplicate broadcast subscriptions (#4231) 2023-08-04 12:34:10 +10:00
metalgearsloth
a3cf4877e4 Don't raise contact events for qdel ents (#4126) 2023-08-04 12:22:59 +10:00
metalgearsloth
6ab08f7dc1 Add BodyStatus readwrite (#4227) 2023-08-04 12:22:50 +10:00
Vordenburg
819f6921cf Add locale support for grammatical measure words (#4064) 2023-08-03 20:00:47 +10:00
moonheart08
cf91369d27 Version: 143.0.0 2023-08-02 16:07:25 -05:00
Moony
0e1328675c Toolshed (#4197)
* Saving work

* Move shit to engine

* lord

* merg

* awa

* bql is kill

* forgot the fucking bike rack

* bql is kill for real

* pjb will kill me

* aughfhbdj

* yo ho here we go on my way to the MINES

* a

* adgddf

* gdsgvfvxshngfgh

* b

* hfsjhghj

* hbfdjjh

* tf you mean i have to document it

* follow C# standards

* Assorted cleanup and documentation pass, minor bugfix in ValueRefParser.

* Start porting old commands, remove that pesky prefix in favor of integrating with the shell.

* Fix valueref up a bit, improve autocomplete for it.

* e

* Toolshed type system adventure.

* a log

* a

* a e i o u

* awa

* fix tests

* Arithmetic commands.

* a

* parse improvements

---------

Co-authored-by: moonheart08 <moonheart08@users.noreply.github.com>
2023-08-02 16:06:16 -05:00
metalgearsloth
a7315b1c95 Version: 142.1.2 2023-08-02 13:43:19 +10:00
metalgearsloth
c8f2a55cbe Don't log error on relay resolve (#4223) 2023-08-02 13:42:07 +10:00
ElectroJr
7812502b0b Version: 142.1.1 2023-08-01 22:42:01 -04:00
Leon Friedrich
3149f99954 Fix bad DetachParentToNull() assert (#4222) 2023-08-02 12:40:59 +10:00
ElectroJr
ef8c6379cd Version: 142.1.0 2023-08-01 20:54:36 -04:00
KIBORG04
f932e023ee Configurable Discord Rich Presence icons and some localization (#4174) 2023-08-02 10:36:45 +10:00
Leon Friedrich
a137c839fc Add prototype serialization validation methods. (#4210) 2023-08-02 10:29:55 +10:00
Leon Friedrich
3e43b88518 Fix bad disconnects in tests (#4217) 2023-08-02 10:29:17 +10:00
metalgearsloth
3d974e0305 Fix entitylookup recursion (#4218) 2023-08-02 10:28:10 +10:00
deathride58
b3682017ac Enables lightsample manipulation shenanigans (#4201) 2023-08-02 04:52:38 +10:00
metalgearsloth
194743a9b0 Set sawmill default to info on release (#4198) 2023-08-02 04:33:31 +10:00
Vera Aguilera Puerto
34d65a7960 Use engine font instead of SS14-specific font in a few places. (#4206) 2023-08-02 04:32:31 +10:00
metalgearsloth
6cd4a37a8f Add VV readwrite to physics stuff (#4220) 2023-08-02 04:31:53 +10:00
Vordenburg
40d879fddc Read Artist and Title tags from Ogg Vorbis files (#4207) 2023-08-02 04:31:20 +10:00
Leon Friedrich
df398c5b13 Truncate discord rich presence strings (#4213) 2023-08-02 04:30:22 +10:00
Leon Friedrich
804b698172 Improve DetachParentToNull() debug asserts (#4194) 2023-08-02 04:27:18 +10:00
metalgearsloth
346514c6e0 Allow overriding joint relays (#4219) 2023-08-02 04:27:01 +10:00
Leon Friedrich
d65e2eb169 Fix test IoC error (#4216) 2023-08-01 18:57:14 +10:00
Leon Friedrich
ff41329ad7 Add DataNode.ToString() (#4209) 2023-08-01 12:13:46 +10:00
Leon Friedrich
6151a26622 Remove unnecessary component fetch in AnyComponentsIntersecting (#4215) 2023-08-01 12:13:32 +10:00
Pieter-Jan Briers
1c7ae13bfa Happy Eyeballs for HttpClient use.
All HttpClient usages in the engine now use Happy Eyeballs, same implementation as the launcher.

Makes a IHttpClientHolder type so content can profit from this technology too. Didn't make use of this in all HttpClient usages in the engine itself, due to varying circumstances making it annoying to refactor.
2023-07-31 22:51:25 +02:00
metalgearsloth
cb6645aebe Version: 142.0.1 2023-07-31 14:33:25 +10:00
Leon Friedrich
fffe3c56e9 Fix enum serialization (#4208) 2023-07-30 20:17:22 +10:00
ElectroJr
204e881690 Version: 142.0.0 2023-07-29 13:42:33 -04:00
metalgearsloth
161b1874c2 Some comp query optimisations (#4203) 2023-07-30 03:34:35 +10:00
metalgearsloth
7c3634f1f5 Add better GetAssemblyByName debug (#4192) 2023-07-30 03:32:02 +10:00
Leon Friedrich
9969899f38 Add method to validate prototype ids in c# fields (#4189) 2023-07-30 03:31:17 +10:00
Leon Friedrich
ed35839942 Add warning for unhandled replay messages (#4199) 2023-07-29 18:04:56 +10:00
metalgearsloth
380ccfacd8 Version: 141.2.1 2023-07-29 16:19:20 +10:00
Leon Friedrich
cc0cc6afb1 Don't recreate _entTraitDict on disconnect (#4200) 2023-07-29 16:16:25 +10:00
Pieter-Jan Briers
8cc2a17444 Version: 141.2.0 2023-07-28 22:16:59 +02:00
Pieter-Jan Briers
9c64fbfce2 Fix protocol abuse exception. 2023-07-27 19:30:39 +02:00
metalgearsloth
0218c4b969 Version: 141.1.0 2023-07-27 18:22:48 +10:00
Vordenburg
cd72523701 Add CollisionLayerChangeEvent (#4147) 2023-07-27 18:20:29 +10:00
metalgearsloth
76bb9b4b19 Run MapInit on pmanager entities (#4196) 2023-07-27 06:49:09 +12:00
metalgearsloth
afdfbba312 Version: 141.0.0 2023-07-26 22:41:12 +10:00
metalgearsloth
8b4925863e Cull Component.Initialize (#4191) 2023-07-26 22:37:45 +10:00
Pieter-Jan Briers
e1597da4c7 Enable EXCEPTION_TOLERANCE on Tools.
This wasn't the case yet??? Whoops.
2023-07-24 20:52:39 +02:00
Pieter-Jan Briers
8375a4038b Throw error if creation of buffered audio source fails.
This can happen if we're out of audio streams. Before, we just kinda pretended like everything was OK, which easily caused crash bugs in e.g. MIDI.

Ideally the audio engine would be less terrible and this could be handled better than "throw new Exception()", but I'm fixing a stack overflow here alright?
2023-07-24 20:52:11 +02:00
Pieter-Jan Briers
8270442d66 Hard exit server on double ^C. 2023-07-23 17:44:20 +02:00
Pieter-Jan Briers
85e1920b95 Version: 140.0.0 2023-07-23 15:41:44 +02:00
Pieter-Jan Briers
5347eb3350 Replay recording API improvements. (#4193) 2023-07-23 15:36:35 +02:00
metalgearsloth
e4a14d1ec8 Start MapGrid ECS (#4185) 2023-07-23 20:50:23 +10:00
metalgearsloth
c52db4d3f2 Version: 139.0.0 2023-07-23 16:13:06 +10:00
metalgearsloth
89f78d76ab Cull Component.Startup (#4190) 2023-07-23 16:04:37 +10:00
metalgearsloth
bbc4668f9c Version: 138.1.0 2023-07-18 21:41:40 +10:00
metalgearsloth
ce4016965e Add NoLerp methods for rotation (#4186) 2023-07-18 21:40:09 +10:00
Pieter-Jan Briers
21e74c9881 Fix ordering of control AnimationCompleted event.
This was changed recently, and it caused exceptions in SS14 (wire hacking animations).
2023-07-18 01:04:49 +02:00
Vera Aguilera Puerto
aa52e8c2ef Version: 138.0.0 2023-07-16 21:09:48 +02:00
Vera Aguilera Puerto
e106d3f72b MidiRenderer master/puppet and various improvements/cleanup (#4184) 2023-07-16 21:08:57 +02:00
metalgearsloth
8eae802fb6 Version: 137.1.0 2023-07-17 00:57:35 +10:00
Pieter-Jan Briers
681feaf0c7 Use relative time in PrecisionSleepWindowsHighResolution
Duh.
2023-07-15 23:38:12 +02:00
Pieter-Jan Briers
0a5a214a06 Precision sleep implementation for Linux (nanosleep). 2023-07-15 23:28:55 +02:00
Pieter-Jan Briers
d80be16f6c Fix sys.precise_sleep being interpreted the wrong way around. 2023-07-15 23:28:26 +02:00
Pieter-Jan Briers
d967bc9fdc Speed up DirLoader.DirLoader on Windows.
New FileHelper.TryOpenFileRead that doesn't throw if the file doesn't exist.

Also used it in a couple other spots.
2023-07-15 19:08:37 +02:00
Pieter-Jan Briers
177ca6b627 Sandboxing performance improvements.
Don't leave file handles dangling.
Prefetch verifying assembly images to speed stuff up.
2023-07-15 18:09:57 +02:00
Pieter-Jan Briers
3c262afaa4 Why would you put an attribute inside an ifdef like that, god. 2023-07-15 16:14:03 +02:00
Pieter-Jan Briers
bce2901b0f Remove manual Windows P/Invokes in favor of TerraFX. 2023-07-15 15:41:34 +02:00
Pieter-Jan Briers
c392d4f996 Precise, time period-independent timing for Windows game loop. 2023-07-15 15:22:52 +02:00
Pieter-Jan Briers
d7ee2bccd7 Use TerraFX.Interop.Windows in Shared. 2023-07-15 15:20:32 +02:00
Pieter-Jan Briers
4e816fa5e7 Add ModUpdateLevel.InputPostEngine 2023-07-15 15:09:17 +02:00
Pieter-Jan Briers
545e55055e BQL paused handling changes (#4099) 2023-07-15 19:21:36 +10:00
metalgearsloth
6b059ed356 Version: 137.0.0 2023-07-13 20:22:47 +10:00
metalgearsloth
b69b4fd8fe Kill comp getstate / handlestate (#4183) 2023-07-13 20:19:58 +10:00
metalgearsloth
cb63499ec9 Add EntityQuery<MetaDataComponent> to EntityManager (#4166) 2023-07-13 20:14:47 +10:00
Vera Aguilera Puerto
dd12110c34 Version: 136.0.1 2023-07-12 08:55:01 +02:00
Vera Aguilera Puerto
a811cfc1a1 Changelog for CEF bugfix 2023-07-12 08:53:51 +02:00
Amy
229a45bea2 Enables debugging and error handling on Linux with CEF enabled (#4181)
Co-authored-by: amylizzle <amylizzle@users.noreply.github.com>
2023-07-12 08:42:30 +02:00
metalgearsloth
78376ccca1 Fix grid fixture warnings (#4180) 2023-07-10 18:09:18 +10:00
metalgearsloth
e4a1415627 Fix erroneous Vector2.Length call (#4178) 2023-07-10 17:53:54 +10:00
metalgearsloth
69589195e0 MapLoader perf stuff (#4179) 2023-07-10 17:53:46 +10:00
Leon Friedrich
ce3b92aea2 Try prevent infinite measure/arrange loops (#4176) 2023-07-10 17:36:22 +10:00
Leon Friedrich
5dc980ae92 Revert #3827 (#4177) 2023-07-10 17:35:55 +10:00
ElectroJr
6edeafeed1 Version: 136.0.0 2023-07-08 22:22:28 -04:00
Leon Friedrich
623aa6a0ae More StyleBox UiScale fixes. (#4175) 2023-07-09 12:19:42 +10:00
ElectroJr
1399b71572 Version: 135.0.0 2023-07-08 15:02:31 -04:00
eoineoineoin
bbf8827efd Make StyleBoxTexture respect UI zoom level (#4165) 2023-07-09 04:49:25 +10:00
ElectroJr
591c261ff5 Version: 134.0.0 2023-07-08 12:10:13 -04:00
TemporalOroboros
75f0cf9dd7 Ecs's UserInterfaceComponent. (#4079) 2023-07-09 02:02:28 +10:00
metalgearsloth
bde8c2c6e8 Version: 133.0.0 2023-07-08 14:12:59 +10:00
metalgearsloth
7d1ad527d9 Replace Robust Vector2 with System.Numerics (#4092) 2023-07-08 14:08:26 +10:00
Morb
6da708f285 Fix ContentGetDirectoryEntries (#4162) 2023-07-06 15:28:38 +10:00
Leon Friedrich
f6a5e0ed93 Fix doc comments & typos (#4170) 2023-07-06 15:28:09 +10:00
Leon Friedrich
21534e7568 Block some parent-child collisions (#4171) 2023-07-06 15:26:20 +10:00
Pieter-Jan Briers
e7aa2cbc7d AssetPassPipe can detect and block duplicates. 2023-07-05 23:56:15 +02:00
Pieter-Jan Briers
5ddba87487 ACZ fix edge case with Accept-Encoding header parsing
This could throw if the requester sent specific headers.
2023-07-05 23:55:43 +02:00
metalgearsloth
a69573178f Version: 132.2.0 2023-07-06 00:02:23 +10:00
metalgearsloth
1ac39cc65f Add recursive joint clearing (#4169) 2023-07-06 00:01:04 +10:00
Pieter-Jan Briers
70897b6ea9 Reduce default MTU even more.
Yeah I think this might still be causing issues.
2023-07-02 17:01:17 +02:00
metalgearsloth
e763d59617 Remove some unnecessary EntityQuery<T> and warns (#4167) 2023-07-02 01:12:45 +10:00
metalgearsloth
d4902a9714 Version: 132.1.0 2023-07-01 22:05:39 +10:00
metalgearsloth
23a40e58e4 Pause animations on ent pause (#4117) 2023-07-01 22:02:33 +10:00
Pieter-Jan Briers
e71f1cc8a5 Warning fixes (#4160)
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
2023-07-01 22:02:12 +10:00
metalgearsloth
b82d246988 Fix ComponentTreeSystem warnings (#4164) 2023-07-01 19:23:37 +10:00
metalgearsloth
d309872334 Version: 132.0.1 2023-06-27 20:13:29 +10:00
metalgearsloth
e33c37ed09 Return map first for grid queries (#4161) 2023-06-27 20:09:58 +10:00
ElectroJr
3ee95b1a71 Version: 132.0.0 2023-06-25 16:44:40 -04:00
metalgearsloth
9a4721a3ee Add prototype counts to IPrototypeManager (#4158) 2023-06-26 06:35:21 +10:00
Leon Friedrich
8fd1e9047f Rejig time offset serializer (#4154) 2023-06-26 06:29:45 +10:00
metalgearsloth
e44e4ac7ed Version: 131.1.0 2023-06-25 22:00:17 +10:00
metalgearsloth
581ef074a0 Add method to get random variant tile (#4153) 2023-06-25 21:52:31 +10:00
metalgearsloth
9bb61b8a35 Add NextByte to random methods (#4151) 2023-06-25 21:52:15 +10:00
Leon Friedrich
e7497c7e4f Fix replay component state bug (#4157) 2023-06-25 21:51:15 +10:00
rene-descartes2021
7bc54d8f73 Cleanup redundant parentheses (#4155) 2023-06-25 21:51:00 +10:00
Pieter-Jan Briers
1631d93e41 Remove AggressiveOptimization attributes.
This isn't a magic "make code go fast" button, none of these usages were correct.
2023-06-25 09:33:10 +02:00
moonheart08
a32ff39516 Version: 131.0.0 2023-06-24 18:57:48 -05:00
Pieter-Jan Briers
2715581f48 Replays: final boss (#4156)
* Add ISawmill.Verbose log helpers

* Verbose logs for server-side networking handshake.

* Replays: final boss

It does zippies now. It fucking works. Amazingly, in fact.

* Add ZipArchive to sandbox
2023-06-24 18:56:37 -05:00
metalgearsloth
061c4352c6 Add SpawnEntities to entitymanager (#4152) 2023-06-23 10:55:28 +10:00
Leon Friedrich
8c5a34f538 Fix bad gamestate asserts (#4149) 2023-06-23 09:48:06 +10:00
Leon Friedrich
55d99155e0 Better deserialization error messages (#4150) 2023-06-21 09:43:49 +10:00
ElectroJr
4c994eb599 Version: 130.0.0 2023-06-18 17:03:02 -04:00
ElectroJr
25fa6b2b2e Change default engine version cvar 2023-06-18 17:00:39 -04:00
ElectroJr
530321bcb6 Version: 0.129.0.1 2023-06-18 15:39:47 -04:00
ElectroJr
da860d4f56 Update Version.py to remove leading zero. 2023-06-18 13:43:32 -04:00
ElectroJr
33702b10f3 Version: 129.0.0 2023-06-18 13:42:47 -04:00
wixoa
b035159de5 Add StyleBoxOverride to LineEdit (#4138) 2023-06-19 03:27:56 +10:00
Leon Friedrich
ad1b9b1d2b Make ActorSystem.Attach() detach from existing entities. (#4146) 2023-06-19 03:24:17 +10:00
Leon Friedrich
9d4105abc7 Add support for client-side replays (#4122) 2023-06-19 03:23:46 +10:00
Pieter-Jan Briers
35902ad839 Update Lidgren to fix Linux socket error reporting. 2023-06-18 18:19:08 +02:00
Julian Giebel
f5b8c8813f Cange richtext tags to be overridable by content (#4141) 2023-06-18 03:20:43 +10:00
Leon Friedrich
a9eafd4025 Add new Dirty() override for Component.Owner removal (#4144) 2023-06-18 03:19:40 +10:00
metalgearsloth
3bd7309536 Version: 0.128.0.0 2023-06-17 11:56:10 +10:00
Leon Friedrich
f5b87b5140 Remove static ILocalizationManager resolves. (#4145) 2023-06-17 11:52:45 +10:00
metalgearsloth
05e38e0880 Version: 0.127.1.0 2023-06-16 12:41:20 +10:00
metalgearsloth
2bcb457786 Add Frame0 method for entity prototypes (#4142) 2023-06-15 20:29:51 +10:00
metalgearsloth
e11cef3335 Version: 0.127.0.0 2023-06-15 12:15:30 +10:00
metalgearsloth
b15b800535 Contact stuff (#4140) 2023-06-15 12:14:06 +10:00
Leon Friedrich
8345cfea60 Automatically create a sawmill for each entity system. (#4137) 2023-06-15 12:09:48 +10:00
Leon Friedrich
497674f306 Change capitalization of PVS to Pvs (#4139) 2023-06-15 12:08:34 +10:00
Pieter-Jan Briers
fd5e5471be Oops, didn't do the IPAddress sandbox properly. 2023-06-11 16:21:24 +02:00
Leon Friedrich
1c90be0abc Make BoxContainer's MesureOverride account for stretching (#4114) 2023-06-11 16:13:20 +02:00
Pieter-Jan Briers
b895da5fda Add launch.launcher and launch.content_bundle CVars 2023-06-11 16:12:08 +02:00
ElectroJr
0ae409a795 Version: 0.126.0.0 2023-06-10 16:01:16 -04:00
Leon Friedrich
2c529510e7 Maybe fix random test failures (#4135) 2023-06-11 05:45:05 +10:00
metalgearsloth
33cdc0d31f Obsolete some metadata stuff (#4110) 2023-06-11 05:44:36 +10:00
metalgearsloth
8dec3ea922 More MM stuff (#4136) 2023-06-10 19:03:55 +10:00
metalgearsloth
60f9ffb423 Physics stuff (#4125) 2023-06-10 18:54:01 +10:00
metalgearsloth
f2c2750f8c Gridtree ECS (#4109) 2023-06-10 18:15:04 +10:00
Vera Aguilera Puerto
00e8afe8fa Fix ClydeAudio sawmill when using the fallback audio proxy 2023-06-10 05:06:22 +02:00
Vera Aguilera Puerto
4cde4abbb8 Remove many more static Logger usages from client. 2023-06-10 01:12:22 +02:00
Pieter-Jan Briers
1da229549d Remove some Logger usages from client.
About all I could muster before I got bored.
2023-06-10 00:19:09 +02:00
Vera Aguilera Puerto
3160437e0f Remove static Logger usages from GameController. (#4132) 2023-06-10 00:10:30 +02:00
Vera Aguilera Puerto
82e1a1003f Remove static Logger usages from GameStateProcessor. (#4131) 2023-06-10 00:10:13 +02:00
Vera Aguilera Puerto
3c7b3bd653 Remove static Logger usages from NetManager (#4130) 2023-06-10 00:09:38 +02:00
Vera Aguilera Puerto
c993c24284 Remove static Logger usages from ClientConsoleHost (#4133) 2023-06-10 00:08:09 +02:00
Vera Aguilera Puerto
720740ce0c Remove static Logger usages from StatusHost. (#4129) 2023-06-10 00:07:48 +02:00
Vera Aguilera Puerto
1959f6f328 Remove static Logger usages from BaseServer and BaseClient. (#4134) 2023-06-10 00:07:27 +02:00
Vera Aguilera Puerto
596b8e5538 Remove static Logger usages from ViewVariables (#4128) 2023-06-10 00:06:44 +02:00
Vera Aguilera Puerto
ce703223b5 Deprecate IPlayerSession methods to attach/detach entities to a player. (#4127)
Co-authored-by: Pieter-Jan Briers <pieterjan.briers@gmail.com>
2023-06-10 00:06:15 +02:00
Pieter-Jan Briers
b1e594858a Add System.Net.IPAddress to sandbox.
For https://github.com/space-wizards/space-station-14/pull/14228
2023-06-09 23:37:42 +02:00
Leon Friedrich
c09800fe5d Prevent scrollbar overlap in OutputPanel (#4113) 2023-06-09 10:20:09 +10:00
Julian Giebel
add8771d1f Fix richtext inline controll scaling (#4121) 2023-06-09 10:19:42 +10:00
metalgearsloth
40833ce35b Mark static loggers as obsolete (#4124) 2023-06-09 01:10:13 +10:00
metalgearsloth
de81199037 Version: 0.125.0.1 2023-06-07 20:43:58 +10:00
metalgearsloth
4af1728da4 use ISawmill on mapmanager (#4123) 2023-06-07 20:40:01 +10:00
Leon Friedrich
11fed18c47 Fix mapped strings serializer not properly checking string size. (#4115) 2023-06-06 10:55:57 +02:00
ElectroJr
bdb781d680 Version: 0.125.0.0 2023-06-05 00:40:37 -04:00
Leon Friedrich
e08dac2be9 Add support for replay playback. (#4107) 2023-06-05 14:36:18 +10:00
moonheart08
7a04c81fe1 Version: 0.124.0.1 2023-06-04 15:40:19 -05:00
Nemanja
035b1a510d Add NumberFormatInfo to shared sandbox (#4111) 2023-06-04 15:35:34 -05:00
Pieter-Jan Briers
4a27df0166 Add clientAssemblies list to resource manifest.
Allows whitelisting only certain assemblies to be loaded. Intended to be used with the new content bundle stuff that's incoming launcher-side.
2023-06-03 13:48:34 +02:00
Pieter-Jan Briers
478fa8e6de Oops I accidentally committed the VFS command thing. Better commit the rest now. 2023-06-03 12:27:23 +02:00
Pieter-Jan Briers
23abb6177d Fixes for resource manager, roots and ResPath.
`ResPath.RelativeTo()` now considers non-rooted paths relative to `.`
This fixes some things like `MemoryContentRoot`'s `FindFiles()` implementation.

Fix `IContentRoot.GetEntries()` default implementation (used by all content roots except `DirLoader`) not working at all.

Made `ResourceManager.ContentGetDirectoryEntries()` report content root mount paths as directories.

Added tests for all of the above.
2023-06-03 12:23:28 +02:00
Pieter-Jan Briers
7b23729f94 Fix bare ">" command exception. 2023-06-02 22:59:28 +02:00
canvas123
cf86c7a8b5 Fixed some coding mistakes (#4105)
Co-authored-by: Canvas123 <lunarfury6@gmail.com>
Co-authored-by: Pieter-Jan Briers <pieterjan.briers@gmail.com>
2023-06-02 20:12:11 +02:00
metalgearsloth
e2830c9ad8 Version: 0.124.0.0 2023-06-02 22:19:13 +10:00
Leon Friedrich
d95c1aef05 Add EntityUid fields to some physics events (#4103) 2023-06-02 22:16:37 +10:00
metalgearsloth
46ae16718e Physics query stuff (#4102) 2023-06-02 16:37:51 +10:00
metalgearsloth
102c24d5d8 Version: 0.123.1.1 2023-06-02 15:49:47 +10:00
metalgearsloth
9dacf63e36 More joint cloning (#4104) 2023-06-02 15:48:39 +10:00
Leon Friedrich
cec071f907 Add ability to reset loaded prototypes. (#4097) 2023-06-01 14:56:36 +10:00
Leon Friedrich
5e08553af6 Add method to clear networked resources. (#4096) 2023-06-01 14:55:27 +10:00
metalgearsloth
540febc75b Version: 0.123.1.0 2023-06-01 12:01:14 +10:00
metalgearsloth
0f8231b069 Box2 stuff (#4101) 2023-06-01 12:00:15 +10:00
ElectroJr
7e912cf4ce Version: 0.123.0.0 2023-05-30 23:59:21 -04:00
metalgearsloth
467914e115 Add RemoveSwap to ValueList (#4093) 2023-05-31 13:50:57 +10:00
ShadowCommander
5d67041a0c Add EntityQueryEnumerator comments on EntityQuery and .Owner (#4095) 2023-05-30 21:34:09 +02:00
Leon Friedrich
52fc800398 Make version related cvars not server-only (#4086) 2023-05-30 21:33:48 +02:00
Pieter-Jan Briers
3164b58300 Fix keyboard events always propagating to default viewport if devwindow is open. 2023-05-30 21:29:43 +02:00
metalgearsloth
1ca68a89e7 MM + poly shape fixes (#4094) 2023-05-30 14:43:51 +10:00
metalgearsloth
8ad25f2a9f 2 more mapmanager things (#4091) 2023-05-29 02:14:41 +10:00
metalgearsloth
6dc33e4fe0 Version: 0.122.0.0 2023-05-28 23:24:03 +10:00
metalgearsloth
0ebdd4ac1d MapManager query changes (#4090) 2023-05-28 23:22:39 +10:00
metalgearsloth
24be915ef1 Container minor stuff (#4089) 2023-05-28 21:41:51 +10:00
metalgearsloth
8b48b54575 Version: 0.121.0.0 2023-05-28 14:55:01 +10:00
metalgearsloth
d389e30c87 Changes for audio (#4087) 2023-05-28 14:50:21 +10:00
Leon Friedrich
f8f14dc817 Add IWritableDirProvider.OpenOsWindow() (#4084) 2023-05-28 09:28:23 +10:00
Leon Friedrich
d9a5f9c4dd Add replay loading/reading. (#4077) 2023-05-28 04:32:35 +10:00
metalgearsloth
fbcbcecae6 Version: 0.120.0.0 2023-05-27 14:14:24 +10:00
metalgearsloth
768377f59b Add joint relays (#4081) 2023-05-27 14:10:55 +10:00
Leon Friedrich
34adf454c5 Slight map manager cleanup (#4083) 2023-05-24 11:25:16 +10:00
Leon Friedrich
9af00eea03 Fix spriteview scaling (#4082) 2023-05-23 15:32:42 +10:00
Leon Friedrich
a6c487f8b7 Fix upload folder command (#4076) 2023-05-21 16:23:30 +10:00
metalgearsloth
5b7d686de9 Version: 0.119.0.1 2023-05-20 13:33:36 +10:00
metalgearsloth
3a42e8e07a Fix fire collisions (#4074) 2023-05-20 13:32:10 +10:00
metalgearsloth
115a3f12c7 Version: 0.119.0.0 2023-05-20 11:57:03 +10:00
Leon Friedrich
ccec1cbdf3 Move upload commands to engine (#4072) 2023-05-20 11:53:05 +10:00
Leon Friedrich
36a124a3aa Add IContentRoot.FileExists() (#4071) 2023-05-20 11:10:05 +10:00
moonheart08
7836130bef Version: 0.118.0.0 2023-05-19 15:42:08 -05:00
Moony
06f5c78152 Allow specifiying overrides for components when spawning an entity. (#4068)
* Oh goddamnit this is a refactor now.

* aaaaaaaaaaa

---------

Co-authored-by: moonheart08 <moonheart08@users.noreply.github.com>
2023-05-19 15:38:45 -05:00
metalgearsloth
57ddf81fc4 Version: 0.117.0.0 2023-05-19 17:14:31 +10:00
Leon Friedrich
0e7863650b IconComponent cleanup & linter inheritance (#4070) 2023-05-19 17:12:36 +10:00
metalgearsloth
a04ad5eeab Version: 0.116.0.0 2023-05-19 16:23:09 +10:00
TemporalOroboros
435b252c86 Removes AppearanceVisualizers (#4069) 2023-05-19 07:15:06 +10:00
Leon Friedrich
4e72ddffbd Modify replay recording directory selection (#4066) 2023-05-18 21:33:06 +10:00
ElectroJr
c99059e8ba Version: 0.115.0.0 2023-05-17 22:08:07 -04:00
Leon Friedrich
d8aa0b68c9 Change default state reset behaviour (#4065) 2023-05-17 17:31:26 -05:00
metalgearsloth
ebfa44cc2c Version: 0.114.1.0 2023-05-18 00:48:51 +10:00
metalgearsloth
a3ef7fa3c9 Add API to remove joint by ID (#4041) 2023-05-18 00:21:29 +10:00
Leon Friedrich
f398ad8a22 Slightly speed up entity deletion (#4061)
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
2023-05-18 00:00:51 +10:00
Leon Friedrich
f06beeb6f6 Remove static logs from EntityManager (#4062) 2023-05-17 14:18:49 +10:00
ElectroJr
3e2e764f89 Version: 0.114.0.0 2023-05-16 20:36:18 -04:00
ElectroJr
a42d6f51a8 Automatically append .png for fallback texture resolves 2023-05-16 20:35:40 -04:00
Leon Friedrich
7cb01b8a85 Update theme on child add (#4059) 2023-05-17 10:19:08 +10:00
Leon Friedrich
022a668266 Revert "Fix hidden action numbers by updating UI theme" (#4057) 2023-05-17 05:51:38 +10:00
Leon Friedrich
529b529073 Fix PVS reconnect error (#4056) 2023-05-17 04:13:15 +10:00
metalgearsloth
46b4d57a8c Add non-generic comp lookups (#4054) 2023-05-17 03:47:37 +10:00
metalgearsloth
369b2de052 Version: 0.113.0.3 2023-05-16 21:22:30 +10:00
metalgearsloth
c86ab63010 Use sawmill for pvs log (#4051) 2023-05-16 21:02:28 +10:00
ElectroJr
b692ed2437 Version: 0.113.0.2 2023-05-15 02:15:44 -04:00
ElectroJr
c077bbc2fd Remove last bad assert 2023-05-15 02:15:26 -04:00
Leon Friedrich
7ccef97287 Remove another bad assert (#4046) 2023-05-15 16:02:53 +10:00
Leon Friedrich
905ace3681 Remove some asserts (#4045) 2023-05-15 15:31:09 +10:00
Leon Friedrich
004b185e73 Fix deletion networking (#4044) 2023-05-15 15:27:28 +10:00
Leon Friedrich
a1dd01a23c Fix f3 menu debug assert when mouse is off-screen (#4043) 2023-05-15 13:35:55 +10:00
metalgearsloth
8d25792752 Version: 0.113.0.1 2023-05-15 13:35:01 +10:00
Skye
4335f00e28 Use theme resolve (#4042) 2023-05-15 13:33:04 +10:00
metalgearsloth
0b14aec199 Version: 0.113.0.0 2023-05-15 13:14:33 +10:00
Leon Friedrich
eceefa1308 Fix pulling prediction issues (#4036) 2023-05-15 12:51:17 +10:00
Skye
109e685d55 Fix hidden action numbers by updating UI theme (#3973) 2023-05-15 12:50:01 +10:00
Leon Friedrich
b87d1a0a73 Move JobQueue & Job to engine (#4037) 2023-05-15 12:47:09 +10:00
Leon Friedrich
b422d8d3ca Make map-grids set TransformComponent.GridUid (#4040) 2023-05-15 12:39:45 +10:00
Leon Friedrich
5f5a2bade0 Make InitializeEntity() and StartEntity() public (#4039) 2023-05-15 12:38:16 +10:00
Leon Friedrich
45135eb416 Fix some joint bugs (#4038) 2023-05-15 12:37:26 +10:00
Leon Friedrich
eb7886bff4 Fix sprite debug assert (#4033) 2023-05-15 00:52:46 +10:00
Raphael Bertoche
f08344f60e Fix duplicate yaml validation error exception (#4032) 2023-05-14 10:37:05 +10:00
metalgearsloth
b37f9e827c vv perm tweaks (#4026) 2023-05-14 10:33:28 +10:00
metalgearsloth
bbd8cd3cf9 Remove joint log (#4029) 2023-05-14 10:29:11 +10:00
DrSmugleaf
ce086833b6 Fix log for adding duplicate component reference (#4031) 2023-05-14 10:28:56 +10:00
eoineoineoin
f7eebce14e Add padding to glyphs in atlas (#4011) 2023-05-14 04:19:31 +10:00
DrSmugleaf
394bfda92f Version: 0.112.0.1 2023-05-13 01:08:34 -07:00
DrSmugleaf
c70a3d6f4b Fix crash from UIScreens not having dependencies injected (#4030) 2023-05-13 01:04:08 -07:00
Leon Friedrich
12237db4d7 Move tpto command to shared. (#4025) 2023-05-13 11:15:07 +10:00
Leon Friedrich
9526bb773b Use local session for local client-side shells. (#4024) 2023-05-13 10:44:38 +10:00
Menshin
ff35b921aa Add option for norot/snapping sprite layers (#3808) 2023-05-13 08:14:03 +10:00
metalgearsloth
8511fe4d3b Version: 0.112.0.0 2023-05-13 00:08:58 +10:00
Leon Friedrich
dea195be4a Change prof tree style & add basic stylesheet support (#4021) 2023-05-13 00:04:35 +10:00
Leon Friedrich
945c3dada9 Try fix collision mispredicts (#4016) 2023-05-13 00:02:42 +10:00
Leon Friedrich
3d3d6d38e0 Move default theme directory (#4022)
* Move default theme directory

* missed one
2023-05-11 22:50:58 -05:00
jicksaw
7bc65a38fc Fix JSON Serialization of ResPath (#4020) 2023-05-12 13:26:18 +10:00
moonheart08
2aaa41252a Version: 0.111.0.0 2023-05-11 06:40:23 -05:00
Moony
538535db9a Engine default stylesheet + debug connect screen (#4017)
* Debug connection screen

* [ContentAccessAllowed] so I can use IStateManager on engine types.

* Implement a default engine stylesheet.

* awa

* Fix an issue that can cause hangs when resolving a color.

---------

Co-authored-by: moonheart08 <moonheart08@users.noreply.github.com>
Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
2023-05-11 06:38:50 -05:00
metalgearsloth
c4c2e84936 Version: 0.110.0.0 2023-05-09 17:25:03 +10:00
Leon Friedrich
1678a26d0c Remove obsolete Fixture.Body references (#4014) 2023-05-09 17:21:14 +10:00
Leon Friedrich
6afd67acea Fix EntityLookup not properly adding nested contained entities. (#4015) 2023-05-09 12:26:51 +10:00
Leon Friedrich
e2bac1b3df Sort serializable types (#4012) 2023-05-08 16:05:23 +10:00
metalgearsloth
474f4f09b9 Remove name + author from map file (#3992) 2023-05-07 17:22:14 +02:00
AJCM-git
e979673d54 Fixes Omnisharp failing to analyze the client by default. (#3203) 2023-05-07 17:21:57 +02:00
metalgearsloth
048e01e409 Version: 0.109.1.0 2023-05-08 01:01:44 +10:00
metalgearsloth
071e211cfe Crude IsDefault checks for entities (#3945) 2023-05-08 00:58:27 +10:00
ElectroJr
f0211ca445 Version: 0.109.0.0 2023-05-06 19:44:10 -04:00
Leon Friedrich
5d9d47a2a5 Fix screen overlay bug (#4010) 2023-05-07 09:39:16 +10:00
Vera Aguilera Puerto
25c1346dd9 Allow loading an "override" soundfont from an environment variable. (#4004) 2023-05-07 09:38:12 +10:00
Leon Friedrich
af1fc3cf6b Add BeforeSaveEvent (#4005) 2023-05-07 09:37:20 +10:00
Leon Friedrich
99cd739b39 Fix unset EndCollideEvent fields (#4009) 2023-05-07 09:36:47 +10:00
Leon Friedrich
ccffd44f40 Add method to clear all scheduled midi events. (#4007)
* Add method to clear midi events.

* Rename method
2023-05-07 09:36:32 +10:00
metalgearsloth
7c4303c9a4 Version: 0.108.0.0 2023-05-06 16:27:58 +10:00
metalgearsloth
a52719b53f Refactor fixture serialization (#3923) 2023-05-06 16:26:06 +10:00
Leon Friedrich
1449302701 Small shader code cleanup (#3990) 2023-05-06 11:52:27 +10:00
Leon Friedrich
d2b3fc737b Fix circular transform hierarchy crash (#4002) 2023-05-05 14:54:04 +10:00
metalgearsloth
dc5d9a881e Version: 0.107.0.1 2023-05-04 23:35:11 +10:00
metalgearsloth
ee8f95650b Fix maploader logs (#4001) 2023-05-04 23:32:45 +10:00
deltanedas
ebc12410d4 fix wrong attribute name in autogen state errors (#4000) 2023-05-03 17:00:05 -07:00
metalgearsloth
89b4062eb6 Version: 0.107.0.0 2023-05-03 10:13:04 +10:00
Leon Friedrich
6846b71e43 Remove texture IoC resolves (#3999) 2023-05-02 15:02:57 +10:00
metalgearsloth
5697800922 Remove LocalPlayer static resolves (#3995) 2023-05-02 14:59:50 +10:00
Leon Friedrich
37b8c49a44 Light query/transform changes (#3998) 2023-05-02 14:46:18 +10:00
ElectroJr
4577d5d3d5 Version: 0.106.1.0 2023-05-01 21:11:24 -04:00
Leon Friedrich
4a65111dda Make screen-space overlays use BeforeDraw() (#3997) 2023-05-02 10:36:20 +10:00
metalgearsloth
b24e6d0673 Add comp to loaded maps (#3994)
Easiest way to tell how MapLoader loaded a map (i.e. did it use the existing map or did it overwrite it).
2023-05-01 19:32:23 -04:00
Pieter-Jan Briers
1ce5be2774 Remove finalizer from GameShared.
Incorrect copy pasting of disposable pattern, gone.
2023-05-01 18:00:01 +02:00
metalgearsloth
6ea8e5fae1 Version: 0.106.0.0 2023-05-01 14:52:07 +10:00
metalgearsloth
45734a2bdd TimeOffsetSerializer fixes (#3985) 2023-05-01 14:47:16 +10:00
metalgearsloth
b5ebc11d26 Update map file schema validator (#3991) 2023-05-01 14:16:09 +10:00
Leon Friedrich
b8081a335a Fix queued deletion error log (#3982) 2023-05-01 14:11:51 +10:00
Leon Friedrich
381c856dd4 Add transform recursion check (#3983) 2023-05-01 14:11:21 +10:00
Leon Friedrich
2efed72eba Fix respath null errors (#3989) 2023-05-01 14:11:07 +10:00
metalgearsloth
4d26202cf5 Version: 0.105.1.0 2023-05-01 13:40:31 +10:00
Leon Friedrich
3aa4bd1448 Add basic map loader support for entity renaming (#3975) 2023-05-01 13:35:47 +10:00
Leon Friedrich
179da34be8 Add comment to rga.yml (#3988) 2023-05-01 06:21:35 +10:00
metalgearsloth
0581dbe99f Add CompOrNull to entityquery struct (#3986) 2023-04-30 19:03:16 +10:00
metalgearsloth
1b5c5befa9 Version: 0.105.0.0 2023-04-30 16:28:10 +10:00
Leon Friedrich
c5ecc426d0 Remove server and shared sprite component (#3981) 2023-04-30 16:09:07 +10:00
Tom Leys
2618bc7a36 Check for Sprite layer's existance (#3984) 2023-04-30 09:08:42 +10:00
Leon Friedrich
4c282b00d1 Fix error placement overlay error + add overlay exception tolerance (#3980) 2023-04-30 03:44:42 +10:00
metalgearsloth
c5282afbb7 Version: 0.104.1.0 2023-04-29 20:15:57 +10:00
metalgearsloth
5e276d3112 Fix completionhelper paths (#3979) 2023-04-29 20:13:51 +10:00
Leon Friedrich
d7d22d9cd4 Make VV auto-dirty components (#3969) 2023-04-29 19:28:47 +10:00
metalgearsloth
adca56b111 Version: 0.104.0.0 2023-04-29 16:08:55 +10:00
Leon Friedrich
69cdf6f727 Generalize sprite view (#3978) 2023-04-29 16:06:30 +10:00
metalgearsloth
a65ccd7c24 Add debug assert for data defs (#3977) 2023-04-29 15:53:02 +10:00
metalgearsloth
4f840da5d6 Version: 0.103.0.0 2023-04-29 14:12:47 +10:00
metalgearsloth
96ef013095 Save entities by prototype in map data (#3913) 2023-04-29 14:08:52 +10:00
deepCurse
4efc04a167 Add sf3 support (#3955) 2023-04-28 23:01:37 +02:00
metalgearsloth
7cdd45b4ff Obsolete comp references (#3900) 2023-04-29 03:54:24 +10:00
James Simonson
365fad488c Adjust center point on non 32px Sprites if SpriteOffset == false (#3865) 2023-04-29 03:52:50 +10:00
metalgearsloth
c1e7aca3fe Make RobustServerSim public (#3835) 2023-04-29 03:31:27 +10:00
pali
3f7fce2f02 Fix prob definition inequality (#3976) 2023-04-29 03:15:47 +10:00
ElectroJr
105aa13eb1 Version: 0.102.1.0 2023-04-28 03:14:23 -04:00
ElectroJr
7d8d6ebd20 release notes 2023-04-28 03:14:12 -04:00
Leon Friedrich
1bb2d39d71 Fix _windowIconPath null error (#3974) 2023-04-28 16:22:06 +10:00
Pieter-Jan Briers
0a5375d1c7 Oh huh I don't need P/Invoke for everything huh?? 2023-04-26 22:58:49 +02:00
Pieter-Jan Briers
c9042f188c Console output fixes.
Make it not assume UTF-8 when it's not.
Try to set the console output to UTF-8 on Windows.
Remove UTF-16 output code cuz who needs it.
2023-04-26 22:51:52 +02:00
metalgearsloth
cea74c63cd Add force / torque API for physics (#3965) 2023-04-26 14:17:45 +10:00
ElectroJr
37420b253b Version: 0.102.0.0 2023-04-25 00:06:20 -04:00
ElectroJr
c4dead2c99 Release notes + tiny map saving fix 2023-04-25 00:06:05 -04:00
Leon Friedrich
f917748809 Make map loading log errors on invalid UIDs (#3970) 2023-04-25 13:58:10 +10:00
Leon Friedrich
f25a728a36 Revert "Fix map serialization error log" (#3968) 2023-04-24 17:32:17 +10:00
Leon Friedrich
be9f0a988a Fix map serialization error log (#3967) 2023-04-24 17:29:57 +10:00
metalgearsloth
eae1e7c108 'fix' transform coordinates assert (#3964)
Co-authored-by: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com>
2023-04-24 16:17:29 +10:00
metalgearsloth
6f4e31d6c4 Add dupe prototype ID validation (#3966) 2023-04-24 15:55:43 +10:00
Leon Friedrich
d52759f4fb Fix interp overlay (#3963) 2023-04-23 18:33:16 +10:00
Leon Friedrich
4242591b56 Fix pvs chunk update bug (#3961) 2023-04-23 16:23:24 +10:00
metalgearsloth
276c1f6ff8 Version: 0.101.1.1 2023-04-23 15:12:47 +10:00
metalgearsloth
19df65188b Fix poly deserialization (#3959) 2023-04-23 15:08:24 +10:00
metalgearsloth
9223c79ca3 Version: 0.101.1.0 2023-04-23 13:13:27 +10:00
Moony
693a73549d Reorder initialization slightly. (#3940) 2023-04-23 13:09:01 +10:00
metalgearsloth
c7c21a34e7 Add replacement to entity placement (#3857) 2023-04-23 13:07:53 +10:00
metalgearsloth
d8ba637502 Version: 0.101.0.0 2023-04-22 17:01:45 +10:00
metalgearsloth
b638a784cf Fix distance output for overlapping circles (#3958) 2023-04-22 17:00:10 +10:00
metalgearsloth
733c0e7a45 Box2D updates (#3957) 2023-04-22 16:41:05 +10:00
metalgearsloth
62aa9bfb49 Mouse joint damping fix (#3956) 2023-04-22 15:56:40 +10:00
ElectroJr
fcb34ed8c6 Version: 0.100.0.0 2023-04-21 00:16:36 -04:00
ElectroJr
e718e119f4 release notes 2023-04-21 00:16:17 -04:00
Leon Friedrich
eb711e44b5 Make GetAABBNoContainer actually raise the event (#3954) 2023-04-21 14:13:41 +10:00
Leon Friedrich
ac66038bb5 Make Resolve() fail on deleted components. (#3952) 2023-04-21 14:02:06 +10:00
Leon Friedrich
17ca016791 Fix PVS concurrent update exception (#3953) 2023-04-21 13:45:28 +10:00
DrSmugleaf
4c8be516cf Remove ILookupWorldBox2Component component reference (#3914) 2023-04-20 23:41:30 +10:00
metalgearsloth
2089e9b749 Version: 0.99.0.0 2023-04-20 20:36:24 +10:00
metalgearsloth
9f9900751d Delete some entity init code (#3947) 2023-04-20 20:33:32 +10:00
metalgearsloth
8a6cadd38f Revert "Revert "Replace ResourcePath with ResPath (#3926)" (#3949)" (#3950) 2023-04-20 20:15:57 +10:00
metalgearsloth
b582b317c1 Contact changes (#3946) 2023-04-20 20:07:31 +10:00
metalgearsloth
e84523359a Version: 0.98.0.0 2023-04-20 11:45:19 +10:00
metalgearsloth
d646403068 Revert "Replace ResourcePath with ResPath (#3926)" (#3949) 2023-04-20 11:43:51 +10:00
metalgearsloth
6fb8df41e5 Version: 0.97.1.1 2023-04-20 11:21:09 +10:00
metalgearsloth
2a7980965e Hotfix assembly paths (#3948) 2023-04-20 11:20:09 +10:00
metalgearsloth
c458892467 Version: 0.97.1.0 2023-04-20 10:40:11 +10:00
Leon Friedrich
c67151b9c9 Improve PVS metrics & multithread ack processing. (#3936) 2023-04-20 10:37:18 +10:00
metalgearsloth
ef64828613 Make FastNoiseLite serializable (#3944) 2023-04-20 10:30:39 +10:00
Leon Friedrich
c82364df7b Make NetGraph logarithmic (#3941) 2023-04-20 00:12:56 +10:00
Leon Friedrich
f89d6fc73f Add invalid broadphase check (#3939) 2023-04-20 00:12:18 +10:00
metalgearsloth
9fb28b5f2a Version: 0.97.0.0 2023-04-19 23:38:56 +10:00
Ygg01
d6a3e1e286 Replace ResourcePath with ResPath (#3926) 2023-04-19 23:37:46 +10:00
Leon Friedrich
8958b2123e Add stack trace to transform log. (#3938) 2023-04-17 11:36:10 +10:00
ElectroJr
6550ece258 Version: 0.96.9.0 2023-04-16 19:56:37 -04:00
ElectroJr
fc9526092b Release notes 2023-04-16 19:56:09 -04:00
Leon Friedrich
bb26e243d6 Allow integration tests to raise gui events. (#3937) 2023-04-17 09:52:58 +10:00
Leon Friedrich
ad66e31d6e Fix PVS bug (#3935) 2023-04-16 10:54:42 +10:00
Pieter-Jan Briers
e357330409 Version: 0.96.8.2 2023-04-15 18:05:15 +02:00
Pieter-Jan Briers
f3877f3d6a Sandboxing: load from launcher engine before loading from disk load paths.
Robust.Client.WebView includes Robust.Client.dll and such now, so sandboxing was loading the Robust.Client.dll from there instead of from the running engine itself.
2023-04-15 18:03:53 +02:00
Leon Friedrich
2705e2a56a Allow PrototypeLayerData to clear shaders (#3934) 2023-04-15 11:56:38 +10:00
DrSmugleaf
4fd5f2bb64 Make AutoGenerateComponentState partial class compilation error clickable (#3932) 2023-04-13 19:33:21 -07:00
metalgearsloth
1163a445cd Version: 0.96.8.1 2023-04-14 10:30:19 +10:00
metalgearsloth
56d15c8ef0 Fix mapinit in some instances (#3931) 2023-04-14 10:26:54 +10:00
metalgearsloth
abd3a8b47e Version: 0.96.8.0 2023-04-13 21:12:11 +10:00
Leon Friedrich
c21a062bcb Add BroadphaseNetworkingTest (#3930) 2023-04-13 15:40:36 +10:00
metalgearsloth
0ff270c625 Create entities before applying entity states. (#3919) 2023-04-13 02:08:39 +10:00
metalgearsloth
7a35a859d9 Set paused before ent startup when loading (#3806) 2023-04-12 19:51:26 +10:00
ElectroJr
23f397fd6b Version: 0.96.7.0 2023-04-11 13:18:03 -04:00
ElectroJr
2ac3c0824b Release notes 2023-04-11 13:17:30 -04:00
Leon Friedrich
c90907ba92 Add dependency injection option to IDynamicTypeFactory (#3911) 2023-04-12 03:05:31 +10:00
Amy
5032c883b8 Adds normal blend mode (#3908)
* adds normal blend mode

* error message update

---------

Co-authored-by: amylizzle <amylizzle@users.noreply.github.com>
2023-04-11 15:12:16 +02:00
Ygg01
951e01af5a Adds a new ResPath struct that will replace ResourcePath (#3663) 2023-04-11 11:18:42 +10:00
Leon Friedrich
42a4227efe Fix container out-of-bounds bug (#3922) 2023-04-10 12:34:01 +10:00
Leon Friedrich
ebb2a65e6d Maybe fix audio IndexOutOfRange exceptions (#3910) 2023-04-10 12:33:21 +10:00
Leon Friedrich
6cf0756f27 Replace assert with warning (#3921) 2023-04-10 08:00:20 +10:00
DrSmugleaf
40c8a3ccf7 Version: 0.96.6.0 2023-04-08 19:14:57 -07:00
DrSmugleaf
a9a3af320e Update RELEASE-NOTES.md 2023-04-08 19:06:51 -07:00
metalgearsloth
410957be46 Random shuffle overrides (#3912) 2023-04-09 11:56:42 +10:00
Skye
ff4bebd806 UI: Close window hotkeys (#3918)
Looks good to me!
2023-04-08 18:13:04 -07:00
Leon Friedrich
ff276a3c9f Improve some container asserts (#3916) 2023-04-09 03:38:38 +10:00
moonheart08
93dca22ee5 Version: 0.96.5.0 2023-04-06 12:35:22 -05:00
Kara
85547a9be7 Auto-componentstate source generator (#3684)
* dog what am i doing

* finish gen source part from class symbol

* we are dangerously close to things happening

* generation fixes

* oh? on god?

* stop autogenerating the attribute for no reason + diagnostics

* testing diagnostics

* proper type name handling + clonedata bool

* thank you material storage for making me realize this

* forgot to commit

* p

* fixes for afterautohandlestate

* make it work with access
2023-04-06 12:32:57 -05:00
moonheart08
b31876ff03 Version: 0.96.4.0 2023-04-05 20:57:49 -05:00
Leon Friedrich
6092e39303 Support implicit delta comp states. (#3909) 2023-04-05 20:51:35 -05:00
Pieter-Jan Briers
9ad9fccb22 Version: 0.96.3.0 2023-04-05 20:09:44 +02:00
Pieter-Jan Briers
f5cf39907a Update server SQLitePCLRaw to 2.1.4 2023-04-05 20:05:36 +02:00
Kara
dae4761b72 Version: 0.96.2.0 2023-04-03 00:29:25 -05:00
Kara
2fdb4e30ac Revert "Don't draw text contents over scrollbar for outputpanel" (#3905) 2023-04-02 22:28:27 -07:00
metalgearsloth
07192c4294 Version: 0.96.1.0 2023-04-03 12:55:41 +10:00
Visne
eb65a45ed4 Implement deleting a full word at a time (#3725) 2023-04-03 12:50:30 +10:00
metalgearsloth
68fe69ef24 Invalid OutputPanel entries upon tree enter (#3875) 2023-04-03 06:35:09 +10:00
Leon Friedrich
42e50798b9 Fix empty container (#3902) 2023-04-03 06:34:18 +10:00
Leon Friedrich
d570bcef9a Fix content test workflow (#3903) 2023-04-03 06:34:04 +10:00
metalgearsloth
7b60f5bd06 Don't draw text contents over scrollbar for outputpanel (#3876) 2023-04-03 05:49:23 +10:00
Leon Friedrich
9b0139032b Fix container networking bugs (#3901) 2023-04-03 03:16:09 +10:00
metalgearsloth
d4ccbfc72b Version: 0.96.0.4 2023-04-01 13:37:35 +11:00
Leon Friedrich
fe8a1d2632 Fix implicit appearance state data (#3896) 2023-04-01 12:20:10 +11:00
metalgearsloth
fde8a4a91a Revert "Adjust InRange entity lookups" (#3897) 2023-04-01 12:19:15 +11:00
metalgearsloth
a7b41b3457 Version: 0.96.0.3 2023-03-31 16:52:00 +11:00
metalgearsloth
179845d9b1 Add many more audio logs (#3879) 2023-03-31 16:50:10 +11:00
metalgearsloth
de837b1b03 Adjust InRange entity lookups (#3868) 2023-03-31 16:49:12 +11:00
Leon Friedrich
4f0daa8143 Fix discord null errors (#3895) 2023-03-30 22:11:14 -05:00
metalgearsloth
400bdb43aa Fix log length (#3894) 2023-03-31 12:30:26 +11:00
Leon Friedrich
69bb4f9237 Fix sprite error log. (#3892) 2023-03-31 12:05:35 +11:00
DrSmugleaf
dc5f9302cd Remove Vera from CODEOWNERS (#3891) 2023-03-29 17:37:44 -07:00
metalgearsloth
58b8e27eea Version: 0.96.0.2 2023-03-29 23:43:28 +11:00
metalgearsloth
23d827e4ef Fix adding mapgrid to a map (#3890) 2023-03-29 23:02:31 +11:00
metalgearsloth
2d51bf4d1b Version: 0.96.0.1 2023-03-29 18:44:40 +11:00
metalgearsloth
26efbb4b81 Adjust QDel log (#3888) 2023-03-29 18:38:55 +11:00
metalgearsloth
0ff5bb862a Revert "Move dependencies off of physics contacts (#3867)" (#3887) 2023-03-29 18:38:18 +11:00
metalgearsloth
7d98e5cea5 Bandaid contact length issue (#3885) 2023-03-28 19:11:48 +11:00
wixoa
0d04200c55 Set blend function for shaders with ShaderBlendMode.None (#3877) 2023-03-27 12:12:01 -05:00
metalgearsloth
6983f3b1a1 Version: 0.96.0.0 2023-03-27 22:40:42 +11:00
Leon Friedrich
a284159a18 Remove MapId serializer and rename WorldMap to MapId (#3872) 2023-03-27 22:38:36 +11:00
Leon Friedrich
521a97939d Suppress invalid map saving warnings (#3873) 2023-03-27 22:37:24 +11:00
metalgearsloth
795dd6149c Add temp physics contact logs (#3882) 2023-03-27 22:26:11 +11:00
metalgearsloth
27877820ed Add QueueDel logs (#3878) 2023-03-27 10:41:48 +11:00
metalgearsloth
2cbb1a17e7 Add showrot command (#3874) 2023-03-27 08:05:44 +11:00
faint
605d9737f0 Improve Discord Rich Presence (#3816) 2023-03-25 16:58:22 -07:00
ElectroJr
2662985ce2 Version: 0.95.0.0 2023-03-25 19:24:04 -04:00
ElectroJr
b31836f674 release notes 2023-03-25 19:23:40 -04:00
Leon Friedrich
231d08ae1a Revert "Make PauseTime a DataField (#3863)" (#3871) 2023-03-26 10:20:38 +11:00
Visne
d8b97ee242 Refactor NextWordPosition to EndWordPosition (#3724) 2023-03-24 17:29:44 +11:00
metalgearsloth
71e84d82f8 Version: 0.94.0.0 2023-03-24 17:24:05 +11:00
metalgearsloth
dc30e35615 Move dependencies off of physics contacts (#3867) 2023-03-24 17:17:50 +11:00
Leon Friedrich
eb3dfeaa7b Set IsFirstTimePredicted to false during state application (#3866) 2023-03-24 17:14:01 +11:00
Leon Friedrich
124c627fe2 Make PauseTime a DataField (#3863) 2023-03-24 17:00:25 +11:00
metalgearsloth
0b3a4821fa Use a list for active contacts (#3864) 2023-03-24 16:55:26 +11:00
metalgearsloth
1aec754308 Update release notes
Forgot to save my changes in vs code.
2023-03-24 13:22:52 +11:00
metalgearsloth
dbf01e6b75 Version: 0.93.3.0 2023-03-24 13:21:07 +11:00
metalgearsloth
c10b00fc1b Add a field to disable grid splitting per-grid (#3848) 2023-03-24 13:19:13 +11:00
metalgearsloth
e2b7c11750 Don't write unnecessary tilemap (#3824) 2023-03-24 13:18:34 +11:00
metalgearsloth
105dc0ac1f Add temp logs around contacts (#3862) 2023-03-24 13:18:11 +11:00
metalgearsloth
69dc5aaad4 Version: 0.93.2.0 2023-03-23 23:50:14 +11:00
metalgearsloth
2e5ba99d5f Add some completionhelpers (#3860) 2023-03-23 23:48:00 +11:00
moonheart08
014dd37594 Version: 0.93.1.0 2023-03-22 04:41:04 -05:00
metalgearsloth
14a9583a3e Add playpredicted for entitycoordinates audio (#3856) 2023-03-22 04:39:13 -05:00
Skye
07ad8cf4ed Fluidsynth3 compat (#3850) 2023-03-19 12:32:25 +01:00
Leon Friedrich
bfa9965056 Fix map saving bug (#3852) 2023-03-17 17:28:51 +11:00
Leon Friedrich
9a06a5727e Make DataDefinitions check for private constructors (#3845) 2023-03-17 12:49:02 +11:00
metalgearsloth
4e02f12e19 Add PlayPvs for EntityCoordinates (#3849) 2023-03-15 14:25:40 +11:00
08A
471da9aace Add method prepare placement prototype entity (#3826) 2023-03-15 14:25:08 +11:00
Flipp Syder
5924d9d017 Ensures SplitContainer children have measured sizes when clamping split center (#3827) 2023-03-15 14:22:57 +11:00
Morb
443664fc3f Add SetFallbackCluture to interface (#3846) 2023-03-15 14:21:09 +11:00
ElectroJr
4ecd58dbfe Version: 0.93.0.0 2023-03-14 20:21:36 -04:00
ElectroJr
cfdd9862df Update release notes 2023-03-14 20:21:29 -04:00
Leon Friedrich
302af71764 EmptyContainer tweaks (#3819) 2023-03-15 11:12:04 +11:00
Leon Friedrich
e851cea6b2 Fix audio IoC errors (#3851) 2023-03-15 11:11:32 +11:00
Leon Friedrich
b4df9c49d8 Fix map validator (#3847) 2023-03-15 10:49:19 +11:00
Pieter-Jan Briers
477e7820cd hub_advertise_now command. 2023-03-13 23:03:49 +01:00
Pieter-Jan Briers
80b6f5e01f Add DoesNotReturn annotations to DebugTools.Assert* methods.
These allow Assert(Foo != null) to suppress nullability warnings. No way to configure it for AssertNotNull though.
2023-03-13 23:02:57 +01:00
Leon Friedrich
0a4813225d Add readonly to Box2Rotated methods (#3844) 2023-03-13 03:39:23 +11:00
Leon Friedrich
d9280fdd1c Fix colour slider recursion. (#3838) 2023-03-13 03:39:06 +11:00
DrSmugleaf
52ba22f645 Add benchmark for archetype indexing by handle vs array access vs field direct access (#3801) 2023-03-11 11:44:16 -08:00
Leon Friedrich
357755a65e Fix RSI loading error tolerance (#3841) 2023-03-11 13:42:25 +11:00
Leon Friedrich
466f565e44 Fix sprites sometimes not updating IsInert when changing state. (#3842) 2023-03-11 13:42:12 +11:00
metalgearsloth
ba97f9c116 Version: 0.92.2.1 2023-03-11 12:48:20 +11:00
metalgearsloth
4c81bf164c Revert "Shrink tile bounds slightly (#3831)" (#3837) 2023-03-11 12:45:23 +11:00
1309 changed files with 59633 additions and 25127 deletions

22
.github/CODEOWNERS vendored
View File

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

View File

@@ -7,12 +7,12 @@ jobs:
docfx:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3.6.0
with:
submodules: true
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3.2.0
with:
dotnet-version: 7.0.x

View File

@@ -15,12 +15,12 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3.6.0
with:
submodules: true
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3.2.0
with:
dotnet-version: 7.0.x
- name: Install dependencies

View File

@@ -35,12 +35,12 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3.6.0
with:
submodules: true
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3.2.0
with:
dotnet-version: 7.0.x

View File

@@ -16,12 +16,12 @@ jobs:
$ver = [regex]::Match($env:GITHUB_REF, "refs/tags/v?(.+)").Groups[1].Value
echo ("::set-output name=version::{0}" -f $ver)
- uses: actions/checkout@v2
- uses: actions/checkout@v3.6.0
with:
submodules: true
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3.2.0
with:
dotnet-version: 7.0.x

View File

@@ -13,13 +13,13 @@ jobs:
steps:
- name: Check out content
uses: actions/checkout@v2
uses: actions/checkout@v3.6.0
with:
repository: space-wizards/space-station-14
submodules: recursive
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3.2.0
with:
dotnet-version: 7.0.x
- name: Disable submodule autoupdate
@@ -34,7 +34,7 @@ jobs:
- name: Install dependencies
run: dotnet restore
- name: Build
run: dotnet build --configuration Release --no-restore
run: dotnet build --configuration Tools --no-restore
- name: Content.Tests
run: dotnet test --no-build Content.Tests/Content.Tests.csproj -v n
- name: Content.IntegrationTests

3
.gitmodules vendored
View File

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

1
Arch/Arch Submodule

Submodule Arch/Arch added at c76d18feb7

94
Arch/Arch.csproj Normal file
View File

@@ -0,0 +1,94 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion>
<TargetFramework>net7.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<Nullable>enable</Nullable>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
<PackageId>Arch</PackageId>
<Title>Arch</Title>
<Version>1.2.7.1-alpha</Version>
<Authors>genaray</Authors>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<Description>A high performance c# net.6 and net.7 archetype based ECS ( Entity component system ).</Description>
<PackageReleaseNotes>Updated LowLevel which fixes bugs. </PackageReleaseNotes>
<PackageTags>c#;.net;.net6;.net7;ecs;game;entity;gamedev; game-development; game-engine; entity-component-system;stride;unity;godot;</PackageTags>
<PackageProjectUrl>https://github.com/genaray/Arch</PackageProjectUrl>
<RepositoryUrl>https://github.com/genaray/Arch.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<IsPackable>true</IsPackable>
<LangVersion>11</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Copyright>Apache2.0</Copyright>
<NoWarn>1701;1702;1591</NoWarn>
<Configurations>Debug;Debug-PureECS;Debug-Events;Release;Release-PureECS;Release-Events;</Configurations>
<AssemblyName>Arch</AssemblyName>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<DefaultItemExcludes>src/Arch/**/*</DefaultItemExcludes>
<DefineConstants>$(DefineConstants);PURE_ECS;CONTRACTS_FULL</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DefineConstants>$(DefineConstants);PURE_ECS;CONTRACTS_FULL;TRACE;</DefineConstants>
<Optimize>false</Optimize>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>
<ItemGroup>
<InternalsVisibleTo Include="Arch.Benchmarks" />
<InternalsVisibleTo Include="Arch.Tests" />
</ItemGroup>
<ItemGroup>
<Using Include="System" />
<Using Include="System.Collections" />
<Using Include="System.Collections.Generic" />
<Using Include="System.Diagnostics" />
<Using Include="System.Diagnostics.CodeAnalysis" />
<Using Include="System.IO" />
<Using Include="System.Linq" />
<Using Include="System.Runtime.CompilerServices" />
<Using Include="System.Runtime.InteropServices" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include=".\Arch\src\Arch.SourceGen\Arch.SourceGen.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Arch.LowLevel" Version="1.1.0" />
<PackageReference Include="Collections.Pooled" Version="2.0.0-preview.27" />
<PackageReference Include="CommunityToolkit.HighPerformance" Version="7.1.2" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
<PackageReference Include="ZeroAllocJobScheduler" Version="1.0.2" />
</ItemGroup>
<ItemGroup>
<Compile Include="Arch\src\Arch\**\*.cs">
<Link>Arch\%(RecursiveDir)%(Filename)%(Extension)</Link>
</Compile>
<Compile Remove="Arch\src\Arch\obj\**\*.cs" />
<InternalsVisibleTo Include="Arch.Benchmarks" />
<InternalsVisibleTo Include="Arch.Tests" />
</ItemGroup>
<Import Project="../MSBuild/Robust.Properties.targets" />
</Project>

View File

@@ -0,0 +1,5 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
<ItemGroup>
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\Robust.Shared.CompNetworkGenerator\Robust.Shared.CompNetworkGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
</ItemGroup>
</Project>

View File

@@ -23,7 +23,7 @@
<PropertyGroup Condition="'$(FullRelease)' != 'True'">
<DefineConstants>$(DefineConstants);DEVELOPMENT</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<PropertyGroup Condition="'$(Configuration)' == 'Release' Or '$(Configuration)' == 'Tools'">
<DefineConstants>$(DefineConstants);EXCEPTION_TOLERANCE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(EnableClientScripting)' == 'True'">

View File

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

View File

@@ -25,4 +25,7 @@
<!-- analyzer -->
<Import Project="Robust.Analyzers.targets" Condition="'$(SkipRobustAnalyzer)' != 'true'" />
<!-- serialization generator -->
<Import Project="Robust.Serialization.Generator.targets" />
</Project>

View File

@@ -0,0 +1,5 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
<ItemGroup>
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\Robust.Serialization.Generator\Robust.Serialization.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
</ItemGroup>
</Project>

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<!-- Avoid MSBuild adding a None entry for XAML files because they'd show up TWICE in the project view. -->
<DefaultItemExcludes>**/*.xaml</DefaultItemExcludes>
<RobustUseExternalMSBuild>false</RobustUseExternalMSBuild>
<RobustUseExternalMSBuild>true</RobustUseExternalMSBuild>
<_RobustUseExternalMSBuild>$(RobustUseExternalMSBuild)</_RobustUseExternalMSBuild>
<_RobustUseExternalMSBuild Condition="'$(_RobustForceInternalMSBuild)' == 'true'">false</_RobustUseExternalMSBuild>
</PropertyGroup>

File diff suppressed because it is too large Load Diff

View File

@@ -2203,3 +2203,207 @@
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
- name: Arch
license: |
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2022 Lars Matthäus/genaray
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Binary file not shown.

View File

@@ -0,0 +1,34 @@
- type: entity
id: debugRotation
abstract: true
categories: [ debug ]
components:
- type: Sprite
netsync: false
visible: true
sprite: debugRotation.rsi
state: direction1
- type: entity
id: debugRotation1
parent: debugRotation
name: dbg_rotation1
components:
- type: Sprite
state: direction1
- type: entity
id: debugRotation4
parent: debugRotation
name: dbg_rotation4
components:
- type: Sprite
state: direction4
- type: entity
id: debugRotationTex
parent: debugRotation
name: dbg_rotationTex
components:
- type: Sprite
state: direction1

View File

@@ -1,3 +1,44 @@
- type: uiTheme
id: Default
path: /textures/interface/Default
path: /Textures/Interface/Default/
colors:
# Root
rootBackground: "#000000"
# Windows
windowBackground: "#111111"
windowBorder: "#444444"
windowHeader: "#001e3d"
windowCloseButton: "#FFFFFF"
windowCloseButtonHover: "#FF7F7F"
windowCloseButtonPressed: "#FF0000"
# Scrollbars
scrollBarDefault: "#80808059"
scrollBarHovered: "#8C8C8C59"
scrollBarGrabbed: "#8C8C8C59"
# Buttons
buttonBackground: "#171717"
buttonBackgroundHovered: "#272727"
buttonBackgroundPressed: "#173717"
buttonBorder: "#444444"
buttonBorderHovered: "#444444"
buttonBorderPressed: "#447044"
buttonBackgroundDisabled: "#333333"
buttonBorderDisabled: "#222222"
# LineEdit
lineEditUneditableText: "#444444"
lineEditPlaceholderText: "#7d7d7d"
lineEditBackground: "#000000"
lineEditBorder: "#444444"
# TabContainer
tabContainerBackground: "#000000"
tabContainerBorder: "#444444"
tabContainerActiveTabBackground: "#173717"
tabContainerActiveTabBorder: "#447044"
tabContainerInactiveTabBackground: "#171717"
tabContainerInactiveTabBorder: "#444444"

View File

@@ -0,0 +1,17 @@
# debug related entities
- type: entityCategory
id: debug
name: entity-category-name-debug
description: entity-category-desc-debug
# entities that spawn other entities
- type: entityCategory
id: spawner
name: entity-category-name-spawner
description: entity-category-desc-spawner
# entities that should be hidden from the spawn menu
- type: entityCategory
id: hideSpawnMenu
name: entity-category-name-hide
description: entity-category-desc-hide

View File

@@ -11,6 +11,10 @@ cmd-parse-failure-uid = {$arg} is not a valid entity UID.
cmd-parse-failure-mapid = {$arg} is not a valid MapId.
cmd-parse-failure-entity-exist = UID {$arg} does not correspond to an existing entity.
cmd-error-file-not-found = Could not find file: {$file}.
cmd-error-dir-not-found = Could not find directory: {$dir}.
cmd-failure-no-attached-entity = There is no entity attached to this shell.
## 'help' command
cmd-help-desc = Display general help or help text for a specific command
@@ -377,8 +381,11 @@ cmd-netaudit-help = netaudit
cmd-tp-desc = Teleports a player to any location in the round.
cmd-tp-help = tp <x> <y> [<mapID>]
cmd-tpto-desc = Teleports the current player or the specified players/entities to the location of last player/entity specified.d.
cmd-tpto-desc = Teleports the current player or the specified players/entities to the location of the first player/entity.
cmd-tpto-help = tpto <username|uid> [username|uid]...
cmd-tpto-destination-hint = destination (uid or username)
cmd-tpto-victim-hint = entity to teleport (uid or username)
cmd-tpto-parse-error = Cant resolve entity or player: {$str}
cmd-listplayers-desc = Lists all players currently connected.
cmd-listplayers-help = listplayers
@@ -530,24 +537,27 @@ cmd-vv-help = Usage: vv <path|entity ID|guihover>
cmd-vvinvoke-desc = Invoke/Call a path with arguments using VV.
cmd-vvinvoke-help = Usage: vvinvoke <path> [arguments...]
cmd-replaystart-desc = Starts a replay recording, optionally with some time limit.
cmd-replaystart-help = Usage: replaystart [minutes] [directory] [overwrite bool]
cmd-replaystart-success = Started recording a replay.
cmd-replaystart-already-recording = Already recording a replay.
cmd-replaystart-error = An error occurred while trying to start the recording.
cmd-replaystop-desc = Stops a replay recording.
cmd-replaystop-help = Usage: replaystop
cmd-replaystop-success = Stopped recording a replay.
cmd-replaystop-not-recording = Not currently recording a replay.
cmd-replaystats-desc = Displays information about the current replay recording.
cmd-replaystats-help = Usage: replaystats
cmd-replaystats-result = Duration: {$time} min, Ticks: {$ticks}, Size: {$size} mb, rate: {$rate} mb/min.
cmd-dump_dependency_injectors-desc = Dump IoCManager's dependency injector cache.
cmd-dump_dependency_injectors-help = Usage: dump_dependency_injectors
cmd-dump_dependency_injectors-total-count = Total count: { $total }
cmd-dump_netserializer_type_map-desc = Dump NetSerializer's type map and serializer hash.
cmd-dump_netserializer_type_map-help = Usage: dump_netserializer_type_map
cmd-hub_advertise_now-desc = Immediately advertise to the master hub server
cmd-hub_advertise_now-help = Usage: hub_advertise_now
cmd-echo-desc = Echo arguments back to the console
cmd-echo-help = Usage: echo "<message>"
## 'vfs_ls' command
cmd-vfs_ls-desc = List directory contents in the VFS.
cmd-vfs_ls-help = Usage: vfs_list <path>
Example:
vfs_list /Assemblies
cmd-vfs_ls-err-args = Need exactly 1 argument.
cmd-vfs_ls-hint-path = <path>
cmd-reloadtiletextures-desc = Reloads the tile texture atlas to allow hot reloading tile sprites
cmd-reloadtiletextures-help = Usage: reloadtiletextures

View File

@@ -3,6 +3,7 @@
entity-spawn-window-title = Entity Spawn Panel
entity-spawn-window-search-bar-placeholder = search
entity-spawn-window-clear-button = Clear
entity-spawn-window-replace-button-text = Replace
entity-spawn-window-erase-button-text = Erase Mode
entity-spawn-window-override-menu-tooltip = Override placement

View File

@@ -0,0 +1,3 @@
debug-builtin-connection-screen-invalid-username-with-reason = The given username is invalid: {$invalidreason}
debug-builtin-connection-screen-invalid-username = Invalid Username.
debug-builtin-connection-screen-failed-to-connect = Failed to connect: {$reason}

View File

@@ -0,0 +1,5 @@
discord-rpc-in-main-menu = In Main Menu
discord-rpc-in-main-menu-logo-text = I think coolsville SUCKS
discord-rpc-character = Username: {$username}
discord-rpc-on-server = On Server: {$servername}
discord-rpc-players = Players: {$players}/{$maxplayers}

View File

@@ -0,0 +1,8 @@
entity-category-name-debug = Debug
entity-category-desc-debug = Entity prototypes intended for debugging & testing.
entity-category-name-spawner = Spawner
entity-category-desc-spawner = Entity prototypes that spawn other entities.
entity-category-name-hide = Hidden
entity-category-desc-hide = Entity prototypes that should be hidden from the spawn menu

View File

@@ -18,6 +18,15 @@ input-key-F12 = F12
input-key-F13 = F13
input-key-F14 = F14
input-key-F15 = F15
input-key-F16 = F16
input-key-F17 = F17
input-key-F18 = F18
input-key-F19 = F19
input-key-F20 = F20
input-key-F21 = F21
input-key-F22 = F22
input-key-F23 = F23
input-key-F24 = F24
input-key-Pause = Pause
input-key-Left = Left
input-key-Up = Up

View File

@@ -0,0 +1,59 @@
# Playback Commands
cmd-replay-play-desc = Resume replay playback.
cmd-replay-play-help = replay_play
cmd-replay-pause-desc = Pause replay playback
cmd-replay-pause-help = replay_pause
cmd-replay-toggle-desc = Resume or pause replay playback.
cmd-replay-toggle-help = replay_toggle
cmd-replay-stop-desc = Stop and unload a replay.
cmd-replay-stop-help = replay_stop
cmd-replay-load-desc = Load and start a replay.
cmd-replay-load-help = replay_load <replay folder>
cmd-replay-load-hint = Replay folder
cmd-replay-skip-desc = Skip forwards or backwards in time.
cmd-replay-skip-help = replay_skip <tick or timespan>
cmd-replay-skip-hint = Ticks or timespan (HH:MM:SS).
cmd-replay-set-time-desc = Jump forwards or backwards to some specific time.
cmd-replay-set-time-help = replay_set <tick or time>
cmd-replay-set-time-hint = Tick or timespan (HH:MM:SS), starting from
cmd-replay-error-time = "{$time}" is not an integer or timespan.
cmd-replay-error-args = Wrong number of arguments.
cmd-replay-error-no-replay = Not currently playing a replay.
cmd-replay-error-already-loaded = A replay is already loaded.
cmd-replay-error-run-level = You cannot load a replay while connected to a server.
# Recording commands
cmd-replay-recording-start-desc = Starts a replay recording, optionally with some time limit.
cmd-replay-recording-start-help = Usage: replay_recording_start [name] [overwrite] [time limit]
cmd-replay-recording-start-success = Started recording a replay.
cmd-replay-recording-start-already-recording = Already recording a replay.
cmd-replay-recording-start-error = An error occurred while trying to start the recording.
cmd-replay-recording-start-hint-time = [time limit (minutes)]
cmd-replay-recording-start-hint-name = [name]
cmd-replay-recording-start-hint-overwrite = [overwrite (bool)]
cmd-replay-recording-stop-desc = Stops a replay recording.
cmd-replay-recording-stop-help = Usage: replay_recording_stop
cmd-replay-recording-stop-success = Stopped recording a replay.
cmd-replay-recording-stop-not-recording = Not currently recording a replay.
cmd-replay-recording-stats-desc = Displays information about the current replay recording.
cmd-replay-recording-stats-help = Usage: replay_recording_stats
cmd-replay-recording-stats-result = Duration: {$time} min, Ticks: {$ticks}, Size: {$size} MB, rate: {$rate} MB/min.
# Time Control UI
replay-time-box-scrubbing-label = Dynamic Scrubbing
replay-time-box-replay-time-label = Recording Time: {$current} / {$end} ({$percentage}%)
replay-time-box-server-time-label = Server Time: {$current} / {$end}
replay-time-box-index-label = Index: {$current} / {$total}
replay-time-box-tick-label = Tick: {$current} / {$total}

View File

@@ -0,0 +1,423 @@
command-description-tpto =
Teleport the given entities to some target entity.
command-description-player-list =
Returns a list of all player sessions.
command-description-player-self =
Returns the current player session.
command-description-player-imm =
Returns the session associated with the player given as argument.
command-description-player-entity =
Returns the entities of the input sessions.
command-description-self =
Returns the current attached entity.
command-description-physics-velocity =
Returns the velocity of the input entities.
command-description-physics-angular-velocity =
Returns the angular velocity of the input entities.
command-description-buildinfo =
Provides information about the build of the game.
command-description-cmd-list =
Returns a list of all commands, for this side.
command-description-explain =
Explains the given expression, providing command descriptions and signatures.
command-description-search =
Searches through the input for the provided value.
command-description-stopwatch =
Measures the execution time of the given expression.
command-description-types-consumers =
Provides all commands that can consume the given type.
command-description-types-tree =
Debug tool to return all types the command interpreter can downcast the input to.
command-description-types-gettype =
Returns the type of the input.
command-description-types-fullname =
Returns the full name of the input type according to CoreCLR.
command-description-as =
Casts the input to the given type.
Effectively a type hint if you know the type but the interpreter does not.
command-description-count =
Counts the amount of entries in it's input, returning an integer.
command-description-map =
Maps the input over the given block, with the provided expected return type.
This command may be modified to not need an explicit return type in the future.
command-description-select =
Selects N objects or N% of objects from the input.
One can additionally invert this command with not to make it select everything except N objects instead.
command-description-comp =
Returns the given component from the input entities, discarding entities without that component.
command-description-delete =
Deletes the input entities.
command-description-ent =
Returns the provided entity ID.
command-description-entities =
Returns all entities on the server.
command-description-paused =
Filters the input entities by whether or not they are paused.
This command can be inverted with not.
command-description-with =
Filters the input entities by whether or not they have the given component.
This command can be inverted with not.
command-description-fuck =
Throws an exception.
command-description-ecscomp-listty =
Lists every type of component registered.
command-description-cd =
Changes the session's current directory to the given relative or absolute path.
command-description-ls-here =
Lists the contents of the current directory.
command-description-ls-in =
Lists the contents of the given relative or absolute path.
command-description-methods-get =
Returns all methods associated with the input type.
command-description-methods-overrides =
Returns all methods overriden on the input type.
command-description-methods-overridesfrom =
Returns all methods overriden from the given type on the input type.
command-description-cmd-moo =
Asks the important questions.
command-description-cmd-descloc =
Returns the localization string for a command's description.
command-description-cmd-getshim =
Returns a command's execution shim.
command-description-help =
Provides a quick rundown of how to use toolshed.
command-description-ioc-registered =
Returns all the types registered with IoCManager on the current thread (usually the game thread)
command-description-ioc-get =
Gets an instance of an IoC registration.
command-description-loc-tryloc =
Tries to get a localization string, returning null if unable.
command-description-loc-loc =
Gets a localization string, returning the unlocalized string if unable.
command-description-physics-angular_velocity =
Returns the angular velocity of the given entities.
command-description-vars =
Provides a list of all variables set in this session.
command-description-any =
Returns true if there's any values in the input, otherwise false.
command-description-ArrowCommand =
Assigns the input to a variable.
command-description-isempty =
Returns true if the input is empty, otherwise false.
command-description-isnull =
Returns true if the input is null, otherwise false.
command-description-unique =
Filters the input sequence for uniqueness, removing duplicate values.
command-description-where =
Given some input sequence IEnumerable<T>, takes a block of signature T -> bool that decides if each input value should be included in the output sequence.
command-description-do =
Backwards compatibility with BQL, applies the given old commands over the input sequence.
command-description-named =
Filters the input entities by their name, with the regex ^selector$.
command-description-prototyped =
Filters the input entities by their prototype.
command-description-nearby =
Creates a new list of all entities nearby the inputs within the given range.
command-description-first =
Returns the first entry of the given enumerable.
command-description-splat =
"Splats" a block, value, or variable, creating N copies of it in a list.
command-description-val =
Casts the given value, block, or variable to the given type. This is mostly a workaround for current limitations of variables.
command-description-actor-controlled =
Filters entities by whether or not they're actively controlled.
command-description-actor-session =
Returns the sessions associated with the input entities.
command-description-physics-parent =
Returns the parent(s) of the input entities.
command-description-emplace =
Runs the given block over it's inputs, with the input value placed into the variable $value within the block.
Additionally breaks out $wx, $wy, $proto, $desc, $name, and $paused for entities.
Can also have breakout values for other types, consult the documentation for that type for further info.
command-description-AddCommand =
Performs numeric addition.
command-description-SubtractCommand =
Performs numeric subtraction.
command-description-MultiplyCommand =
Performs numeric multiplication.
command-description-DivideCommand =
Performs numeric division.
command-description-min =
Returns the minimum of two values.
command-description-max =
Returns the maximum of two values.
command-description-BitAndCommand =
Performs bitwise AND.
command-description-BitOrCommand =
Performs bitwise OR.
command-description-BitXorCommand =
Performs bitwise XOR.
command-description-neg =
Negates the input.
command-description-GreaterThanCommand =
Performs a greater-than comparison, x > y.
command-description-LessThanCommand =
Performs a less-than comparison, x < y.
command-description-GreaterThanOrEqualCommand =
Performs a greater-than-or-equal comparison, x >= y.
command-description-LessThanOrEqualCommand =
Performs a less-than-or-equal comparison, x <= y.
command-description-EqualCommand =
Performs an equality comparison, returning true if the inputs are equal.
command-description-NotEqualCommand =
Performs an equality comparison, returning true if the inputs are not equal.
command-description-append =
Appends a value to the input enumerable.
command-description-DefaultIfNullCommand =
Replaces the input with the type's default value if it is null, albeit only for value types (not objects).
command-description-OrValueCommand =
If the input is null, uses the provided alternate value.
command-description-DebugPrintCommand =
Prints the given value transparently, for debug prints in a command run.
command-description-i =
Integer constant.
command-description-f =
Float constant.
command-description-s =
String constant.
command-description-b =
Bool constant.
command-description-join =
Joins two sequences together into one sequence.
command-description-reduce =
Given a block to use as a reducer, turns a sequence into a single value.
The left hand side of the block is implied, and the right hand is stored in $value.
command-description-rep =
Repeats the input value N times to form a sequence.
command-description-take =
Takes N values from the input sequence
command-description-spawn-at =
Spawns an entity at the given coordinates.
command-description-spawn-on =
Spawns an entity on the given entity, at it's coordinates.
command-description-spawn-attached =
Spawns an entity attached to the given entity, at (0 0) relative to it.
command-description-mappos =
Returns an entity's coordinates relative to it's current map.
command-description-pos =
Returns an entity's coordinates.
command-description-tp-coords =
Teleports the target to the given coordinates.
command-description-tp-to =
Teleports the target to the given other entity.
command-description-tp-into =
Teleports the target "into" the given other entity, attaching it at (0 0) relative to it.
command-description-comp-get =
Gets the given component from the given entity.
command-description-comp-add =
Adds the given component to the given entity.
command-description-comp-ensure =
Ensures the given entity has the given component.
command-description-comp-has =
Check if the given entity has the given component.
command-description-AddVecCommand =
Adds a scalar (single value) to every element in the input.
command-description-SubVecCommand =
Subtracts a scalar (single value) from every element in the input.
command-description-MulVecCommand =
Multiplies a scalar (single value) by every element in the input.
command-description-DivVecCommand =
Divides every element in the input by a scalar (single value).
command-description-rng-to =
Returns a number from its input to its argument (i.e. n..m inclusive)
command-description-rng-from =
Returns a number to its input from its argument (i.e. m..n inclusive)
command-description-rng-prob =
Returns a boolean based on the input probability/chance (from 0 to 1)
command-description-sum =
Computes the sum of the input.
command-description-bin =
"Bins" the input, counting up how many times each unique element occurs.
command-description-extremes =
Returns the two extreme ends of a list, interwoven.
command-description-sortby =
Sorts the input least to greatest by the computed key.
command-description-sortmapby =
Sorts the input least to greatest by the computed key, replacing the value with it's computed key afterward.
command-description-sort =
Sorts the input least to greatest.
command-description-sortdownby =
Sorts the input greatest to least by the computed key.
command-description-sortmapdownby =
Sorts the input greatest to least by the computed key, replacing the value with it's computed key afterward.
command-description-sortdown =
Sorts the input greatest to least.
command-description-iota =
Returns a list of numbers 1 to N.
command-description-to =
Returns a list of numbers N to M.
command-description-curtick =
The current game tick.
command-description-curtime =
The current game time (a TimeSpan)
command-description-realtime =
The current realtime since startup (a TimeSpan)
command-description-servertime =
The current server game time, or zero if we are the server (a TimeSpan)
command-description-replace =
Replaces the input entities with the given prototype, preserving position and rotation (but nothing else)
command-description-allcomps =
Returns all components on the given entity.
command-description-entitysystemupdateorder-tick =
Lists the tick update order of entity systems.
command-description-entitysystemupdateorder-frame =
Lists the frame update order of entity systems.
command-description-more =
Prints the contents of $more, i.e. any extras that Toolshed didn't print from the last command.
command-description-ModulusCommand =
Computes the modulus of two values.
This is usually remainder, check C#'s documentation for the type.
command-description-ModVecCommand =
Performs the modulus operation over the input with the given constant right-hand value.
command-description-BitAndNotCommand =
Performs bitwise AND-NOT over the input.
command-description-BitOrNotCommand =
Performs bitwise OR-NOT over the input.
command-description-BitXnorCommand =
Performs bitwise XNOR over the input.
command-description-BitNotCommand =
Performs bitwise NOT on the input.
command-description-abs =
Computes the absolute value of the input (removing the sign)
command-description-average =
Computes the average (arithmetic mean) of the input.
command-description-bibytecount =
Returns the size of the input in bytes, given that the input implements IBinaryInteger.
This is NOT sizeof.
command-description-shortestbitlength =
Returns the minimum number of bits needed to represent the input value.
command-description-countleadzeros =
Counts the number of leading binary zeros in the input value.
command-description-counttrailingzeros =
Counts the number of trailing binary zeros in the input value.
command-description-fpi =
pi (3.14159...) as a float.
command-description-fe =
e (2.71828...) as a float.
command-description-ftau =
tau (6.28318...) as a float.
command-description-fepsilon =
The epsilon value for a float, exactly 1.4e-45.
command-description-dpi =
pi (3.14159...) as a double.
command-description-de =
e (2.71828...) as a double.
command-description-dtau =
tau (6.28318...) as a double.
command-description-depsilon =
The epsilon value for a double, exactly 4.9406564584124654E-324.
command-description-hpi =
pi (3.14...) as a half.
command-description-he =
e (2.71...) as a half.
command-description-htau =
tau (6.28...) as a half.
command-description-hepsilon =
The epsilon value for a half, exactly 5.9604645E-08.
command-description-floor =
Returns the floor of the input value (rounding toward zero).
command-description-ceil =
Returns the ceil of the input value (rounding away from zero).
command-description-round =
Rounds the input value.
command-description-trunc =
Truncates the input value.
command-description-round2frac =
Rounds the input value to the specified number of fractional digits.
command-description-exponentbytecount =
Returns the number of bytes required to store the exponent.
command-description-significandbytecount =
Returns the number of bytes required to store the significand.
command-description-significandbitcount =
Returns the exact bit length of the significand.
command-description-exponentshortestbitcount =
Returns the minimum number of bits to store the exponent.
command-description-stepnext =
Steps to the next float value, adding one to the significand with carry.
command-description-stepprev =
Steps to the previous float value, subtracting one from the significand with carry.
command-description-checkedto =
Converts from the input numeric type to the target, erroring if not possible.
command-description-saturateto =
Converts from the input numeric type to the target, saturating if the value is out of range.
For example, converting 382 to a byte would saturate to 255 (the maximum value of a byte).
command-description-truncto =
Converts from the input numeric type to the target, with truncation.
In the case of integers, this is a bit cast with sign extension.
command-description-iscanonical =
Returns whether the input is in canonical form.
command-description-iscomplex =
Returns whether the input is a complex number (by value, not by type)
command-description-iseven =
Returns whether the input is even.
Not a javascript package.
command-description-isodd =
Returns whether the input is odd.
command-description-isfinite =
Returns whether the input is finite.
command-description-isimaginary =
Returns whether the input is purely imaginary (no real part).
command-description-isinfinite =
Returns whether the input is infinite.
command-description-isinteger =
Returns whether the input is an integer (by value, not by type)
command-description-isnan =
Returns whether the input is Not a Number (NaN).
This is a special floating point value, so this is by value, not by type.
command-description-isnegative =
Returns whether the input is negative.
command-description-ispositive =
Returns whether the input is positive.
command-description-isreal =
Returns whether the input is purely real (no imaginary part).
command-description-issubnormal =
Returns whether the input is in sub-normal form.
command-description-iszero =
Returns whether the input is zero.
command-description-pow =
Computes the power of its lefthand to its righthand. x^y.
command-description-sqrt =
Computes the square root of its input.
command-description-cbrt =
Computes the cube root of its input.
command-description-root =
Computes the Nth root of its input.
command-description-hypot =
Computes the hypotenuse of a triangle with the given sides A and B.
command-description-sin =
Computes the sine of the input.
command-description-sinpi =
Computes the sine of the input multiplied by pi.
command-description-asin =
Computes the arcsine of the input.
command-description-asinpi =
Computes the arcsine of the input multiplied by pi.
command-description-cos =
Computes the cosine of the input.
command-description-cospi =
Computes the cosine of the input multiplied by pi.
command-description-acos =
Computes the arcosine of the input.
command-description-acospi =
Computes the arcosine of the input multiplied by pi.
command-description-tan =
Computes the tangent of the input.
command-description-tanpi =
Computes the tangent of the input multiplied by pi.
command-description-atan =
Computes the arctangent of the input.
command-description-atanpi =
Computes the arctangent of the input multiplied by pi.
command-description-iterate =
Iterates the given function over the input N times, returning a list of results.
Think of this like successively applying the function to a value, tracking all the intermediate values.
command-description-pick =
Picks a random value from the input.
command-description-tee =
Tees the input into the given block, ignoring the block's result.
This essentially lets you have a branch in your code to do multiple operations on one value.
command-description-cmd-info =
Returns a CommandSpec for the given command.
On it's own, this means it'll print the comamnd's help message.
command-description-comp-rm =
Removes the given component from the entity.

View File

@@ -0,0 +1,7 @@
uploadfolder-command-description = Uploads a folder from your UserData folder recursively to the server contentDB.
uploadfolder-command-help = uploadfolder [folder you want to upload in userdata/UploadFolder]
uploadfolder-command-wrong-args = Wrong number of arguments!
uploadfolder-command-folder-not-found = Folder {$folder} not found!
uploadfolder-command-resource-upload-disabled = Network Resource Uploading is currently disabled. check Server CVars.
uploadfolder-command-file-too-big = File {$filename} above the current size limit! It must be smaller than {$sizeLimit} MB. skipping.
uploadfolder-command-success = Uploaded {$fileCount} files

View File

@@ -1,5 +1,6 @@
## ViewVariablesInstanceEntity
view-variables = View Variables
view-variable-instance-entity-server-components-add-component-button-placeholder = Add Component
view-variable-instance-entity-client-variables-tab-title = Client Variables
view-variable-instance-entity-client-components-tab-title = Client Components
@@ -8,4 +9,4 @@ view-variable-instance-entity-server-components-tab-title = Server Components
view-variable-instance-entity-client-components-search-bar-placeholder = Search
view-variable-instance-entity-server-components-search-bar-placeholder = Search
view-variable-instance-entity-add-window-server-components = Add Component [S]
view-variable-instance-entity-add-window-client-components = Add Component [C]
view-variable-instance-entity-add-window-client-components = Add Component [C]

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

View File

Before

Width:  |  Height:  |  Size: 637 B

After

Width:  |  Height:  |  Size: 637 B

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
@@ -12,6 +13,7 @@ namespace Robust.Analyzers
public class AccessAnalyzer : DiagnosticAnalyzer
{
private const string AccessAttributeType = "Robust.Shared.Analyzers.AccessAttribute";
private const string RobustAutoGeneratedAttributeType = "Robust.Shared.Analyzers.RobustAutoGeneratedAttribute";
private const string PureAttributeType = "System.Diagnostics.Contracts.PureAttribute";
[SuppressMessage("ReSharper", "RS2008")]
@@ -73,11 +75,20 @@ namespace Robust.Analyzers
// Get the attributes
var friendAttribute = context.Compilation.GetTypeByMetadataName(AccessAttributeType);
var autoGenAttribute = context.Compilation.GetTypeByMetadataName(RobustAutoGeneratedAttributeType);
// Get the type that is containing this expression, or, the type where this is happening.
if (context.ContainingSymbol?.ContainingType is not {} accessingType)
return;
// Should we ignore the access attempt due to the accessing type being auto-generated?
if (accessingType.GetAttributes().FirstOrDefault(a =>
a.AttributeClass != null &&
a.AttributeClass.Equals(autoGenAttribute, SymbolEqualityComparer.Default)) is { } attr)
{
return;
}
// Determine which type of access is happening here... Read, write or execute?
var accessAttempt = DetermineAccess(context, targetAccess, operation);

View File

@@ -23,16 +23,6 @@ public sealed class ByRefEventAnalyzer : DiagnosticAnalyzer
"Make sure that methods subscribing to a ref event have the ref keyword for the event argument."
);
private static readonly DiagnosticDescriptor ByValueEventSubscribedByRefRule = new(
Diagnostics.IdValueEventRaisedByRef,
"Value event subscribed to by-ref",
"Tried to subscribe to a value event '{0}' by-ref.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure that methods subscribing to value events do not have the ref keyword for the event argument."
);
private static readonly DiagnosticDescriptor ByRefEventRaisedByValueRule = new(
Diagnostics.IdByRefEventRaisedByValue,
"By-ref event raised by value",
@@ -55,7 +45,6 @@ public sealed class ByRefEventAnalyzer : DiagnosticAnalyzer
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
ByRefEventSubscribedByValueRule,
ByValueEventSubscribedByRefRule,
ByRefEventRaisedByValueRule,
ByValueEventRaisedByRefRule
);
@@ -64,71 +53,9 @@ public sealed class ByRefEventAnalyzer : DiagnosticAnalyzer
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
context.EnableConcurrentExecution();
context.RegisterOperationAction(CheckEventSubscription, OperationKind.Invocation);
context.RegisterOperationAction(CheckEventRaise, OperationKind.Invocation);
}
private void CheckEventSubscription(OperationAnalysisContext context)
{
if (context.Operation is not IInvocationOperation operation)
return;
var subscribeMethods = context.Compilation
.GetTypeByMetadataName("Robust.Shared.GameObjects.EntitySystem")?
.GetMembers()
.Where(m => m.Name.Contains("SubscribeLocalEvent"))
.Cast<IMethodSymbol>();
if (subscribeMethods == null)
return;
if (!subscribeMethods.Any(m => m.Equals(operation.TargetMethod.OriginalDefinition, Default)))
return;
var typeArguments = operation.TargetMethod.TypeArguments;
if (typeArguments.Length < 1 || typeArguments.Length > 2)
return;
if (operation.Arguments.First().Value is not IDelegateCreationOperation delegateCreation)
return;
if (delegateCreation.Target is not IMethodReferenceOperation methodReference)
return;
var eventParameter = methodReference.Method.Parameters.LastOrDefault();
if (eventParameter == null)
return;
ITypeSymbol eventArgument;
switch (typeArguments.Length)
{
case 1:
eventArgument = typeArguments[0];
break;
case 2:
eventArgument = typeArguments[1];
break;
default:
return;
}
var byRefAttribute = context.Compilation.GetTypeByMetadataName(ByRefAttribute);
if (byRefAttribute == null)
return;
var isByRefEventType = eventArgument
.GetAttributes()
.Any(attribute => attribute.AttributeClass?.Equals(byRefAttribute, Default) ?? false);
var parameterIsRef = eventParameter.RefKind == RefKind.Ref;
if (isByRefEventType != parameterIsRef)
{
var descriptor = isByRefEventType ? ByRefEventSubscribedByValueRule : ByValueEventSubscribedByRefRule;
var diagnostic = Diagnostic.Create(descriptor, operation.Syntax.GetLocation(), eventArgument);
context.ReportDiagnostic(diagnostic);
}
}
private void CheckEventRaise(OperationAnalysisContext context)
{
if (context.Operation is not IInvocationOperation operation)

View File

@@ -0,0 +1,293 @@
#nullable enable
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Robust.Analyzers;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class DataDefinitionAnalyzer : DiagnosticAnalyzer
{
private const string DataDefinitionNamespace = "Robust.Shared.Serialization.Manager.Attributes.DataDefinitionAttribute";
private const string ImplicitDataDefinitionNamespace = "Robust.Shared.Serialization.Manager.Attributes.ImplicitDataDefinitionForInheritorsAttribute";
private const string DataFieldBaseNamespace = "Robust.Shared.Serialization.Manager.Attributes.DataFieldBaseAttribute";
private static readonly DiagnosticDescriptor DataDefinitionPartialRule = new(
Diagnostics.IdDataDefinitionPartial,
"Type must be partial",
"Type {0} is a DataDefinition but is not partial.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to mark any type that is a data definition as partial."
);
private static readonly DiagnosticDescriptor NestedDataDefinitionPartialRule = new(
Diagnostics.IdNestedDataDefinitionPartial,
"Type must be partial",
"Type {0} contains nested data definition {1} but is not partial.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to mark any type containing a nested data definition as partial."
);
private static readonly DiagnosticDescriptor DataFieldWritableRule = new(
Diagnostics.IdDataFieldWritable,
"Data field must not be readonly",
"Data field {0} in data definition {1} is readonly.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to remove the readonly modifier."
);
private static readonly DiagnosticDescriptor DataFieldPropertyWritableRule = new(
Diagnostics.IdDataFieldPropertyWritable,
"Data field property must have a setter",
"Data field property {0} in data definition {1} does not have a setter.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to add a setter."
);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
DataDefinitionPartialRule, NestedDataDefinitionPartialRule, DataFieldWritableRule, DataFieldPropertyWritableRule
);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeDataDefinition, SyntaxKind.ClassDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataDefinition, SyntaxKind.StructDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataDefinition, SyntaxKind.RecordDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataDefinition, SyntaxKind.RecordStructDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataDefinition, SyntaxKind.InterfaceDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataField, SyntaxKind.FieldDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataFieldProperty, SyntaxKind.PropertyDeclaration);
}
private void AnalyzeDataDefinition(SyntaxNodeAnalysisContext context)
{
if (context.Node is not TypeDeclarationSyntax declaration)
return;
var type = context.SemanticModel.GetDeclaredSymbol(declaration)!;
if (!IsDataDefinition(type))
return;
if (!IsPartial(declaration))
{
context.ReportDiagnostic(Diagnostic.Create(DataDefinitionPartialRule, declaration.Keyword.GetLocation(), type.Name));
}
var containingType = type.ContainingType;
while (containingType != null)
{
var containingTypeDeclaration = (TypeDeclarationSyntax) containingType.DeclaringSyntaxReferences[0].GetSyntax();
if (!IsPartial(containingTypeDeclaration))
{
context.ReportDiagnostic(Diagnostic.Create(NestedDataDefinitionPartialRule, containingTypeDeclaration.Keyword.GetLocation(), containingType.Name, type.Name));
}
containingType = containingType.ContainingType;
}
}
private void AnalyzeDataField(SyntaxNodeAnalysisContext context)
{
if (context.Node is not FieldDeclarationSyntax field)
return;
var typeDeclaration = field.FirstAncestorOrSelf<TypeDeclarationSyntax>();
if (typeDeclaration == null)
return;
var type = context.SemanticModel.GetDeclaredSymbol(typeDeclaration)!;
if (!IsDataDefinition(type))
return;
foreach (var variable in field.Declaration.Variables)
{
var fieldSymbol = context.SemanticModel.GetDeclaredSymbol(variable);
if (fieldSymbol == null)
continue;
if (IsReadOnlyDataField(type, fieldSymbol))
{
context.ReportDiagnostic(Diagnostic.Create(DataFieldWritableRule, context.Node.GetLocation(), fieldSymbol.Name, type.Name));
}
}
}
private void AnalyzeDataFieldProperty(SyntaxNodeAnalysisContext context)
{
if (context.Node is not PropertyDeclarationSyntax property)
return;
var typeDeclaration = property.FirstAncestorOrSelf<TypeDeclarationSyntax>();
if (typeDeclaration == null)
return;
var type = context.SemanticModel.GetDeclaredSymbol(typeDeclaration)!;
if (!IsDataDefinition(type) || type.IsRecord || type.IsValueType)
return;
var propertySymbol = context.SemanticModel.GetDeclaredSymbol(property);
if (propertySymbol == null)
return;
if (IsReadOnlyDataField(type, propertySymbol))
{
context.ReportDiagnostic(Diagnostic.Create(DataFieldPropertyWritableRule, context.Node.GetLocation(), propertySymbol.Name, type.Name));
}
}
private static bool IsReadOnlyDataField(ITypeSymbol type, ISymbol field)
{
if (!IsDataField(field, out _, out _))
return false;
return IsReadOnlyMember(type, field);
}
private static bool IsPartial(TypeDeclarationSyntax type)
{
return type.Modifiers.IndexOf(SyntaxKind.PartialKeyword) != -1;
}
private static bool IsDataDefinition(ITypeSymbol? type)
{
if (type == null)
return false;
return HasAttribute(type, DataDefinitionNamespace) ||
IsImplicitDataDefinition(type);
}
private static bool IsDataField(ISymbol member, out ITypeSymbol type, out AttributeData attribute)
{
// TODO data records and other attributes
if (member is IFieldSymbol field)
{
foreach (var attr in field.GetAttributes())
{
if (attr.AttributeClass != null && Inherits(attr.AttributeClass, DataFieldBaseNamespace))
{
type = field.Type;
attribute = attr;
return true;
}
}
}
else if (member is IPropertySymbol property)
{
foreach (var attr in property.GetAttributes())
{
if (attr.AttributeClass != null && Inherits(attr.AttributeClass, DataFieldBaseNamespace))
{
type = property.Type;
attribute = attr;
return true;
}
}
}
type = null!;
attribute = null!;
return false;
}
private static bool Inherits(ITypeSymbol type, string parent)
{
foreach (var baseType in GetBaseTypes(type))
{
if (baseType.ToDisplayString() == parent)
return true;
}
return false;
}
private static bool IsReadOnlyMember(ITypeSymbol type, ISymbol member)
{
if (member is IFieldSymbol field)
{
return field.IsReadOnly;
}
else if (member is IPropertySymbol property)
{
if (property.SetMethod == null)
return true;
if (property.SetMethod.IsInitOnly)
return type.IsReferenceType;
return false;
}
return false;
}
private static bool HasAttribute(ITypeSymbol type, string attributeName)
{
foreach (var attribute in type.GetAttributes())
{
if (attribute.AttributeClass?.ToDisplayString() == attributeName)
return true;
}
return false;
}
private static bool IsImplicitDataDefinition(ITypeSymbol type)
{
if (HasAttribute(type, ImplicitDataDefinitionNamespace))
return true;
foreach (var baseType in GetBaseTypes(type))
{
if (HasAttribute(baseType, ImplicitDataDefinitionNamespace))
return true;
}
foreach (var @interface in type.AllInterfaces)
{
if (IsImplicitDataDefinitionInterface(@interface))
return true;
}
return false;
}
private static bool IsImplicitDataDefinitionInterface(ITypeSymbol @interface)
{
if (HasAttribute(@interface, ImplicitDataDefinitionNamespace))
return true;
foreach (var subInterface in @interface.AllInterfaces)
{
if (HasAttribute(subInterface, ImplicitDataDefinitionNamespace))
return true;
}
return false;
}
private static IEnumerable<ITypeSymbol> GetBaseTypes(ITypeSymbol type)
{
var baseType = type.BaseType;
while (baseType != null)
{
yield return baseType;
baseType = baseType.BaseType;
}
}
}

View File

@@ -0,0 +1,168 @@
#nullable enable
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxKind;
using static Robust.Analyzers.Diagnostics;
namespace Robust.Analyzers;
[ExportCodeFixProvider(LanguageNames.CSharp)]
public sealed class DefinitionFixer : CodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(
IdDataDefinitionPartial, IdNestedDataDefinitionPartial, IdDataFieldWritable, IdDataFieldPropertyWritable
);
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
foreach (var diagnostic in context.Diagnostics)
{
switch (diagnostic.Id)
{
case IdDataDefinitionPartial:
return RegisterPartialTypeFix(context, diagnostic);
case IdNestedDataDefinitionPartial:
return RegisterPartialTypeFix(context, diagnostic);
case IdDataFieldWritable:
return RegisterDataFieldFix(context, diagnostic);
case IdDataFieldPropertyWritable:
return RegisterDataFieldPropertyFix(context, diagnostic);
}
}
return Task.CompletedTask;
}
public override FixAllProvider GetFixAllProvider()
{
return WellKnownFixAllProviders.BatchFixer;
}
private static async Task RegisterPartialTypeFix(CodeFixContext context, Diagnostic diagnostic)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
var span = diagnostic.Location.SourceSpan;
var token = root?.FindToken(span.Start).Parent?.AncestorsAndSelf().OfType<TypeDeclarationSyntax>().First();
if (token == null)
return;
context.RegisterCodeFix(CodeAction.Create(
"Make type partial",
c => MakeDataDefinitionPartial(context.Document, token, c),
"Make type partial"
), diagnostic);
}
private static async Task<Document> MakeDataDefinitionPartial(Document document, TypeDeclarationSyntax declaration, CancellationToken cancellation)
{
var root = (CompilationUnitSyntax?) await document.GetSyntaxRootAsync(cancellation);
var token = SyntaxFactory.Token(PartialKeyword);
var newDeclaration = declaration.AddModifiers(token);
root = root!.ReplaceNode(declaration, newDeclaration);
return document.WithSyntaxRoot(root);
}
private static async Task RegisterDataFieldFix(CodeFixContext context, Diagnostic diagnostic)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
var span = diagnostic.Location.SourceSpan;
var field = root?.FindToken(span.Start).Parent?.AncestorsAndSelf().OfType<FieldDeclarationSyntax>().FirstOrDefault();
if (field == null)
return;
context.RegisterCodeFix(CodeAction.Create(
"Make data field writable",
c => MakeFieldWritable(context.Document, field, c),
"Make data field writable"
), diagnostic);
}
private static async Task RegisterDataFieldPropertyFix(CodeFixContext context, Diagnostic diagnostic)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
var span = diagnostic.Location.SourceSpan;
var property = root?.FindToken(span.Start).Parent?.AncestorsAndSelf().OfType<PropertyDeclarationSyntax>().FirstOrDefault();
if (property == null)
return;
context.RegisterCodeFix(CodeAction.Create(
"Make data field writable",
c => MakePropertyWritable(context.Document, property, c),
"Make data field writable"
), diagnostic);
}
private static async Task<Document> MakeFieldWritable(Document document, FieldDeclarationSyntax declaration, CancellationToken cancellation)
{
var root = (CompilationUnitSyntax?) await document.GetSyntaxRootAsync(cancellation);
var token = declaration.Modifiers.First(t => t.IsKind(ReadOnlyKeyword));
var newDeclaration = declaration.WithModifiers(declaration.Modifiers.Remove(token));
root = root!.ReplaceNode(declaration, newDeclaration);
return document.WithSyntaxRoot(root);
}
private static async Task<Document> MakePropertyWritable(Document document, PropertyDeclarationSyntax declaration, CancellationToken cancellation)
{
var root = (CompilationUnitSyntax?) await document.GetSyntaxRootAsync(cancellation);
var newDeclaration = declaration;
var privateSet = newDeclaration
.AccessorList?
.Accessors
.FirstOrDefault(s => s.IsKind(SetAccessorDeclaration) || s.IsKind(InitAccessorDeclaration));
if (newDeclaration.AccessorList != null && privateSet != null)
{
newDeclaration = newDeclaration.WithAccessorList(
newDeclaration.AccessorList.WithAccessors(
newDeclaration.AccessorList.Accessors.Remove(privateSet)
)
);
}
AccessorDeclarationSyntax setter;
if (declaration.Modifiers.Any(m => m.IsKind(PrivateKeyword)))
{
setter = SyntaxFactory.AccessorDeclaration(
SetAccessorDeclaration,
default,
default,
SyntaxFactory.Token(SetKeyword),
default,
default,
SyntaxFactory.Token(SemicolonToken)
);
}
else
{
setter = SyntaxFactory.AccessorDeclaration(
SetAccessorDeclaration,
default,
SyntaxFactory.TokenList(SyntaxFactory.Token(PrivateKeyword)),
SyntaxFactory.Token(SetKeyword),
default,
default,
SyntaxFactory.Token(SemicolonToken)
);
}
newDeclaration = newDeclaration.AddAccessorListAccessors(setter);
root = root!.ReplaceNode(declaration, newDeclaration);
return document.WithSyntaxRoot(root);
}
}

View File

@@ -18,9 +18,12 @@ public static class Diagnostics
public const string IdInvalidNotNullableFlagType = "RA0011";
public const string IdNotNullableFlagValueType = "RA0012";
public const string IdByRefEventSubscribedByValue = "RA0013";
public const string IdValueEventSubscribedByRef = "RA0014";
public const string IdByRefEventRaisedByValue = "RA0015";
public const string IdValueEventRaisedByRef = "RA0016";
public const string IdDataDefinitionPartial = "RA0017";
public const string IdNestedDataDefinitionPartial = "RA0018";
public const string IdDataFieldWritable = "RA0019";
public const string IdDataFieldPropertyWritable = "RA0020";
public static SuppressionDescriptor MeansImplicitAssignment =>
new SuppressionDescriptor("RADC1000", "CS0649", "Marked as implicitly assigned.");

View File

@@ -0,0 +1,177 @@
using System;
using System.Runtime.CompilerServices;
using Arch.Core;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Engines;
using Robust.Shared.Analyzers;
using static Robust.Benchmarks.EntityManager.ArchetypeComponentAccessBenchmark;
namespace Robust.Benchmarks.Arch;
[MemoryDiagnoser]
[Virtual]
public class ArchComponentAccessBenchmark
{
private const int N = 10000;
private static readonly Consumer Consumer = new();
private Entity _entity;
private World _world = default!;
private QueryDescription _singleQuery;
private QueryDescription _tenQuery;
[GlobalSetup]
public void GlobalSetup()
{
var _ = new JobScheduler.JobScheduler("ArchBenchmark");
_world = World.Create();
for (var i = 0; i < N; i++)
{
var entity = _world.Create();
// Randomly chosen id
if (entity.Id == 1584)
_entity = entity;
_world.Add(
entity,
new Struct1(),
new Struct2(),
new Struct3(),
new Struct4(),
new Struct5(),
new Struct6(),
new Struct7(),
new Struct8(),
new Struct9(),
new Struct10()
);
}
_singleQuery = new QueryDescription().WithAll<Struct1>();
_tenQuery = new QueryDescription().WithAll<Struct1, Struct2, Struct3, Struct4, Struct5, Struct6, Struct7, Struct8, Struct9, Struct10>();
}
[GlobalCleanup]
public void GlobalCleanup()
{
JobScheduler.JobScheduler.Instance.Dispose();
Environment.Exit(0);
}
[Benchmark]
public Struct1 GetSingle()
{
return _world.Get<Struct1>(_entity);
}
[Benchmark]
public (Struct1, Struct2, Struct3, Struct4, Struct5, Struct6, Struct7, Struct8, Struct9, Struct10)
GetTen()
{
return (
_world.Get<Struct1>(_entity),
_world.Get<Struct2>(_entity),
_world.Get<Struct3>(_entity),
_world.Get<Struct4>(_entity),
_world.Get<Struct5>(_entity),
_world.Get<Struct6>(_entity),
_world.Get<Struct7>(_entity),
_world.Get<Struct8>(_entity),
_world.Get<Struct9>(_entity),
_world.Get<Struct10>(_entity)
);
}
[Benchmark]
public bool HasSingle()
{
return _world.Has<Struct1>(_entity);
}
[Benchmark]
public bool HasTen()
{
return _world.Has<Struct1>(_entity) &&
_world.Has<Struct2>(_entity) &&
_world.Has<Struct3>(_entity) &&
_world.Has<Struct4>(_entity) &&
_world.Has<Struct5>(_entity) &&
_world.Has<Struct6>(_entity) &&
_world.Has<Struct7>(_entity) &&
_world.Has<Struct8>(_entity) &&
_world.Has<Struct9>(_entity) &&
_world.Has<Struct10>(_entity);
}
[Benchmark]
public void IterateSingle()
{
_world.Query(_singleQuery, static (ref Struct1 s) => Consumer.Consume(s));
}
[Benchmark]
public void IterateSingleInline()
{
_world.InlineQuery<QueryConsumer>(_singleQuery);
}
[Benchmark]
public void IterateSingleParallel()
{
_world.ParallelQuery(_singleQuery, static (ref Struct1 s) => Consumer.Consume(s));
}
[Benchmark]
public void IterateSingleInlineParallel()
{
_world.InlineParallelQuery<QueryConsumer>(_singleQuery);
}
[Benchmark]
public void IterateTen()
{
_world.Query(_tenQuery,
static (
ref Struct1 s1, ref Struct2 s2, ref Struct3 s3, ref Struct4 s4,
ref Struct5 s5, ref Struct6 s6, ref Struct7 s7, ref Struct8 s8,
ref Struct9 s9, ref Struct10 s10) =>
Consumer.Consume((s1, s2, s3, s4, s5, s6, s7, s8, s9, s10)));
}
[Benchmark]
public void IterateTenInline()
{
_world.InlineQuery<QueryConsumer>(_tenQuery);
}
[Benchmark]
public void IterateTenParallel()
{
_world.ParallelQuery(_tenQuery,
static (
ref Struct1 s1, ref Struct2 s2, ref Struct3 s3, ref Struct4 s4,
ref Struct5 s5, ref Struct6 s6, ref Struct7 s7, ref Struct8 s8,
ref Struct9 s9, ref Struct10 s10) =>
Consumer.Consume((s1, s2, s3, s4, s5, s6, s7, s8, s9, s10)));
}
[Benchmark]
public void IterateTenInlineParallel()
{
_world.InlineParallelQuery<QueryConsumer>(_tenQuery);
}
private struct QueryConsumer : IForEach
{
private static readonly Consumer Consumer = new();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(Entity entity)
{
Consumer.Consume(entity);
}
}
}

View File

@@ -8,7 +8,7 @@ using Robust.UnitTesting.Server;
namespace Robust.Benchmarks.EntityManager;
[Virtual]
public class AddRemoveComponentBenchmark
public partial class AddRemoveComponentBenchmark
{
private ISimulation _simulation = default!;
private IEntityManager _entityManager = default!;
@@ -41,14 +41,14 @@ public class AddRemoveComponentBenchmark
{
for (var i = 2; i <= N+1; i++)
{
var uid = new EntityUid(i);
var uid = new EntityUid(i, -1);
_entityManager.AddComponent<A>(uid);
_entityManager.RemoveComponent<A>(uid);
}
}
[ComponentProtoName("A")]
public sealed class A : Component
public sealed partial class A : Component
{
}
}

View File

@@ -482,7 +482,7 @@ public class ArchetypeComponentAccessBenchmark
public struct Struct9{}
public struct Struct10{}
private sealed class Archetype<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>
public sealed class Archetype<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>
{
private int _nextId;
private readonly Dictionary<int, int> _ids;
@@ -905,7 +905,7 @@ public class ArchetypeComponentAccessBenchmark
var curLength = array.Length;
if (curLength <= idx.Value)
{
var newLength = MathHelper.NextPowerOfTwo(Math.Max(8, idx.Value));
var newLength = MathHelper.NextPowerOfTwo(System.Math.Max(8, idx.Value));
Array.Resize(ref array, newLength);
}

View File

@@ -57,7 +57,7 @@ public class ComponentIndexBenchmark
private static class CompArrayIndex<T>
{
// ReSharper disable once StaticMemberInGenericType
public static readonly CompIdx Idx = new(Interlocked.Increment(ref _compIndexMaster));
public static readonly CompIdx Idx = new(Interlocked.Increment(ref _compIndexMaster), typeof(T));
}
private static CompIdx GetCompIdIndex(Type type)

View File

@@ -0,0 +1,75 @@
using BenchmarkDotNet.Attributes;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.UnitTesting.Server;
namespace Robust.Benchmarks.EntityManager;
public partial class ComponentIteratorBenchmark
{
private ISimulation _simulation = default!;
private IEntityManager _entityManager = default!;
[UsedImplicitly]
[Params(1, 10, 100, 1000)]
public int N;
public A[] Comps = default!;
[GlobalSetup]
public void GlobalSetup()
{
_simulation = RobustServerSimulation
.NewSimulation()
.RegisterComponents(f => f.RegisterClass<A>())
.InitializeInstance();
_entityManager = _simulation.Resolve<IEntityManager>();
Comps = new A[N+2];
var coords = new MapCoordinates(0, 0, new MapId(1));
_simulation.AddMap(coords.MapId);
for (var i = 0; i < N; i++)
{
var uid = _entityManager.SpawnEntity(null, coords);
_entityManager.AddComponent<A>(uid);
}
}
[Benchmark]
public A[] ComponentStructEnumerator()
{
var query = _entityManager.EntityQueryEnumerator<A>();
var i = 0;
while (query.MoveNext(out var comp))
{
Comps[i] = comp;
i++;
}
return Comps;
}
[Benchmark]
public A[] ComponentIEnumerable()
{
var i = 0;
foreach (var comp in _entityManager.EntityQuery<A>())
{
Comps[i] = comp;
i++;
}
return Comps;
}
[ComponentProtoName("A")]
public sealed partial class A : Component
{
}
}

View File

@@ -0,0 +1,53 @@
using BenchmarkDotNet.Attributes;
using Robust.Shared.Analyzers;
using static Robust.Benchmarks.EntityManager.ArchetypeComponentAccessBenchmark;
namespace Robust.Benchmarks.EntityManager;
[MemoryDiagnoser]
[Virtual]
public class ArrayAccessBenchmark
{
[Params(new[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9})]
public int[] Array = default!;
[Params(5)]
public int Element;
[Params(500)]
public int Handle;
public Archetype<int, int, int, int, int, int, int, int, int, int> Archetype = default!;
[GlobalSetup]
public void GlobalSetup()
{
Archetype = new Archetype<int, int, int, int, int, int, int, int, int, int>(1000);
}
[Benchmark]
public int? GetArrayElement()
{
return Consume();
}
[Benchmark]
public int? GetExisting()
{
return Consume(Element);
}
[Benchmark]
public int? GetArchetype()
{
return Consume(Archetype.GetComponentUnsafeHandle<int>(Handle));
}
private int? Consume(int? value = null)
{
if (value == null)
value = Array[5];
return value;
}
}

View File

@@ -1,4 +1,3 @@
using System;
using BenchmarkDotNet.Attributes;
using JetBrains.Annotations;
using Robust.Shared.Analyzers;
@@ -9,7 +8,7 @@ using Robust.UnitTesting.Server;
namespace Robust.Benchmarks.EntityManager;
[Virtual]
public class GetComponentBenchmark
public partial class GetComponentBenchmark
{
private ISimulation _simulation = default!;
private IEntityManager _entityManager = default!;
@@ -47,7 +46,7 @@ public class GetComponentBenchmark
{
for (var i = 2; i <= N+1; i++)
{
Comps[i] = _entityManager.GetComponent<A>(new EntityUid(i));
Comps[i] = _entityManager.GetComponent<A>(new EntityUid(i, -1));
}
// Return something so the JIT doesn't optimize out all the GetComponent calls.
@@ -55,7 +54,7 @@ public class GetComponentBenchmark
}
[ComponentProtoName("A")]
public sealed class A : Component
public sealed partial class A : Component
{
}
}

View File

@@ -8,7 +8,7 @@ using Robust.UnitTesting.Server;
namespace Robust.Benchmarks.EntityManager;
[Virtual]
public class SpawnDeleteEntityBenchmark
public partial class SpawnDeleteEntityBenchmark
{
private ISimulation _simulation = default!;
private IEntityManager _entityManager = default!;
@@ -56,7 +56,7 @@ public class SpawnDeleteEntityBenchmark
}
[ComponentProtoName("A")]
public sealed class A : Component
public sealed partial class A : Component
{
}
}

View File

@@ -1,33 +1,32 @@
using BenchmarkDotNet.Attributes;
using Robust.Shared.Analyzers;
namespace Robust.Benchmarks.NumericsHelpers
namespace Robust.Benchmarks.NumericsHelpers;
[Virtual]
public class AddBenchmark
{
[Virtual]
public class AddBenchmark
[Params(32, 128)]
public int N { get; set; }
[Params(1,2)]
public int T { get; set; }
private float[] _inputA = default!;
private float[] _inputB = default!;
private float[] _output = default!;
[GlobalSetup]
public void Setup()
{
[Params(32, 128)]
public int N { get; set; }
_inputA = new float[N];
_inputB = new float[N];
_output = new float[N];
}
[Params(1,2)]
public int T { get; set; }
private float[] _inputA = default!;
private float[] _inputB = default!;
private float[] _output = default!;
[GlobalSetup]
public void Setup()
{
_inputA = new float[N];
_inputB = new float[N];
_output = new float[N];
}
[Benchmark]
public void Bench()
{
Shared.Maths.NumericsHelpers.Add(_inputA, _inputB, _output);
}
[Benchmark]
public void Bench()
{
Shared.Maths.NumericsHelpers.Add(_inputA, _inputB, _output);
}
}

View File

@@ -8,6 +8,7 @@
<NoWarn>RA0003</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Arch\Arch.csproj" />
<ProjectReference Include="..\Robust.Server\Robust.Server.csproj" />
<ProjectReference Include="..\Robust.Shared\Robust.Shared.csproj" />
<ProjectReference Include="..\Robust.UnitTesting\Robust.UnitTesting.csproj" />

View File

@@ -33,8 +33,8 @@ namespace Robust.Benchmarks.Serialization
return new ValueDataNode(value.ToString(CultureInfo.InvariantCulture));
}
public int CreateCopy(ISerializationManager serializationManager, int source, SerializationHookContext hookCtx,
ISerializationContext? context = null)
public int CreateCopy(ISerializationManager serializationManager, int source,
IDependencyCollection dependencies, SerializationHookContext hookCtx, ISerializationContext? context = null)
{
return source;
}

View File

@@ -108,9 +108,7 @@ namespace Robust.Benchmarks.Serialization.Copy
copy.Potency = Seed.Potency;
copy.Ligneous = Seed.Ligneous;
copy.PlantRsi = Seed.PlantRsi == null
? null!
: new ResourcePath(Seed.PlantRsi.ToString(), Seed.PlantRsi.Separator);
copy.PlantRsi = new ResPath(Seed.PlantRsi.ToString());
copy.PlantIconState = Seed.PlantIconState;
copy.Bioluminescent = Seed.Bioluminescent;
copy.BioluminescentColor = Seed.BioluminescentColor;

View File

@@ -5,9 +5,9 @@ namespace Robust.Benchmarks.Serialization.Definitions
{
[DataDefinition]
[Virtual]
public class DataDefinitionWithString
public partial class DataDefinitionWithString
{
[DataField("string")]
public string StringField { get; init; } = default!;
public string StringField { get; set; } = default!;
}
}

View File

@@ -3,9 +3,9 @@
namespace Robust.Benchmarks.Serialization.Definitions
{
[DataDefinition]
public sealed class SealedDataDefinitionWithString
public sealed partial class SealedDataDefinitionWithString
{
[DataField("string")]
public string StringField { get; init; } = default!;
public string StringField { get; private set; } = default!;
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager.Attributes;
@@ -10,8 +11,7 @@ namespace Robust.Benchmarks.Serialization.Definitions
/// Arbitrarily large data definition for benchmarks.
/// Taken from content.
/// </summary>
[Prototype("seed")]
public sealed class SeedDataDefinition : IPrototype
public sealed partial class SeedDataDefinition : Component
{
public const string Prototype = @"
- type: seed
@@ -87,7 +87,7 @@ namespace Robust.Benchmarks.Serialization.Definitions
#endregion
#region Cosmetics
[DataField("plantRsi", required: true)] public ResourcePath PlantRsi { get; set; } = default!;
[DataField("plantRsi", required: true)] public ResPath PlantRsi { get; set; } = default!;
[DataField("plantIconState")] public string PlantIconState { get; set; } = "produce";
[DataField("bioluminescent")] public bool Bioluminescent { get; set; }
[DataField("bioluminescentColor")] public Color BioluminescentColor { get; set; } = Color.White;
@@ -106,7 +106,7 @@ namespace Robust.Benchmarks.Serialization.Definitions
}
[DataDefinition]
public struct SeedChemQuantity
public partial struct SeedChemQuantity
{
[DataField("Min")]
public int Min;

View File

@@ -0,0 +1,171 @@
using System;
using System.Linq;
using System.Numerics;
using BenchmarkDotNet.Attributes;
using Robust.Server.Containers;
using Robust.Server.GameStates;
using Robust.Shared;
using Robust.Shared.Analyzers;
using Robust.Shared.Configuration;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.UnitTesting.Server;
namespace Robust.Benchmarks.Transform;
/// <summary>
/// This benchmark tests various transform/move related functions with an entity that has many children.
/// </summary>
[Virtual, MemoryDiagnoser]
public class RecursiveMoveBenchmark
{
private ISimulation _simulation = default!;
private IEntityManager _entMan = default!;
private SharedTransformSystem _transform = default!;
private ContainerSystem _container = default!;
private PvsSystem _pvs = default!;
private EntityCoordinates _mapCoords;
private EntityCoordinates _gridCoords;
private EntityUid _ent;
private EntityUid _child;
private TransformComponent _childXform = default!;
private EntityQuery<TransformComponent> _query;
[GlobalSetup]
public void GlobalSetup()
{
_simulation = RobustServerSimulation
.NewSimulation()
.InitializeInstance();
if (!_simulation.Resolve<IConfigurationManager>().GetCVar(CVars.NetPVS))
throw new InvalidOperationException("PVS must be enabled");
_entMan = _simulation.Resolve<IEntityManager>();
_transform = _entMan.System<SharedTransformSystem>();
_container = _entMan.System<ContainerSystem>();
_pvs = _entMan.System<PvsSystem>();
_query = _entMan.GetEntityQuery<TransformComponent>();
// Create map & grid
var mapMan = _simulation.Resolve<IMapManager>();
var mapSys = _entMan.System<SharedMapSystem>();
var mapId = mapMan.CreateMap();
var map = mapMan.GetMapEntityId(mapId);
var gridComp = mapMan.CreateGridEntity(mapId);
var grid = gridComp.Owner;
_gridCoords = new EntityCoordinates(grid, .5f, .5f);
_mapCoords = new EntityCoordinates(map, 100, 100);
mapSys.SetTile(grid, gridComp, Vector2i.Zero, new Tile(1));
// Next, we will spawn our test entity. This entity will have a complex transform/container hierarchy.
// This is intended to be representative of a typical SS14 player entity, with organs. clothing, and a full backpack.
_ent = _entMan.Spawn();
// Quick check that SetCoordinates actually changes the parent as expected
// I.e., ensure that grid-traversal code doesn't just dump the entity on the map.
_transform.SetCoordinates(_ent, _gridCoords);
if (_query.GetComponent(_ent).ParentUid != _gridCoords.EntityId)
throw new Exception("Grid traversal error.");
_transform.SetCoordinates(_ent, _mapCoords);
if (_query.GetComponent(_ent).ParentUid != _mapCoords.EntityId)
throw new Exception("Grid traversal error.");
// Add 5 direct children in slots to represent clothing.
for (var i = 0; i < 5; i++)
{
var id = $"inventory{i}";
_container.EnsureContainer<ContainerSlot>(_ent, id);
if (!_entMan.TrySpawnInContainer(null, _ent, id, out _))
throw new Exception($"Failed to setup entity");
}
// body parts
_container.EnsureContainer<Container>(_ent, "body");
for (var i = 0; i < 5; i++)
{
// Simple organ
if (!_entMan.TrySpawnInContainer(null, _ent, "body", out _))
throw new Exception($"Failed to setup entity");
// body part that has another body part / limb
if (!_entMan.TrySpawnInContainer(null, _ent, "body", out var limb))
throw new Exception($"Failed to setup entity");
_container.EnsureContainer<ContainerSlot>(limb.Value, "limb");
if (!_entMan.TrySpawnInContainer(null, limb.Value, "limb", out _))
throw new Exception($"Failed to setup entity");
}
// Backpack
_container.EnsureContainer<ContainerSlot>(_ent, "inventory-backpack");
if (!_entMan.TrySpawnInContainer(null, _ent, "inventory-backpack", out var backpack))
throw new Exception($"Failed to setup entity");
// Misc backpack contents.
var backpackStorage = _container.EnsureContainer<Container>(backpack.Value, "storage");
for (var i = 0; i < 10; i++)
{
if (!_entMan.TrySpawnInContainer(null, backpack.Value, "storage", out _))
throw new Exception($"Failed to setup entity");
}
// Emergency box inside of the backpack
var box = backpackStorage.ContainedEntities.First();
var boxContainer = _container.EnsureContainer<Container>(box, "storage");
for (var i = 0; i < 10; i++)
{
if (!_entMan.TrySpawnInContainer(null, box, "storage", out _))
throw new Exception($"Failed to setup entity");
}
// Deepest child.
_child = boxContainer.ContainedEntities.First();
_childXform = _query.GetComponent(_child);
_pvs.ProcessCollections();
}
/// <summary>
/// This implicitly measures move events, including PVS and entity lookups. Though given that most of the entities
/// are in containers, this will bias the entity lookup aspect.
/// </summary>
[Benchmark]
public void MoveEntity()
{
_transform.SetCoordinates(_ent, _gridCoords);
_transform.SetCoordinates(_ent, _mapCoords);
}
/// <summary>
/// Like <see cref="MoveEntity"/>, but also processes queued PVS chunk updates.
/// </summary>
[Benchmark]
public void MoveAndUpdateChunks()
{
_transform.SetCoordinates(_ent, _gridCoords);
_pvs.ProcessCollections();
_transform.SetCoordinates(_ent, _mapCoords);
_pvs.ProcessCollections();
}
[Benchmark]
public Vector2 GetWorldPos()
{
return _transform.GetWorldPosition(_childXform);
}
[Benchmark]
public EntityUid GetRootUid()
{
var xform = _childXform;
while (xform.ParentUid.IsValid())
{
xform = _query.GetComponent(xform.ParentUid);
}
return xform.ParentUid;
}
}

View File

@@ -0,0 +1,36 @@
using BenchmarkDotNet.Attributes;
using JetBrains.Annotations;
using Robust.Shared.Analyzers;
using Robust.Shared.Utility;
#pragma warning disable CS0612
namespace Robust.Benchmarks.Utility;
[Virtual]
public class ResourcePathBench
{
private string _path = default!;
[UsedImplicitly]
[Params(10, 100, 1000)]
public int N;
[GlobalSetup]
public void GlobalSetup()
{
_path = "/a/b/c/../test";
}
[Benchmark]
public ResPath CreateWithSeparatorResPath()
{
ResPath res = default;
for (var i = 0; i < N; i++)
{
res = new ResPath(_path);
}
return res;
}
}
#pragma warning restore CS0612

View File

@@ -25,7 +25,7 @@ namespace Robust.Build.Tasks
Single = ts.GetType("System.Single");
Int32 = ts.GetType("System.Int32");
(Vector2, Vector2ConstructorFull) = GetNumericTypeInfo("Robust.Shared.Maths.Vector2", Single, 2);
(Vector2, Vector2ConstructorFull) = GetNumericTypeInfo("System.Numerics.Vector2", Single, 2);
(Vector2i, Vector2iConstructorFull) = GetNumericTypeInfo("Robust.Shared.Maths.Vector2i", Int32, 2);
(Thickness, ThicknessConstructorFull) = GetNumericTypeInfo("Robust.Shared.Maths.Thickness", Single, 4);

View File

@@ -110,25 +110,6 @@ namespace Robust.Build.Tasks
var compiler =
new RobustXamlILCompiler(transformerconfig, emitConfig, true);
var loaderDispatcherDef = new TypeDefinition("CompiledRobustXaml", "!XamlLoader",
TypeAttributes.Class, asm.MainModule.TypeSystem.Object);
var loaderDispatcherMethod = new MethodDefinition("TryLoad",
MethodAttributes.Static | MethodAttributes.Public,
asm.MainModule.TypeSystem.Object)
{
Parameters = {new ParameterDefinition(asm.MainModule.TypeSystem.String)}
};
loaderDispatcherDef.Methods.Add(loaderDispatcherMethod);
asm.MainModule.Types.Add(loaderDispatcherDef);
var stringEquals = asm.MainModule.ImportReference(asm.MainModule.TypeSystem.String.Resolve().Methods.First(
m =>
m.IsStatic && m.Name == "Equals" && m.Parameters.Count == 2 &&
m.ReturnType.FullName == "System.Boolean"
&& m.Parameters[0].ParameterType.FullName == "System.String"
&& m.Parameters[1].ParameterType.FullName == "System.String"));
bool CompileGroup(IResourceGroup group)
{
var typeDef = new TypeDefinition("CompiledRobustXaml", "!" + group.Name, TypeAttributes.Class,
@@ -252,31 +233,6 @@ namespace Robust.Build.Tasks
$"No call to RobustXamlLoader.Load(this) call found anywhere in the type {classType.FullName} and type seems to have custom constructors.");
}
}
//add compiled build method
var compiledBuildMethod = typeSystem.GetTypeReference(builder).Resolve().Methods
.First(m => m.Name == buildName);
var parameterlessCtor = classTypeDefinition.GetConstructors()
.FirstOrDefault(c => c.IsPublic && !c.IsStatic && !c.HasParameters);
if (compiledBuildMethod != null && parameterlessCtor != null)
{
var i = loaderDispatcherMethod.Body.Instructions;
var nop = Instruction.Create(OpCodes.Nop);
i.Add(Instruction.Create(OpCodes.Ldarg_0));
i.Add(Instruction.Create(OpCodes.Ldstr, res.Uri));
i.Add(Instruction.Create(OpCodes.Call, stringEquals));
i.Add(Instruction.Create(OpCodes.Brfalse, nop));
if (parameterlessCtor != null)
i.Add(Instruction.Create(OpCodes.Newobj, parameterlessCtor));
else
{
i.Add(Instruction.Create(OpCodes.Call, compiledBuildMethod));
}
i.Add(Instruction.Create(OpCodes.Ret));
i.Add(nop);
}
}
catch (Exception e)
{
@@ -293,8 +249,6 @@ namespace Robust.Build.Tasks
return false;
}
loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ldnull));
loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
return true;
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.UserInterface;

View File

@@ -60,7 +60,7 @@ namespace Robust.Client.WebView.Cef
var cachePath = "";
if (_resourceManager.UserData is WritableDirProvider userData)
cachePath = userData.GetFullPath(new ResourcePath("/cef_cache"));
cachePath = userData.GetFullPath(new ResPath("/cef_cache"));
var settings = new CefSettings()
{
@@ -85,12 +85,10 @@ namespace Robust.Client.WebView.Cef
_app = new RobustCefApp(_sawmill);
// We pass no main arguments...
CefRuntime.Initialize(new CefMainArgs(null), settings, _app, IntPtr.Zero);
// TODO CEF: After this point, debugging breaks. No, literally. My client crashes but ONLY with the debugger.
// I have tried using the DEBUG and RELEASE versions of libcef.so, stripped or non-stripped...
// And nothing seemed to work. Odd.
// So these arguments look like nonsense, but it turns out CEF is just *like that*.
// The first argument is literally nonsense, but it needs to be there as otherwise the second argument doesn't apply
// The second argument turns off CEF's bullshit error handling, which breaks dotnet's error handling.
CefRuntime.Initialize(new CefMainArgs(new string[]{"binary","--disable-in-process-stack-traces"}), settings, _app, IntPtr.Zero);
if (_cfg.GetCVar(WCVars.WebResProtocol))
{
@@ -171,10 +169,10 @@ namespace Robust.Client.WebView.Cef
_sawmill.Debug($"HANDLING: {request.Url}");
var resourcePath = new ResourcePath(uri.AbsolutePath);
if (_resourceManager.TryContentFileRead(resourcePath, out var stream))
var resPath = new ResPath(uri.AbsolutePath);
if (_resourceManager.TryContentFileRead(resPath, out var stream))
{
if (!_parent.TryGetResourceMimeType(resourcePath.Extension, out var mime))
if (!_parent.TryGetResourceMimeType(resPath.Extension, out var mime))
mime = "application/octet-stream";
return new RequestResultStream(stream, mime, HttpStatusCode.OK).MakeHandler();

View File

@@ -1,7 +1,10 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using Robust.Shared.Animations;
using Robust.Shared.Maths;
using Vector3 = Robust.Shared.Maths.Vector3;
using Vector4 = Robust.Shared.Maths.Vector4;
namespace Robust.Client.Animations
{
@@ -117,7 +120,7 @@ namespace Robust.Client.Animations
switch (a)
{
case Vector2 vector2:
return Vector2.InterpolateCubic((Vector2) preA, vector2, (Vector2) b, (Vector2) postB, t);
return Vector2Helpers.InterpolateCubic((Vector2) preA, vector2, (Vector2) b, (Vector2) postB, t);
case Vector3 vector3:
return Vector3.InterpolateCubic((Vector3) preA, vector3, (Vector3) b, (Vector3) postB, t);
case Vector4 vector4:

View File

@@ -1,4 +1,4 @@
using System;
using System;
using Robust.Client.Graphics;
namespace Robust.Client.Audio;
@@ -8,13 +8,17 @@ public sealed class AudioStream
public TimeSpan Length { get; }
internal ClydeHandle? ClydeHandle { get; }
public string? Name { get; }
public string? Title { get; }
public string? Artist { get; }
public int ChannelCount { get; }
internal AudioStream(ClydeHandle handle, TimeSpan length, int channelCount, string? name = null)
internal AudioStream(ClydeHandle handle, TimeSpan length, int channelCount, string? name = null, string? title = null, string? artist = null)
{
ClydeHandle = handle;
Length = length;
ChannelCount = channelCount;
Name = name;
Title = title;
Artist = artist;
}
}

View File

@@ -1,4 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Robust.Client.Graphics;
using Robust.Shared.Audio.Midi;
using Robust.Shared.GameObjects;
@@ -15,7 +17,6 @@ public enum MidiRendererStatus : byte
public interface IMidiRenderer : IDisposable
{
/// <summary>
/// The buffered audio source of this renderer.
/// </summary>
@@ -34,6 +35,7 @@ public interface IMidiRenderer : IDisposable
/// <summary>
/// This increases all note on velocities to 127.
/// </summary>
[Obsolete($"Use {nameof(VelocityOverride)} instead, you can set it to 127 to achieve the same effect.")]
bool VolumeBoost { get; set; }
/// <summary>
@@ -94,6 +96,27 @@ public interface IMidiRenderer : IDisposable
/// </summary>
double SequencerTimeScale { get; }
/// <summary>
/// Whether this renderer will subscribe to another and copy its events.
/// See <see cref="FilteredChannels"/> to filter specific channels.
/// </summary>
IMidiRenderer? Master { get; set; }
// NOTE: Why is the properties below BitArray, you ask?
// Well see, MIDI 2.0 supports up to 256(!) channels as opposed to MIDI 1.0's meekly 16 channels...
// I'd like us to support MIDI 2.0 one day so I'm just future-proofing here. Also BitArray is cool!
/// <summary>
/// Allows you to filter out note events from certain channels.
/// Only NoteOn will be filtered.
/// </summary>
BitArray FilteredChannels { get; }
/// <summary>
/// Allows you to override all NoteOn velocities. Set to null to disable.
/// </summary>
byte? VelocityOverride { get; set; }
/// <summary>
/// Start listening for midi input.
/// </summary>
@@ -120,6 +143,16 @@ public interface IMidiRenderer : IDisposable
/// </summary>
void StopAllNotes();
/// <summary>
/// Reset renderer back to a clean state.
/// </summary>
void SystemReset();
/// <summary>
/// Clears all scheduled events.
/// </summary>
void ClearAllEvents();
/// <summary>
/// Render and play MIDI to the audio source.
/// </summary>
@@ -151,7 +184,7 @@ public interface IMidiRenderer : IDisposable
/// This is only used if <see cref="Mono"/> is set to True
/// and <see cref="TrackingEntity"/> is null.
/// </summary>
EntityCoordinates? TrackingCoordinates { get; set; }
MapCoordinates? TrackingCoordinates { get; set; }
MidiRendererState RendererState { get; }
@@ -159,7 +192,8 @@ public interface IMidiRenderer : IDisposable
/// Send a midi event for the renderer to play.
/// </summary>
/// <param name="midiEvent">The midi event to be played</param>
void SendMidiEvent(RobustMidiEvent midiEvent);
/// <param name="raiseEvent">Whether to raise an event for this event.</param>
void SendMidiEvent(RobustMidiEvent midiEvent, bool raiseEvent = true);
/// <summary>
/// Schedule a MIDI event to be played at a later time.
@@ -172,7 +206,7 @@ public interface IMidiRenderer : IDisposable
/// <summary>
/// Apply a certain state to the renderer.
/// </summary>
void ApplyState(MidiRendererState state);
void ApplyState(MidiRendererState state, bool filterChannels = false);
/// <summary>
/// Actually disposes of this renderer. Do NOT use outside the MIDI thread.

View File

@@ -3,20 +3,27 @@ using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using NFluidsynth;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared;
using Robust.Shared.Asynchronous;
using Robust.Shared.Audio.Midi;
using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;
using Robust.Shared.Exceptions;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Threading;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
@@ -24,6 +31,15 @@ namespace Robust.Client.Audio.Midi;
internal sealed partial class MidiManager : IMidiManager
{
public const string SoundfontEnvironmentVariable = "ROBUST_SOUNDFONT_OVERRIDE";
private int _minRendererParallel;
private float _occlusionUpdateDelay;
private float _positionUpdateDelay;
[ViewVariables] private TimeSpan _nextOcclusionUpdate = TimeSpan.Zero;
[ViewVariables] private TimeSpan _nextPositionUpdate = TimeSpan.Zero;
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IResourceCacheInternal _resourceManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
@@ -31,6 +47,9 @@ internal sealed partial class MidiManager : IMidiManager
[Dependency] private readonly IClydeAudio _clydeAudio = default!;
[Dependency] private readonly ITaskManager _taskManager = default!;
[Dependency] private readonly ILogManager _logger = default!;
[Dependency] private readonly IParallelManager _parallel = default!;
[Dependency] private readonly IRuntimeLog _runtime = default!;
[Dependency] private readonly IGameTiming _timing = default!;
private SharedPhysicsSystem _broadPhaseSystem = default!;
@@ -57,11 +76,10 @@ internal sealed partial class MidiManager : IMidiManager
}
}
[ViewVariables]
private readonly List<IMidiRenderer> _renderers = new();
[ViewVariables] private readonly List<IMidiRenderer> _renderers = new();
private bool _alive = true;
private Settings? _settings;
[ViewVariables] private Settings? _settings;
private Thread? _midiThread;
private ISawmill _midiSawmill = default!;
private float _volume = 0f;
@@ -87,10 +105,12 @@ internal sealed partial class MidiManager : IMidiManager
"/usr/share/soundfonts/default.sf2",
"/usr/share/soundfonts/default.dls",
"/usr/share/soundfonts/FluidR3_GM.sf2",
"/usr/share/soundfonts/FluidR3_GM2-2.sf2",
"/usr/share/soundfonts/freepats-general-midi.sf2",
"/usr/share/sounds/sf2/default.sf2",
"/usr/share/sounds/sf2/default.dls",
"/usr/share/sounds/sf2/FluidR3_GM.sf2",
"/usr/share/sounds/sf2/FluidR3_GM2-2.sf2",
"/usr/share/sounds/sf2/TimGM6mb.sf2",
};
@@ -103,7 +123,7 @@ internal sealed partial class MidiManager : IMidiManager
private const string ContentCustomSoundfontDirectory = "/Audio/MidiCustom/";
private static ResourcePath CustomSoundfontDirectory = new ResourcePath("/soundfonts/");
private static ResPath CustomSoundfontDirectory = new("/soundfonts/");
private readonly ResourceLoaderCallbacks _soundfontLoaderCallbacks;
@@ -111,7 +131,7 @@ internal sealed partial class MidiManager : IMidiManager
private bool _failedInitialize;
private NFluidsynth.Logger.LoggerDelegate _loggerDelegate = default!;
private ISawmill _sawmill = default!;
private ISawmill _fluidsynthSawmill = default!;
private float _maxCastLength;
[ViewVariables(VVAccess.ReadWrite)]
@@ -126,20 +146,28 @@ internal sealed partial class MidiManager : IMidiManager
{
if (FluidsynthInitialized || _failedInitialize) return;
_volume = _cfgMan.GetCVar(CVars.MidiVolume);
_cfgMan.OnValueChanged(CVars.MidiVolume, value =>
{
_volume = value;
_volumeDirty = true;
}, true);
_cfgMan.OnValueChanged(CVars.MidiMinRendererParallel,
value => _minRendererParallel = value, true);
_cfgMan.OnValueChanged(CVars.MidiOcclusionUpdateDelay,
value => _occlusionUpdateDelay = value, true);
_cfgMan.OnValueChanged(CVars.MidiPositionUpdateDelay,
value => _positionUpdateDelay = value, true);
_midiSawmill = _logger.GetSawmill("midi");
#if DEBUG
_midiSawmill.Level = LogLevel.Debug;
#else
_midiSawmill.Level = LogLevel.Error;
#endif
_sawmill = _logger.GetSawmill("midi.fluidsynth");
_fluidsynthSawmill = _logger.GetSawmill("midi.fluidsynth");
_loggerDelegate = LoggerDelegate;
if (!_resourceManager.UserData.Exists(CustomSoundfontDirectory))
@@ -163,8 +191,6 @@ internal sealed partial class MidiManager : IMidiManager
_settings["synth.lock-memory"].IntValue = 0;
_settings["synth.threadsafe-api"].IntValue = 1;
_settings["synth.gain"].DoubleValue = 1.0d;
_settings["synth.polyphony"].IntValue = 1024;
_settings["synth.cpu-cores"].IntValue = 2;
_settings["synth.midi-channels"].IntValue = 16;
_settings["synth.overflow.age"].DoubleValue = 3000;
_settings["audio.driver"].StringValue = "file";
@@ -172,8 +198,11 @@ internal sealed partial class MidiManager : IMidiManager
_settings["audio.period-size"].IntValue = 4096;
_settings["midi.autoconnect"].IntValue = 1;
_settings["player.reset-synth"].IntValue = 0;
_settings["synth.midi-channels"].IntValue = Math.Clamp(RobustMidiEvent.MaxChannels, 16, 256);
_settings["synth.midi-bank-select"].StringValue = "gm";
//_settings["synth.verbose"].IntValue = 1; // Useful for debugging.
_parallel.AddAndInvokeParallelCountChanged(UpdateParallelCount);
}
catch (Exception e)
{
@@ -191,6 +220,18 @@ internal sealed partial class MidiManager : IMidiManager
FluidsynthInitialized = true;
}
private void UpdateParallelCount()
{
if (_settings == null)
return;
_settings["synth.polyphony"].IntValue = Math.Clamp(1024 + (int)(Math.Log2(_parallel.ParallelProcessCount) * 2048), 1, 65535);
_settings["synth.cpu-cores"].IntValue = Math.Clamp(_parallel.ParallelProcessCount, 1, 256);
_midiSawmill.Debug($"Synth Cores: {_settings["synth.cpu-cores"].IntValue}");
_midiSawmill.Debug($"Synth Polyphony: {_settings["synth.polyphony"].IntValue}");
}
private void OnRaycastLengthChanged(float value)
{
_maxCastLength = value;
@@ -207,7 +248,7 @@ internal sealed partial class MidiManager : IMidiManager
NFluidsynth.Logger.LogLevel.Debug => LogLevel.Debug,
_ => LogLevel.Debug
};
_sawmill.Log(rLevel, message);
_fluidsynthSawmill.Log(rLevel, message);
}
public IMidiRenderer? GetNewRenderer(bool mono = true)
@@ -234,10 +275,11 @@ internal sealed partial class MidiManager : IMidiManager
var renderer = new MidiRenderer(_settings!, soundfontLoader, mono, this, _clydeAudio, _taskManager, _midiSawmill);
_midiSawmill.Debug($"Loading soundfont {FallbackSoundfont}");
_midiSawmill.Debug($"Loading fallback soundfont {FallbackSoundfont}");
// Since the last loaded soundfont takes priority, we load the fallback soundfont before the soundfont.
renderer.LoadSoundfont(FallbackSoundfont);
// Load system-specific soundfonts.
if (OperatingSystem.IsLinux())
{
foreach (var filepath in LinuxSoundfonts)
@@ -247,8 +289,8 @@ internal sealed partial class MidiManager : IMidiManager
try
{
_midiSawmill.Debug($"Loading OS soundfont {filepath}");
renderer.LoadSoundfont(filepath);
_midiSawmill.Debug($"Loaded Linux soundfont {filepath}");
}
catch (Exception)
{
@@ -262,7 +304,7 @@ internal sealed partial class MidiManager : IMidiManager
{
if (File.Exists(OsxSoundfont) && SoundFont.IsSoundFont(OsxSoundfont))
{
_midiSawmill.Debug($"Loading soundfont {OsxSoundfont}");
_midiSawmill.Debug($"Loading OS soundfont {OsxSoundfont}");
renderer.LoadSoundfont(OsxSoundfont);
}
}
@@ -270,27 +312,42 @@ internal sealed partial class MidiManager : IMidiManager
{
if (File.Exists(WindowsSoundfont) && SoundFont.IsSoundFont(WindowsSoundfont))
{
_midiSawmill.Debug($"Loading soundfont {WindowsSoundfont}");
_midiSawmill.Debug($"Loading OS soundfont {WindowsSoundfont}");
renderer.LoadSoundfont(WindowsSoundfont);
}
}
// Load content-specific custom soundfonts, which could override the system/fallback soundfont.
_midiSawmill.Debug($"Loading soundfonts from {ContentCustomSoundfontDirectory}");
// Maybe load soundfont specified in environment variable.
// Load it here so it can override system soundfonts but not content or user data soundfonts.
if (Environment.GetEnvironmentVariable(SoundfontEnvironmentVariable) is {} soundfontOverride)
{
if (File.Exists(soundfontOverride) && SoundFont.IsSoundFont(soundfontOverride))
{
_midiSawmill.Debug($"Loading environment variable soundfont {soundfontOverride}");
renderer.LoadSoundfont(soundfontOverride);
}
}
// Load content-specific custom soundfonts, which should override the system/fallback soundfont.
_midiSawmill.Debug($"Loading soundfonts from content directory {ContentCustomSoundfontDirectory}");
foreach (var file in _resourceManager.ContentFindFiles(ContentCustomSoundfontDirectory))
{
if (file.Extension != "sf2" && file.Extension != "dls") continue;
_midiSawmill.Debug($"Loading soundfont {file}");
if (file.Extension != "sf2" && file.Extension != "dls" && file.Extension != "sf3") continue;
_midiSawmill.Debug($"Loading content soundfont {file}");
renderer.LoadSoundfont(file.ToString());
}
var userDataPath = _resourceManager.UserData.RootDir == null
? CustomSoundfontDirectory
: new ResPath(_resourceManager.UserData.RootDir) / CustomSoundfontDirectory.ToRelativePath();
// Load every soundfont from the user data directory last, since those may override any other soundfont.
_midiSawmill.Debug($"Loading soundfonts from {{USERDATA}} {CustomSoundfontDirectory}");
var enumerator = _resourceManager.UserData.Find($"{CustomSoundfontDirectory.ToRelativePath()}/*").Item1;
_midiSawmill.Debug($"Loading soundfonts from user data directory {userDataPath}");
var enumerator = _resourceManager.UserData.Find($"{CustomSoundfontDirectory.ToRelativePath()}*").Item1;
foreach (var file in enumerator)
{
if (file.Extension != "sf2" && file.Extension != "dls") continue;
_midiSawmill.Debug($"Loading soundfont {{USERDATA}} {file}");
if (file.Extension != "sf2" && file.Extension != "dls" && file.Extension != "sf3") continue;
_midiSawmill.Debug($"Loading user soundfont {file}");
renderer.LoadSoundfont(file.ToString());
}
@@ -320,72 +377,108 @@ internal sealed partial class MidiManager : IMidiManager
lock (_renderers)
{
foreach (var renderer in _renderers)
if (_renderers.Count == 0)
return;
var transQuery = _entityManager.GetEntityQuery<TransformComponent>();
var physicsQuery = _entityManager.GetEntityQuery<PhysicsComponent>();
var opts = new ParallelOptions { MaxDegreeOfParallelism = _parallel.ParallelProcessCount };
if (_renderers.Count > _minRendererParallel)
{
if (renderer.Disposed)
continue;
if(_volumeDirty)
renderer.Source.SetVolume(Volume);
if (!renderer.Mono)
Parallel.ForEach(_renderers, opts, renderer => UpdateRenderer(renderer, transQuery, physicsQuery));
}
else
{
foreach (var renderer in _renderers)
{
renderer.Source.SetGlobal();
continue;
}
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);
}
if (mapPos != null && mapPos.Value.MapId == _eyeManager.CurrentMap)
{
var pos = mapPos.Value;
var sourceRelative = pos.Position - _eyeManager.CurrentEye.Position.Position;
var occlusion = 0f;
if (sourceRelative.Length > 0)
{
occlusion = _broadPhaseSystem.IntersectRayPenetration(
pos.MapId,
new CollisionRay(
_eyeManager.CurrentEye.Position.Position,
sourceRelative.Normalized,
OcclusionCollisionMask),
MathF.Min(sourceRelative.Length, _maxCastLength),
renderer.TrackingEntity);
}
renderer.Source.SetOcclusion(occlusion);
if (!renderer.Source.SetPosition(pos.Position))
{
return;
}
if (trackingEntity)
{
var vel = _broadPhaseSystem.GetMapLinearVelocity(renderer.TrackingEntity!.Value);
renderer.Source.SetVelocity(vel);
}
}
else
{
renderer.Source.SetOcclusion(float.MaxValue);
UpdateRenderer(renderer, transQuery, physicsQuery);
}
}
}
if (_nextOcclusionUpdate < _timing.RealTime)
_nextOcclusionUpdate = _timing.RealTime.Add(TimeSpan.FromSeconds(_occlusionUpdateDelay));
if (_nextPositionUpdate < _timing.RealTime)
_nextPositionUpdate = _timing.RealTime.Add(TimeSpan.FromSeconds(_positionUpdateDelay));
_volumeDirty = false;
}
private void UpdateRenderer(IMidiRenderer renderer, EntityQuery<TransformComponent> transQuery,
EntityQuery<PhysicsComponent> physicsQuery)
{
try
{
if (renderer.Disposed)
return;
if (_volumeDirty)
renderer.Source.SetVolume(Volume);
if (!renderer.Mono)
{
renderer.Source.SetGlobal();
return;
}
if (_nextPositionUpdate < _timing.RealTime)
{
if (renderer.TrackingEntity is {} trackedEntity && !_entityManager.Deleted(trackedEntity))
{
renderer.TrackingCoordinates = transQuery.GetComponent(renderer.TrackingEntity!.Value).MapPosition;
}
else if (renderer.TrackingCoordinates == null)
{
return;
}
if (!renderer.Source.SetPosition(renderer.TrackingCoordinates.Value.Position))
{
return;
}
var vel = _broadPhaseSystem.GetMapLinearVelocity(renderer.TrackingEntity!.Value,
xformQuery: transQuery, physicsQuery: physicsQuery);
renderer.Source.SetVelocity(vel);
}
if (renderer.TrackingCoordinates != null && renderer.TrackingCoordinates.Value.MapId == _eyeManager.CurrentMap)
{
if (_nextOcclusionUpdate >= _timing.RealTime)
return;
var pos = renderer.TrackingCoordinates.Value;
var sourceRelative = pos.Position - _eyeManager.CurrentEye.Position.Position;
var occlusion = 0f;
if (sourceRelative.Length() > 0)
{
occlusion = _broadPhaseSystem.IntersectRayPenetration(
pos.MapId,
new CollisionRay(
_eyeManager.CurrentEye.Position.Position,
sourceRelative.Normalized(),
OcclusionCollisionMask),
MathF.Min(sourceRelative.Length(), _maxCastLength),
renderer.TrackingEntity);
}
renderer.Source.SetOcclusion(occlusion);
}
else
{
renderer.Source.SetOcclusion(float.MaxValue);
}
}
catch (Exception ex)
{
_runtime.LogException(ex, _midiSawmill.Name);
}
}
/// <summary>
/// Main method for the thread rendering the midi audio.
@@ -400,7 +493,12 @@ internal sealed partial class MidiManager : IMidiManager
{
var renderer = _renderers[i];
if (!renderer.Disposed)
{
if (renderer.Master is { Disposed: true })
renderer.Master = null;
renderer.Render();
}
else
{
renderer.InternalDispose();
@@ -476,7 +574,7 @@ internal sealed partial class MidiManager : IMidiManager
Stream? stream;
var resourceCache = _parent._resourceManager;
var resourcePath = new ResourcePath(filename);
var resourcePath = new ResPath(filename);
if (resourcePath.IsRooted)
{
@@ -550,7 +648,7 @@ internal sealed partial class MidiManager : IMidiManager
return 0;
}
public override int Seek(IntPtr sfHandle, int offset, SeekOrigin origin)
public override int Seek(IntPtr sfHandle, long offset, SeekOrigin origin)
{
var stream = _openStreams[(int) sfHandle];
@@ -559,11 +657,11 @@ internal sealed partial class MidiManager : IMidiManager
return 0;
}
public override int Tell(IntPtr sfHandle)
public override long Tell(IntPtr sfHandle)
{
var stream = _openStreams[(int) sfHandle];
return (int) stream.Position;
return (long) stream.Position;
}
public override int Close(IntPtr sfHandle)

View File

@@ -1,4 +1,6 @@
using System;
using System.Collections;
using JetBrains.Annotations;
using NFluidsynth;
using Robust.Client.Graphics;
using Robust.Shared.Asynchronous;
@@ -9,7 +11,6 @@ using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
using Logger = Robust.Shared.Log.Logger;
namespace Robust.Client.Audio.Midi;
@@ -21,14 +22,13 @@ internal sealed class MidiRenderer : IMidiRenderer
// TODO: Make this a replicated CVar in MidiManager
private const int MidiSizeLimit = 2000000;
private const double BytesToMegabytes = 0.000001d;
private const int ChannelCount = 16;
private const int ChannelCount = RobustMidiEvent.MaxChannels;
private readonly ISawmill _midiSawmill;
private readonly Settings _settings;
[ViewVariables(VVAccess.ReadWrite)]
private bool _debugEvents = false;
[ViewVariables(VVAccess.ReadWrite)] private bool _debugEvents = false;
// Kept around to avoid the loader callbacks getting GC'd
// ReSharper disable once NotAccessedField.Local
@@ -48,8 +48,9 @@ internal sealed class MidiRenderer : IMidiRenderer
private readonly SequencerClientId _robustRegister;
private readonly SequencerClientId _debugRegister;
[ViewVariables]
private MidiRendererState _rendererState = new();
[ViewVariables] private MidiRendererState _rendererState = new();
private IMidiRenderer? _master;
public MidiRendererState RendererState => _rendererState;
public IClydeBufferedAudioSource Source { get; set; }
IClydeBufferedAudioSource IMidiRenderer.Source => Source;
@@ -70,8 +71,8 @@ internal sealed class MidiRenderer : IMidiRenderer
{
for (byte i = 0; i < ChannelCount; i++)
{
// Channel 9 is the percussion channel. Let's not change its instrument...
if (i == 9)
// Don't change percussion channel instrument.
if (i == RobustMidiEvent.PercussionChannel)
continue;
SendMidiEvent(RobustMidiEvent.ProgramChange(i, value, SequencerTick));
@@ -96,11 +97,14 @@ internal sealed class MidiRenderer : IMidiRenderer
{
for (byte i = 0; i < ChannelCount; i++)
{
// Channel 9 is the percussion channel. Let's not change its bank...
if (i == 9)
// Don't change percussion channel bank.
if (i == RobustMidiEvent.PercussionChannel)
continue;
SendMidiEvent(RobustMidiEvent.BankSelect(i, value, SequencerTick));
// Re-select program.
SendMidiEvent(RobustMidiEvent.ProgramChange(i, _midiProgram, SequencerTick));
}
}
@@ -128,7 +132,11 @@ internal sealed class MidiRenderer : IMidiRenderer
}
[ViewVariables(VVAccess.ReadWrite)]
public bool DisablePercussionChannel { get; set; } = true;
public bool DisablePercussionChannel
{
get => FilteredChannels[RobustMidiEvent.PercussionChannel];
set => FilteredChannels[RobustMidiEvent.PercussionChannel] = value;
}
[ViewVariables(VVAccess.ReadWrite)]
public bool DisableProgramChangeEvent { get; set; } = true;
@@ -181,13 +189,62 @@ internal sealed class MidiRenderer : IMidiRenderer
}
[ViewVariables(VVAccess.ReadWrite)]
public bool VolumeBoost { get; set; }
[Obsolete($"Use {nameof(VelocityOverride)} instead, you can set it to 127 to achieve the same effect.")]
public bool VolumeBoost
{
get => VelocityOverride == 127;
set => VelocityOverride = value ? 127 : null;
}
[ViewVariables(VVAccess.ReadWrite)]
public EntityUid? TrackingEntity { get; set; } = null;
[ViewVariables(VVAccess.ReadWrite)]
public EntityCoordinates? TrackingCoordinates { get; set; } = null;
public MapCoordinates? TrackingCoordinates { get; set; } = null;
[ViewVariables]
public BitArray FilteredChannels { get; } = new(RobustMidiEvent.MaxChannels);
[ViewVariables(VVAccess.ReadWrite)]
public byte? VelocityOverride { get; set; } = null;
[ViewVariables(VVAccess.ReadWrite)]
public IMidiRenderer? Master
{
get => _master;
set
{
if (value == _master)
return;
if (_master is { Disposed: false })
{
try
{
_master.OnMidiEvent -= SendMidiEvent;
}
catch
{
// ignored
}
}
_master = value;
if (_master == null)
return;
_master.OnMidiEvent += SendMidiEvent;
ApplyState(_master.RendererState, true);
MidiBank = _midiBank;
}
}
[ViewVariables, UsedImplicitly]
private double CpuLoad => !_synth.Disposed ? _synth.CpuLoad : 0;
public event Action<RobustMidiEvent>? OnMidiEvent;
public event Action? OnMidiPlayerFinished;
internal MidiRenderer(Settings settings, SoundFontLoader soundFontLoader, bool mono,
IMidiManager midiManager, IClydeAudio clydeAudio, ITaskManager taskManager, ISawmill midiSawmill)
@@ -354,6 +411,16 @@ internal sealed class MidiRenderer : IMidiRenderer
}
}
public void SystemReset()
{
SendMidiEvent(RobustMidiEvent.SystemReset(SequencerTick));
}
public void ClearAllEvents()
{
_sequencer.RemoveEvents(SequencerClientId.Wildcard, SequencerClientId.Wildcard, -1);
}
public void LoadSoundfont(string filename, bool resetPresets = true)
{
lock (_playerStateLock)
@@ -363,9 +430,6 @@ internal sealed class MidiRenderer : IMidiRenderer
}
}
public event Action<RobustMidiEvent>? OnMidiEvent;
public event Action? OnMidiPlayerFinished;
void IMidiRenderer.Render()
{
Render();
@@ -427,7 +491,7 @@ internal sealed class MidiRenderer : IMidiRenderer
if (!Source.IsPlaying) Source.StartPlaying();
}
public void ApplyState(MidiRendererState state)
public void ApplyState(MidiRendererState state, bool filterChannels = false)
{
lock (_playerStateLock)
{
@@ -435,6 +499,9 @@ internal sealed class MidiRenderer : IMidiRenderer
for (var channel = 0; channel < ChannelCount; channel++)
{
if (filterChannels && !FilteredChannels[channel])
continue;
_synth.AllNotesOff(channel);
_synth.PitchBend(channel, state.PitchBend.AsSpan[channel]);
@@ -457,7 +524,8 @@ internal sealed class MidiRenderer : IMidiRenderer
}
}
_synth.ProgramChange(channel, state.Program.AsSpan[channel]);
var program = DisableProgramChangeEvent ? MidiProgram : state.Program.AsSpan[channel];
_synth.ProgramChange(channel, program);
for (var key = 0; key < state.NoteVelocities.AsSpan[channel].AsSpan.Length; key++)
{
@@ -482,7 +550,12 @@ internal sealed class MidiRenderer : IMidiRenderer
}
}
public void SendMidiEvent(RobustMidiEvent midiEvent)
private void SendMidiEvent(RobustMidiEvent midiEvent)
{
SendMidiEvent(midiEvent, true);
}
public void SendMidiEvent(RobustMidiEvent midiEvent, bool raiseEvent)
{
if (Disposed)
return;
@@ -500,11 +573,10 @@ internal sealed class MidiRenderer : IMidiRenderer
break;
case RobustMidiCommand.NoteOn:
// Channel 9 is the percussion channel. We only block NoteOn events to it.
if (DisablePercussionChannel && midiEvent.Channel == 9)
return;
if (FilteredChannels[midiEvent.Channel])
break;
var velocity = (byte)(VolumeBoost ? 127 : midiEvent.Velocity);
var velocity = VelocityOverride ?? midiEvent.Velocity;
_rendererState.NoteVelocities.AsSpan[midiEvent.Channel].AsSpan[midiEvent.Key] = velocity;
_synth.NoteOn(midiEvent.Channel, midiEvent.Key, velocity);
@@ -518,7 +590,7 @@ internal sealed class MidiRenderer : IMidiRenderer
case RobustMidiCommand.ControlChange:
// CC0 is bank selection
if (midiEvent.Control == 0x0 && DisableProgramChangeEvent)
return;
break;
_rendererState.Controllers.AsSpan[midiEvent.Channel].AsSpan[midiEvent.Control] = midiEvent.Value;
if(midiEvent.Control != 0x0)
@@ -529,7 +601,7 @@ internal sealed class MidiRenderer : IMidiRenderer
case RobustMidiCommand.ProgramChange:
if (DisableProgramChangeEvent)
return;
break;
_rendererState.Program.AsSpan[midiEvent.Channel] = midiEvent.Program;
_synth.ProgramChange(midiEvent.Channel, midiEvent.Program);
@@ -556,14 +628,14 @@ internal sealed class MidiRenderer : IMidiRenderer
switch (midiEvent.Control)
{
case 0x0 when midiEvent.Status == 0xFF:
_rendererState = new ();
_rendererState = new MidiRendererState();
_synth.SystemReset();
// Reset the instrument to the one we were using.
if (DisableProgramChangeEvent)
{
MidiProgram = _midiProgram;
MidiBank = _midiBank;
MidiProgram = _midiProgram;
}
break;
@@ -592,7 +664,10 @@ internal sealed class MidiRenderer : IMidiRenderer
//_midiSawmill.Error("Exception while sending midi event of type {0}: {1}", midiEvent.Type, e, midiEvent);
}
_taskManager.RunOnMainThread(() => OnMidiEvent?.Invoke(midiEvent));
if (raiseEvent)
{
_taskManager.RunOnMainThread(() => OnMidiEvent?.Invoke(midiEvent));
}
}
public void ScheduleMidiEvent(RobustMidiEvent midiEvent, uint time, bool absolute = false)
@@ -628,6 +703,9 @@ internal sealed class MidiRenderer : IMidiRenderer
/// <inheritdoc />
void IMidiRenderer.InternalDispose()
{
OnMidiEvent = null;
OnMidiPlayerFinished = null;
Source?.Dispose();
_driver?.Dispose();

View File

@@ -1,6 +1,7 @@
using System;
using System.Runtime.InteropServices;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
namespace Robust.Client.Audio.Midi;
@@ -12,7 +13,7 @@ public struct MidiRendererState
internal FixedArray16<byte> ChannelPressure;
internal FixedArray16<ushort> PitchBend;
internal Span<byte> AsSpan => MemoryMarshal.CreateSpan(ref NoteVelocities._00._00, 4160);
[ViewVariables] internal Span<byte> AsSpan => MemoryMarshal.CreateSpan(ref NoteVelocities._00._00, 4160);
static unsafe MidiRendererState()
{

View File

@@ -1,7 +1,6 @@
using System;
using System.Net;
using Robust.Client.Configuration;
using Robust.Client.Debugging;
using Robust.Client.GameObjects;
using Robust.Client.GameStates;
using Robust.Client.Player;
@@ -9,20 +8,19 @@ using Robust.Client.Utility;
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.Enums;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Network.Messages;
using Robust.Shared.Players;
using Robust.Shared.Player;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Robust.Client
{
/// <inheritdoc />
public sealed class BaseClient : IBaseClient
public sealed class BaseClient : IBaseClient, IPostInjectInit
{
[Dependency] private readonly IClientNetManager _net = default!;
[Dependency] private readonly IPlayerManager _playMan = default!;
@@ -32,6 +30,7 @@ namespace Robust.Client
[Dependency] private readonly IDiscordRichPresence _discord = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IClientGameStateManager _gameStates = default!;
[Dependency] private readonly ILogManager _logMan = default!;
/// <inheritdoc />
public ushort DefaultPort { get; } = 1212;
@@ -48,6 +47,7 @@ namespace Robust.Client
public string? LastDisconnectReason { get; private set; }
private (TimeSpan, GameTick) _timeBase;
private ISawmill _logger = default!;
/// <inheritdoc />
public void Initialize()
@@ -62,13 +62,21 @@ namespace Robust.Client
_configManager.OnValueChanged(CVars.NetTickrate, TickRateChanged, invokeImmediately: true);
_playMan.Initialize();
_playMan.Initialize(0);
_playMan.PlayerListUpdated += OnPlayerListUpdated;
Reset();
}
private void OnPlayerListUpdated()
{
var serverPlayers = _playMan.PlayerCount;
if (_net.ServerChannel != null && GameInfo != null && _net.IsConnected)
_discord.Update(GameInfo.ServerName, _net.ServerChannel.UserName, GameInfo.ServerMaxPlayers.ToString(), serverPlayers.ToString());
}
private void SyncTimeBase(MsgSyncTimeBase message)
{
Logger.DebugS("client", $"Synchronized time base: {message.Tick}: {message.Time}");
_logger.Debug($"Synchronized time base: {message.Tick}: {message.Time}");
if (RunLevel >= ClientRunLevel.Connected)
_timing.TimeBase = (message.Time, message.Tick);
@@ -84,7 +92,7 @@ namespace Robust.Client
}
_timing.SetTickRateAt((byte) tickrate, info.TickChanged);
Logger.InfoS("client", $"Tickrate changed to: {tickrate} on tick {_timing.CurTick}");
_logger.Info($"Tickrate changed to: {tickrate} on tick {_timing.CurTick}");
}
/// <inheritdoc />
@@ -119,9 +127,10 @@ namespace Robust.Client
{
DebugTools.Assert(RunLevel < ClientRunLevel.Connecting);
DebugTools.Assert(!_net.IsConnected);
_playMan.Startup();
_playMan.LocalPlayer!.Name = PlayerNameOverride ?? _configManager.GetCVar(CVars.PlayerName);
var name = PlayerNameOverride ?? _configManager.GetCVar(CVars.PlayerName);
_playMan.SetupSinglePlayer(name);
OnRunLevelChanged(ClientRunLevel.SinglePlayerGame);
_playMan.JoinGame(_playMan.LocalSession!);
GameStartedSetup();
}
@@ -162,19 +171,15 @@ namespace Robust.Client
info.ServerName = serverName;
}
var maxPlayers = _configManager.GetCVar<int>("game.maxplayers");
info.ServerMaxPlayers = maxPlayers;
var channel = _net.ServerChannel!;
var userName = _net.ServerChannel!.UserName;
var userId = _net.ServerChannel.UserId;
_discord.Update(info.ServerName, userName, info.ServerMaxPlayers.ToString());
// start up player management
_playMan.Startup();
_playMan.SetupMultiplayer(channel);
_playMan.PlayerStatusChanged += OnStatusChanged;
_playMan.LocalPlayer!.UserId = userId;
_playMan.LocalPlayer.Name = userName;
var serverPlayers = _playMan.PlayerCount;
_discord.Update(info.ServerName, channel.UserName, info.ServerMaxPlayers.ToString(), serverPlayers.ToString());
_playMan.LocalPlayer.StatusChanged += OnLocalStatusChanged;
}
/// <summary>
@@ -206,6 +211,8 @@ namespace Robust.Client
private void Reset()
{
_configManager.ReceivedInitialNwVars -= OnReceivedClientData;
_playMan.PlayerStatusChanged -= OnStatusChanged;
_configManager.ClearReceivedInitialNwVars();
OnRunLevelChanged(ClientRunLevel.Initialize);
}
@@ -248,28 +255,31 @@ namespace Robust.Client
Reset();
}
private void OnLocalStatusChanged(object? obj, StatusEventArgs eventArgs)
private void OnStatusChanged(object? sender, SessionStatusEventArgs e)
{
if (e.Session != _playMan.LocalSession)
return;
// player finished fully connecting to the server.
// OldStatus is used here because it can go from connecting-> connected or connecting-> ingame
if (eventArgs.OldStatus == SessionStatus.Connecting)
{
OnPlayerJoinedServer(_playMan.LocalPlayer!.Session);
}
if (eventArgs.NewStatus == SessionStatus.InGame)
{
OnPlayerJoinedGame(_playMan.LocalPlayer!.Session);
}
if (e.OldStatus == SessionStatus.Connecting)
OnPlayerJoinedServer(e.Session);
else if (e.NewStatus == SessionStatus.InGame)
OnPlayerJoinedGame(e.Session);
}
private void OnRunLevelChanged(ClientRunLevel newRunLevel)
{
Logger.DebugS("client", $"Runlevel changed to: {newRunLevel}");
_logger.Debug($"Runlevel changed to: {newRunLevel}");
var args = new RunLevelChangedEventArgs(RunLevel, newRunLevel);
RunLevel = newRunLevel;
RunLevelChanged?.Invoke(this, args);
}
void IPostInjectInit.PostInject()
{
_logger = _logMan.GetSawmill("client");
}
}
/// <summary>

View File

@@ -16,10 +16,13 @@ using Robust.Client.Profiling;
using Robust.Client.Prototypes;
using Robust.Client.Reflection;
using Robust.Client.Replays;
using Robust.Client.Replays.Loading;
using Robust.Client.Replays.Playback;
using Robust.Client.ResourceManagement;
using Robust.Client.Serialization;
using Robust.Client.State;
using Robust.Client.Timing;
using Robust.Client.Upload;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.RichText;
using Robust.Client.UserInterface.Themes;
@@ -34,12 +37,13 @@ using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Physics;
using Robust.Shared.Players;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Reflection;
using Robust.Shared.Replays;
using Robust.Shared.Serialization;
using Robust.Shared.Timing;
using Robust.Shared.Upload;
using Robust.Shared.ViewVariables;
namespace Robust.Client
@@ -64,6 +68,7 @@ namespace Robust.Client
deps.Register<IComponentFactory, ComponentFactory>();
deps.Register<ITileDefinitionManager, ClydeTileDefinitionManager>();
deps.Register<IClydeTileDefinitionManager, ClydeTileDefinitionManager>();
deps.Register<ClydeTileDefinitionManager, ClydeTileDefinitionManager>();
deps.Register<GameController, GameController>();
deps.Register<IGameController, GameController>();
deps.Register<IGameControllerInternal, GameController>();
@@ -77,7 +82,10 @@ namespace Robust.Client
deps.Register<IClientEntityManager, ClientEntityManager>();
deps.Register<IClientEntityManagerInternal, ClientEntityManager>();
deps.Register<IEntityNetworkManager, ClientEntityManager>();
deps.Register<IReplayLoadManager, ReplayLoadManager>();
deps.Register<IReplayPlaybackManager, ReplayPlaybackManager>();
deps.Register<IReplayRecordingManager, ReplayRecordingManager>();
deps.Register<IReplayRecordingManagerInternal, ReplayRecordingManager>();
deps.Register<IClientGameStateManager, ClientGameStateManager>();
deps.Register<IBaseClient, BaseClient>();
deps.Register<IPlayerManager, PlayerManager>();
@@ -90,6 +98,8 @@ namespace Robust.Client
deps.Register<IMidiManager, MidiManager>();
deps.Register<IAuthManager, AuthManager>();
deps.Register<ProfViewManager>();
deps.Register<IGamePrototypeLoadManager, GamePrototypeLoadManager>();
deps.Register<NetworkResourceManager>();
switch (mode)
{

View File

@@ -2,11 +2,13 @@ using Robust.Client.GameObjects;
using Robust.Shared.ComponentTrees;
using Robust.Shared.GameObjects;
using Robust.Shared.Physics;
using Robust.Shared.ViewVariables;
namespace Robust.Client.ComponentTrees;
[RegisterComponent]
public sealed class LightTreeComponent: Component, IComponentTreeComponent<PointLightComponent>
public sealed partial class LightTreeComponent: Component, IComponentTreeComponent<PointLightComponent>
{
[ViewVariables]
public DynamicTree<ComponentTreeEntry<PointLightComponent>> Tree { get; set; } = default!;
}

View File

@@ -1,3 +1,4 @@
using System.Numerics;
using Robust.Client.GameObjects;
using Robust.Shared.ComponentTrees;
using Robust.Shared.GameObjects;
@@ -18,8 +19,9 @@ public sealed class LightTreeSystem : ComponentTreeSystem<LightTreeComponent, Po
{
// Really we should be rotating the light offset by the relative rotation. But I assume the light offset will
// always be relatively small, so fuck it, this is probably faster than having to compute the angle every time.
var radius = entry.Component.Radius + entry.Component.Offset.Length;
return new Box2(pos - radius, pos + radius);
var radius = entry.Component.Radius + entry.Component.Offset.Length();
var radiusVec = new Vector2(radius, radius);
return new Box2(pos - radiusVec, pos + radiusVec);
}
protected override Box2 ExtractAabb(in ComponentTreeEntry<PointLightComponent> entry)

View File

@@ -6,7 +6,7 @@ using Robust.Shared.Physics;
namespace Robust.Client.ComponentTrees;
[RegisterComponent]
public sealed class SpriteTreeComponent: Component, IComponentTreeComponent<SpriteComponent>
public sealed partial class SpriteTreeComponent: Component, IComponentTreeComponent<SpriteComponent>
{
public DynamicTree<ComponentTreeEntry<SpriteComponent>> Tree { get; set; } = default!;
}

View File

@@ -1,3 +1,4 @@
using System.Numerics;
using Robust.Client.GameObjects;
using Robust.Shared.ComponentTrees;
using Robust.Shared.GameObjects;

View File

@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System;
using Robust.Shared.Network.Messages;
using Robust.Shared.Network;
using Robust.Shared.Replays;
using Robust.Shared.Utility;
namespace Robust.Client.Configuration;
@@ -12,6 +13,8 @@ namespace Robust.Client.Configuration;
internal sealed class ClientNetConfigurationManager : NetConfigurationManager, IClientNetConfigurationManager
{
[Dependency] private readonly IBaseClient _client = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IReplayRecordingManager _replay = default!;
private bool _receivedInitialNwVars = false;
@@ -86,6 +89,12 @@ internal sealed class ClientNetConfigurationManager : NetConfigurationManager, I
ApplyClientNetVarChange(message.NetworkedVars, message.Tick);
else
base.HandleNetVarMessage(message);
_replay.RecordClientMessage(new ReplayMessage.CvarChangeMsg()
{
ReplicatedCvars = message.NetworkedVars,
TimeBase = _timing.TimeBase
});
}
protected override void ApplyNetVarChange(

View File

@@ -14,20 +14,20 @@ internal sealed partial class ClientConsoleHost
private int _completionSeq;
public async Task<CompletionResult> GetCompletions(List<string> args, CancellationToken cancel)
public async Task<CompletionResult> GetCompletions(List<string> args, string argStr, CancellationToken cancel)
{
// Last element is the command currently being typed. May be empty.
// Logger.Debug($"Running completions: {string.Join(", ", args)}");
// _logger.Debug($"Running completions: {string.Join(", ", args)}");
var delay = _cfg.GetCVar(CVars.ConCompletionDelay);
if (delay > 0)
await Task.Delay((int)(delay * 1000), cancel);
return await CalcCompletions(args, cancel);
return await CalcCompletions(args, argStr, cancel);
}
private Task<CompletionResult> CalcCompletions(List<string> args, CancellationToken cancel)
private Task<CompletionResult> CalcCompletions(List<string> args, string argStr, CancellationToken cancel)
{
if (args.Count == 1)
{
@@ -44,10 +44,10 @@ internal sealed partial class ClientConsoleHost
if (!AvailableCommands.TryGetValue(args[0], out var cmd))
return Task.FromResult(CompletionResult.Empty);
return cmd.GetCompletionAsync(LocalShell, args.ToArray()[1..], cancel).AsTask();
return cmd.GetCompletionAsync(LocalShell, args.ToArray()[1..], argStr, cancel).AsTask();
}
private Task<CompletionResult> DoServerCompletions(List<string> args, CancellationToken cancel)
private Task<CompletionResult> DoServerCompletions(List<string> args, string argStr, CancellationToken cancel)
{
var tcs = new TaskCompletionSource<CompletionResult>();
var cts = CancellationTokenSource.CreateLinkedTokenSource(cancel);
@@ -62,6 +62,7 @@ internal sealed partial class ClientConsoleHost
var msg = new MsgConCompletion
{
Args = args.ToArray(),
ArgString = argStr,
Seq = seq
};

View File

@@ -10,9 +10,10 @@ using Robust.Shared.Console;
using Robust.Shared.Enums;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Maths;
using Robust.Shared.Network;
using Robust.Shared.Network.Messages;
using Robust.Shared.Players;
using Robust.Shared.Player;
using Robust.Shared.Reflection;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
@@ -21,13 +22,13 @@ namespace Robust.Client.Console
{
public sealed class AddStringArgs : EventArgs
{
public string Text { get; }
public FormattedMessage Text { get; }
public bool Local { get; }
public bool Error { get; }
public AddStringArgs(string text, bool local, bool error)
public AddStringArgs(FormattedMessage text, bool local, bool error)
{
Text = text;
Local = local;
@@ -46,16 +47,19 @@ namespace Robust.Client.Console
}
/// <inheritdoc cref="IClientConsoleHost" />
internal sealed partial class ClientConsoleHost : ConsoleHost, IClientConsoleHost, IConsoleHostInternal
internal sealed partial class ClientConsoleHost : ConsoleHost, IClientConsoleHost, IConsoleHostInternal, IPostInjectInit
{
[Dependency] private readonly IClientConGroupController _conGroup = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly IBaseClient _client = default!;
[Dependency] private readonly ILogManager _logMan = default!;
[ViewVariables] private readonly Dictionary<string, IConsoleCommand> _availableServerCommands = new();
private bool _requestedCommands;
private ISawmill _logger = default!;
private ISawmill _conLogger = default!;
public ClientConsoleHost() : base(isServer: false) {}
@@ -129,10 +133,17 @@ namespace Robust.Client.Console
AddFormatted?.Invoke(this, new AddFormattedMessageArgs(message));
}
public override void WriteLine(ICommonSession? session, FormattedMessage msg)
{
AddFormattedLine(msg);
}
/// <inheritdoc />
public override void WriteError(ICommonSession? session, string text)
{
OutputText(text, true, true);
var msg = new FormattedMessage();
msg.AddText(text);
OutputText(msg, true, true);
}
public bool IsCmdServer(IConsoleCommand cmd)
@@ -148,8 +159,13 @@ namespace Robust.Client.Console
if (string.IsNullOrWhiteSpace(command))
return;
WriteLine(null, "");
var msg = new FormattedMessage();
msg.PushColor(Color.Gold);
msg.AddText("> " + command);
msg.Pop();
// echo the command locally
WriteLine(null, "> " + command);
OutputText(msg, true, false);
//Commands are processed locally and then sent to the server to be processed there again.
var args = new List<string>();
@@ -171,7 +187,7 @@ namespace Robust.Client.Console
}
args.RemoveAt(0);
var shell = new ConsoleShell(this, null);
var shell = new ConsoleShell(this, session ?? _player.LocalPlayer?.Session, session == null);
var cmdArgs = args.ToArray();
AnyCommandExecuted?.Invoke(shell, commandName, command, cmdArgs);
@@ -202,7 +218,9 @@ namespace Robust.Client.Console
/// <inheritdoc />
public override void WriteLine(ICommonSession? session, string text)
{
OutputText(text, true, false);
var msg = new FormattedMessage();
msg.AddText(text);
OutputText(msg, true, false);
}
/// <inheritdoc />
@@ -211,12 +229,12 @@ namespace Robust.Client.Console
// We don't have anything to dispose.
}
private void OutputText(string text, bool local, bool error)
private void OutputText(FormattedMessage text, bool local, bool error)
{
AddString?.Invoke(this, new AddStringArgs(text, local, error));
var level = error ? LogLevel.Warning : LogLevel.Info;
Logger.LogS(level, "CON", text);
_conLogger.Log(level, text.ToString());
}
private void OnNetworkConnected(object? sender, NetChannelArgs netChannelArgs)
@@ -226,7 +244,7 @@ namespace Robust.Client.Console
private void HandleConCmdAck(MsgConCmdAck msg)
{
OutputText("< " + msg.Text, false, msg.Error);
OutputText(msg.Text, false, msg.Error);
}
private void HandleConCmdReg(MsgConCmdReg msg)
@@ -238,7 +256,7 @@ namespace Robust.Client.Console
// Do not do duplicate commands.
if (_availableServerCommands.ContainsKey(commandName))
{
Logger.Error("console", $"Server sent duplicate console command {commandName}");
_logger.Error($"Server sent duplicate console command {commandName}");
continue;
}
@@ -266,6 +284,12 @@ namespace Robust.Client.Console
_requestedCommands = true;
}
void IPostInjectInit.PostInject()
{
_logger = _logMan.GetSawmill("console");
_conLogger = _logMan.GetSawmill("CON");
}
/// <summary>
/// These dummies are made purely so list and help can list server-side commands.
/// </summary>
@@ -294,13 +318,14 @@ namespace Robust.Client.Console
public async ValueTask<CompletionResult> GetCompletionAsync(
IConsoleShell shell,
string[] args,
string argStr,
CancellationToken cancel)
{
var host = (ClientConsoleHost)shell.ConsoleHost;
var argsList = args.ToList();
argsList.Insert(0, Command);
return await host.DoServerCompletions(argsList, cancel);
return await host.DoServerCompletions(argsList, argStr, cancel);
}
}
@@ -312,16 +337,17 @@ namespace Robust.Client.Console
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
shell.RemoteExecuteCommand(argStr["> ".Length..]);
shell.RemoteExecuteCommand(argStr[">".Length..]);
}
public override async ValueTask<CompletionResult> GetCompletionAsync(
IConsoleShell shell,
string[] args,
string argStr,
CancellationToken cancel)
{
var host = (ClientConsoleHost)shell.ConsoleHost;
return await host.DoServerCompletions(args.ToList(), cancel);
return await host.DoServerCompletions(args.ToList(), argStr[">".Length..], cancel);
}
}
}

View File

@@ -22,13 +22,11 @@ namespace Robust.Client.Console.Commands
return;
}
var entity = EntityUid.Parse(args[0]);
var netEntity = NetEntity.Parse(args[0]);
var entity = _entityManager.GetEntity(netEntity);
var componentName = args[1];
var component = (Component) _componentFactory.GetComponent(componentName);
component.Owner = entity;
var component = _componentFactory.GetComponent(componentName);
_entityManager.AddComponent(entity, component);
}
}
@@ -49,7 +47,8 @@ namespace Robust.Client.Console.Commands
return;
}
var entityUid = EntityUid.Parse(args[0]);
var netEntity = NetEntity.Parse(args[0]);
var entityUid = _entityManager.GetEntity(netEntity);
var componentName = args[1];
var registration = _componentFactory.GetRegistration(componentName);

View File

@@ -78,14 +78,7 @@ namespace Robust.Client.Console.Commands
message.Append($"net ID: {registration.NetID}");
}
message.Append($", References:");
shell.WriteLine(message.ToString());
foreach (var type in registration.References)
{
shell.WriteLine($" {type}");
}
}
catch (UnknownComponentException)
{
@@ -191,6 +184,19 @@ namespace Robust.Client.Console.Commands
}
}
internal sealed class ShowRotationsCommand : LocalizedCommands
{
[Dependency] private readonly IEntitySystemManager _entitySystems = default!;
public override string Command => "showrot";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
var mgr = _entitySystems.GetEntitySystem<DebugDrawingSystem>();
mgr.DebugRotations = !mgr.DebugRotations;
}
}
internal sealed class ShowRayCommand : LocalizedCommands
{
[Dependency] private readonly IEntitySystemManager _entitySystems = default!;
@@ -250,7 +256,7 @@ namespace Robust.Client.Console.Commands
return;
}
var uid = EntityUid.Parse(args[0]);
var uid = EntityUid.Parse(args[0], "-1");
var entmgr = _entityManager;
if (!entmgr.EntityExists(uid))
{
@@ -283,6 +289,7 @@ namespace Robust.Client.Console.Commands
internal sealed class SnapGridGetCell : LocalizedCommands
{
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IMapManager _map = default!;
public override string Command => "sggcell";
@@ -297,7 +304,7 @@ namespace Robust.Client.Console.Commands
string indices = args[1];
if (!EntityUid.TryParse(args[0], out var gridUid))
if (!NetEntity.TryParse(args[0], out var gridNet))
{
shell.WriteError($"{args[0]} is not a valid entity UID.");
return;
@@ -309,7 +316,7 @@ namespace Robust.Client.Console.Commands
return;
}
if (_map.TryGetGrid(gridUid, out var grid))
if (_map.TryGetGrid(_entManager.GetEntity(gridNet), out var grid))
{
foreach (var entity in grid.GetAnchoredEntities(new Vector2i(
int.Parse(indices.Split(',')[0], CultureInfo.InvariantCulture),
@@ -417,6 +424,7 @@ namespace Robust.Client.Console.Commands
internal sealed class GridTileCount : LocalizedCommands
{
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IMapManager _map = default!;
public override string Command => "gridtc";
@@ -429,7 +437,8 @@ namespace Robust.Client.Console.Commands
return;
}
if (!EntityUid.TryParse(args[0], out var gridUid))
if (!NetEntity.TryParse(args[0], out var gridUidNet) ||
!_entManager.TryGetEntity(gridUidNet, out var gridUid))
{
shell.WriteLine($"{args[0]} is not a valid entity UID.");
return;
@@ -455,7 +464,7 @@ namespace Robust.Client.Console.Commands
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
using var writer = _res.UserData.OpenWriteText(new ResourcePath("/guidump.txt"));
using var writer = _res.UserData.OpenWriteText(new ResPath("/guidump.txt"));
foreach (var root in _ui.AllRoots)
{
@@ -608,6 +617,7 @@ namespace Robust.Client.Console.Commands
internal sealed class ChunkInfoCommand : LocalizedCommands
{
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IMapManager _map = default!;
[Dependency] private readonly IEyeManager _eye = default!;
[Dependency] private readonly IInputManager _input = default!;
@@ -616,18 +626,19 @@ namespace Robust.Client.Console.Commands
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
var mousePos = _eye.ScreenToMap(_input.MouseScreenPosition);
var mousePos = _eye.PixelToMap(_input.MouseScreenPosition);
if (!_map.TryFindGridAt(mousePos, out var grid))
if (!_map.TryFindGridAt(mousePos, out var gridUid, out var grid))
{
shell.WriteLine("No grid under your mouse cursor.");
return;
}
var chunkIndex = grid.LocalToChunkIndices(grid.MapToGrid(mousePos));
var chunk = grid.GetOrAddChunk(chunkIndex);
var mapSystem = _entManager.System<SharedMapSystem>();
var chunkIndex = mapSystem.LocalToChunkIndices(gridUid, grid, grid.MapToGrid(mousePos));
var chunk = mapSystem.GetOrAddChunk(gridUid, grid, chunkIndex);
shell.WriteLine($"worldBounds: {grid.CalcWorldAABB(chunk)} localBounds: {chunk.CachedBounds}");
shell.WriteLine($"worldBounds: {mapSystem.CalcWorldAABB(gridUid, grid, chunk)} localBounds: {chunk.CachedBounds}");
}
}
@@ -661,7 +672,7 @@ namespace Robust.Client.Console.Commands
? StringComparer.Ordinal
: StringComparer.OrdinalIgnoreCase;
var reversePathResolution = new ConcurrentDictionary<string, HashSet<ResourcePath>>(stringComparer);
var reversePathResolution = new ConcurrentDictionary<string, HashSet<ResPath>>(stringComparer);
var taskManager = _taskManager;
@@ -675,7 +686,7 @@ namespace Robust.Client.Console.Commands
throw new NotImplementedException();
}
reversePathResolution.GetOrAdd(fullPath, _ => new HashSet<ResourcePath>()).Add(path);
reversePathResolution.GetOrAdd(fullPath, _ => new HashSet<ResPath>()).Add(path);
var dir = Path.GetDirectoryName(fullPath)!;
var fileName = Path.GetFileName(fullPath);
@@ -689,7 +700,7 @@ namespace Robust.Client.Console.Commands
throw new NotImplementedException();
}
reversePathResolution.GetOrAdd(incFullPath, _ => new HashSet<ResourcePath>()).Add(path);
reversePathResolution.GetOrAdd(incFullPath, _ => new HashSet<ResPath>()).Add(path);
var incDir = Path.GetDirectoryName(incFullPath)!;
var incFileName = Path.GetFileName(incFullPath);

View File

@@ -43,6 +43,7 @@ public sealed class ProfileEntitySpawningCommand : IConsoleCommand
GC.Collect();
Span<EntityUid> ents = stackalloc EntityUid[amount];
var stopwatch = new Stopwatch();
stopwatch.Start();
@@ -50,12 +51,17 @@ public sealed class ProfileEntitySpawningCommand : IConsoleCommand
for (var i = 0; i < amount; i++)
{
_entities.SpawnEntity(prototype, MapCoordinates.Nullspace);
ents[i] = _entities.SpawnEntity(prototype, MapCoordinates.Nullspace);
}
MeasureProfiler.SaveData();
shell.WriteLine($"Client: Profiled spawning {amount} entities in {stopwatch.Elapsed.TotalMilliseconds:N3} ms");
foreach (var ent in ents)
{
_entities.DeleteEntity(ent);
}
}
}
#endif

View File

@@ -0,0 +1,280 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Timing;
namespace Robust.Client.Console.Commands;
internal sealed partial class UITestControl
{
private sealed class TabSpriteView : Control
{
private const string EntityId = "debugRotation4";
private readonly IEntityManager _entMan;
private readonly IGameTiming _timing;
private readonly BoxContainer _box;
private record Entry(EntityUid Uid, SpriteComponent Sprite, TransformComponent Transform,
SpriteView View, Action<Entry, float>? Update);
private List<Entry> _entries = new();
private float _degreesPerSecond = 45;
public TabSpriteView()
{
IoCManager.Resolve(ref _entMan, ref _timing);
SetValue(TabContainer.TabTitleProperty, nameof(SpriteView));
_box = new BoxContainer
{
Orientation = BoxContainer.LayoutOrientation.Vertical,
Margin = new Thickness(10),
};
AddChild(new ScrollContainer() { Children = { _box }});
var level = IoCManager.Resolve<IBaseClient>().RunLevel;
if (level != ClientRunLevel.InGame && level != ClientRunLevel.SinglePlayerGame)
{
_box.AddChild(new Label
{
Text = "You need to be in-game for this UI to work."
});
return;
}
_box.AddChild(new Label
{
Text = "This control contains a bunch of sprite views. They are grouped based on SpriteView properties.\n" +
"Each group has views with different rotation and sprite transformations applied.\n" +
"Except for the fixed-size no-stretch view, the sprites should never leave the boxes.\n"
});
_box.AddChild(new Label
{
Text = "=============================\n" +
"Default SpriteView. Ignore sprite offset and world rotation\n" +
"============================="
});
AddEntries();
_box.AddChild(new Label
{
Text = "============================\n" +
"No overrides (Show entity rotation & offset)\n" +
"============================="
});
foreach (var e in AddEntries())
{
e.View.SpriteOffset = true;
e.View.WorldRotation = null;
}
_box.AddChild(new Label
{
Text = "=============================\n" +
"No override + Transformed view\n" +
"============================="
});
foreach (var e in AddEntries())
{
e.View.Scale = new(1, 0.75f);
e.View.EyeRotation = Angle.FromDegrees(45);
e.View.SpriteOffset = true;
e.View.WorldRotation = null;
}
_box.AddChild(new Label
{
Text = "============================\n" +
"No override + Transform + Fixed Size + No Stretch (sprites can leave).\n" +
"============================"
});
foreach (var e in AddEntries())
{
e.View.SetSize = new(64, 64);
e.View.Stretch = SpriteView.StretchMode.None;
e.View.Scale = new(1, 0.75f);
e.View.EyeRotation = Angle.FromDegrees(45);
e.View.SpriteOffset = true;
e.View.WorldRotation = null;
}
_box.AddChild(new Label
{
Text = "============================\n" +
"No override + Transform + Fixed Size + Shrink to view\n" +
"============================"
});
foreach (var e in AddEntries())
{
e.View.SetSize = new(64, 64);
e.View.Stretch = SpriteView.StretchMode.Fit;
e.View.Scale = new(1, 0.75f);
e.View.EyeRotation = Angle.FromDegrees(45);
e.View.SpriteOffset = true;
e.View.WorldRotation = null;
}
_box.AddChild(new Label
{
Text = "============================\n" +
"No override + Transform + Fixed Size + Scale to fill view\n" +
"============================"
});
foreach (var e in AddEntries())
{
e.View.SetSize = new(300, 300);
e.View.Stretch = SpriteView.StretchMode.Fill;
e.View.Scale = new(1, 0.75f);
e.View.EyeRotation = Angle.FromDegrees(45);
e.View.SpriteOffset = true;
e.View.WorldRotation = null;
}
_box.AddChild(new Label
{
Text = "============================\n" +
"With override + Transform + Fixed Size + Scale to fill view\n" +
"============================"
});
foreach (var e in AddEntries())
{
e.View.SetSize = new(300, 300);
e.View.Stretch = SpriteView.StretchMode.Fill;
e.View.Scale = new(1, 0.75f);
e.View.EyeRotation = Angle.FromDegrees(45);
}
}
public void OnClosed()
{
foreach (var e in _entries)
{
_entMan.DeleteEntity(e.Uid);
}
}
private List<Entry> AddEntries()
{
var added = new List<Entry>();
var entry = AddEntry("Default", null);
added.Add(entry);
entry = AddEntry("Local Rotation", (e, time) =>
{
e.Transform.LocalRotation = Angle.FromDegrees(time * _degreesPerSecond);
e.View.InvalidateMeasure();
});
added.Add(entry);
entry = AddEntry("Local Rotation (NoRot)", (e, time) =>
{
e.Transform.LocalRotation = Angle.FromDegrees(time * _degreesPerSecond);
e.View.InvalidateMeasure();
});
entry.Sprite.NoRotation = true;
added.Add(entry);
entry = AddEntry("Offset", (e, time) =>
{
e.Sprite.Offset = new Vector2(MathF.Sin((float) Angle.FromDegrees(time * _degreesPerSecond)), 0);
e.View.InvalidateMeasure();
});
added.Add(entry);
entry = AddEntry("Scaled", (e, time) =>
{
var theta = (float) Angle.FromDegrees(_degreesPerSecond * time).Theta;
e.Sprite.Scale = Vector2.One + new Vector2(0.5f * MathF.Sin(theta), 0.5f * MathF.Cos(theta));
e.View.InvalidateMeasure();
});
added.Add(entry);
entry = AddEntry("Sprite Rotation", (e, time) =>
{
e.Sprite.Rotation = Angle.FromDegrees(time * _degreesPerSecond);
});
added.Add(entry);
entry = AddEntry("Combination", (e, time) =>
{
var theta = (float) Angle.FromDegrees(_degreesPerSecond * time * 2).Theta;
e.Sprite.Scale = Vector2.One + new Vector2(0.5f * MathF.Sin(theta), 0.5f * MathF.Cos(theta));
e.Sprite.Offset = new(MathF.Sin((float) Angle.FromDegrees(time * _degreesPerSecond)), 0);
e.Sprite.Rotation = Angle.FromDegrees(0.5 * time * _degreesPerSecond);
e.Transform.LocalRotation = Angle.FromDegrees(0.25 * time * _degreesPerSecond);
e.View.InvalidateMeasure();
});
added.Add(entry);
return added;
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
var time = (float) _timing.CurTime.TotalSeconds;
foreach (var entry in _entries)
{
entry.Update?.Invoke(entry, time);
}
}
private Entry AddEntry(string text, Action<Entry, float>? onUpdate)
{
var label = new Label
{
MinWidth = 200,
Text = text,
VerticalAlignment = VAlignment.Center
};
var ent = _entMan.SpawnEntity(EntityId, MapCoordinates.Nullspace);
var view = new SpriteView();
view.SetEntity(ent);
var viewBox = new PanelContainer()
{
VerticalAlignment = VAlignment.Center,
Children = { view },
PanelOverride = new StyleBoxFlat
{
BackgroundColor = Color.White,
BorderColor = Color.Black,
BorderThickness = new(4),
}
};
_box.AddChild(new BoxContainer
{
Orientation = BoxContainer.LayoutOrientation.Horizontal,
Margin = new Thickness(10),
MinHeight = 150,
Children = { label, viewBox},
Name = text,
});
var sprite = _entMan.GetComponent<SpriteComponent>(ent);
var xform = _entMan.GetComponent<TransformComponent>(ent);
var entry = new Entry(ent, sprite, xform, view, onUpdate);
_entries.Add(entry);
return entry;
}
}
}

View File

@@ -11,7 +11,7 @@ using Robust.Shared.Utility;
namespace Robust.Client.Console.Commands;
internal sealed class UITestControl : Control
internal sealed partial class UITestControl : Control
{
private const string Lipsum = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer sed interdum diam. Duis erat risus, tincidunt at pulvinar non, accumsan non dui. Morbi feugiat nisi in odio consectetur, ac suscipit nulla mollis. Nulla consequat neque sit amet neque venenatis feugiat. Proin placerat eget mauris sit amet tincidunt. Sed pulvinar purus sed ex varius, et lobortis risus efficitur. Integer blandit eu neque quis elementum. Vivamus lacinia sem non lacinia eleifend. Integer sit amet est ac risus tempus iaculis sed quis leo. Proin eu dui tincidunt orci ornare elementum. Curabitur molestie enim scelerisque, porttitor ipsum vitae, posuere libero. Donec finibus placerat accumsan. Nam et arcu lacus.
@@ -26,6 +26,7 @@ Suspendisse hendrerit blandit urna ut laoreet. Suspendisse ac elit at erat males
private readonly TabContainer _tabContainer;
private readonly TabSpriteView _sprite;
public UITestControl()
{
@@ -88,7 +89,7 @@ Suspendisse hendrerit blandit urna ut laoreet. Suspendisse ac elit at erat males
{
grid.AddChild(new Button
{
MinSize = (50, 50),
MinSize = new(50, 50),
Text = $"{x}, {y}"
});
}
@@ -150,6 +151,14 @@ Suspendisse hendrerit blandit urna ut laoreet. Suspendisse ac elit at erat males
_tabContainer.AddChild(TabTextEdit());
_tabContainer.AddChild(TabRichText());
_sprite = new TabSpriteView();
_tabContainer.AddChild(_sprite);
}
public void OnClosed()
{
_sprite.OnClosed();
}
private Control TabTextEdit()
@@ -216,6 +225,7 @@ Suspendisse hendrerit blandit urna ut laoreet. Suspendisse ac elit at erat males
Untitled4 = 5,
TextEdit = 6,
RichText = 7,
SpriteView = 8,
}
}
@@ -225,8 +235,10 @@ internal sealed class UITestCommand : LocalizedCommands
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
var window = new DefaultWindow { MinSize = (500, 400) };
window.Contents.AddChild(new UITestControl());
var window = new DefaultWindow { MinSize = new(800, 600) };
var control = new UITestControl();
window.OnClose += control.OnClosed;
window.Contents.AddChild(control);
window.OpenCentered();
}
@@ -267,7 +279,7 @@ internal sealed class UITest2Command : LocalizedCommands
var root = _uiMgr.CreateWindowRoot(window);
window.DisposeOnClose = true;
window.RequestClosed += _ => control.OnClosed();
root.AddChild(control);
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Immutable;
using System.Numerics;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Input;

View File

@@ -19,6 +19,6 @@ namespace Robust.Client.Console
void AddFormattedLine(FormattedMessage message);
Task<CompletionResult> GetCompletions(List<string> args, CancellationToken cancel);
Task<CompletionResult> GetCompletions(List<string> args, string argStr, CancellationToken cancel);
}
}

View File

@@ -109,7 +109,7 @@ namespace Robust.Client.Console
public void ReceiveCompletionResponse(MsgScriptCompletionResponse response)
{
Suggestions.SetSuggestions(response);
Suggestions.OpenAt((Position.X + Size.X, Position.Y), (Size.X / 2, Size.Y));
Suggestions.OpenAt(new(Position.X + Size.X, Position.Y), new(Size.X / 2, Size.Y));
}
}
}

View File

@@ -37,7 +37,7 @@ namespace Robust.Client.Console
var mainVBox = new BoxContainer
{
Orientation = LayoutOrientation.Vertical,
MinSize = (500, 300),
MinSize = new(500, 300),
Children =
{
(_watchesVBox = new BoxContainer
@@ -69,7 +69,7 @@ namespace Robust.Client.Console
Contents.AddChild(mainVBox);
SetSize = (300, 300);
SetSize = new(300, 300);
}
private void AddWatch()

View File

@@ -1,5 +1,7 @@
#if DEBUG
using System.Numerics;
using System.Text;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.UserInterface;
@@ -7,7 +9,6 @@ using Robust.Client.UserInterface.Controls;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
namespace Robust.Client.Debugging
@@ -18,6 +19,7 @@ namespace Robust.Client.Debugging
[Dependency] private readonly IInputManager _inputManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IUserInterfaceManager _userInterface = default!;
[Dependency] private readonly MapSystem _mapSystem = default!;
private Label? _label;
@@ -60,25 +62,25 @@ namespace Robust.Client.Debugging
}
var mouseSpot = _inputManager.MouseScreenPosition;
var spot = _eyeManager.ScreenToMap(mouseSpot);
var spot = _eyeManager.PixelToMap(mouseSpot);
if (!_mapManager.TryFindGridAt(spot, out var grid))
if (!_mapManager.TryFindGridAt(spot, out var gridUid, out var grid))
{
_label.Text = string.Empty;
_hovered = null;
return;
}
var tile = grid.GetTileRef(spot);
var tile = _mapSystem.GetTileRef(gridUid, grid, spot);
_label.Position = mouseSpot.Position + new Vector2(32, 0);
if (_hovered?.GridId == grid.Owner && _hovered?.Tile == tile) return;
if (_hovered?.GridId == gridUid && _hovered?.Tile == tile) return;
_hovered = (grid.Owner, tile);
_hovered = (gridUid, tile);
var text = new StringBuilder();
foreach (var ent in grid.GetAnchoredEntities(spot))
foreach (var ent in _mapSystem.GetAnchoredEntities(gridUid, grid, spot))
{
if (EntityManager.TryGetComponent<MetaDataComponent>(ent, out var meta))
{

View File

@@ -1,3 +1,4 @@
using System.Numerics;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.GameObjects;
@@ -12,11 +13,10 @@ namespace Robust.Client.Debugging
public sealed class DebugDrawingSystem : EntitySystem
{
[Dependency] private readonly IOverlayManager _overlayManager = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
private bool _debugPositions;
private bool _debugRotations;
/// <summary>
/// Toggles the visual overlay of the local origin for each entity on screen.
@@ -35,7 +35,7 @@ namespace Robust.Client.Debugging
if (value && !_overlayManager.HasOverlay<EntityPositionOverlay>())
{
_overlayManager.AddOverlay(new EntityPositionOverlay(_lookup, _eyeManager, _entityManager));
_overlayManager.AddOverlay(new EntityPositionOverlay(_lookup, EntityManager));
}
else
{
@@ -44,18 +44,42 @@ namespace Robust.Client.Debugging
}
}
/// <summary>
/// Toggles the visual overlay of the local rotation.
/// </summary>
public bool DebugRotations
{
get => _debugRotations;
set
{
if (value == DebugRotations)
{
return;
}
_debugRotations = value;
if (value && !_overlayManager.HasOverlay<EntityRotationOverlay>())
{
_overlayManager.AddOverlay(new EntityRotationOverlay(_lookup, EntityManager));
}
else
{
_overlayManager.RemoveOverlay<EntityRotationOverlay>();
}
}
}
private sealed class EntityPositionOverlay : Overlay
{
private readonly EntityLookupSystem _lookup;
private readonly IEyeManager _eyeManager;
private readonly IEntityManager _entityManager;
public override OverlaySpace Space => OverlaySpace.WorldSpace;
public EntityPositionOverlay(EntityLookupSystem lookup, IEyeManager eyeManager, IEntityManager entityManager)
public EntityPositionOverlay(EntityLookupSystem lookup, IEntityManager entityManager)
{
_lookup = lookup;
_eyeManager = eyeManager;
_entityManager = entityManager;
}
@@ -64,10 +88,9 @@ namespace Robust.Client.Debugging
const float stubLength = 0.25f;
var worldHandle = (DrawingHandleWorld) args.DrawingHandle;
var viewport = _eyeManager.GetWorldViewport();
var xformQuery = _entityManager.GetEntityQuery<TransformComponent>();
foreach (var entity in _lookup.GetEntitiesIntersecting(_eyeManager.CurrentMap, viewport))
foreach (var entity in _lookup.GetEntitiesIntersecting(args.MapId, args.WorldBounds))
{
var (center, worldRotation) = xformQuery.GetComponent(entity).GetWorldPositionRotation();
@@ -79,5 +102,35 @@ namespace Robust.Client.Debugging
}
}
}
private sealed class EntityRotationOverlay : Overlay
{
private readonly EntityLookupSystem _lookup;
private readonly IEntityManager _entityManager;
public override OverlaySpace Space => OverlaySpace.WorldSpace;
public EntityRotationOverlay(EntityLookupSystem lookup, IEntityManager entityManager)
{
_lookup = lookup;
_entityManager = entityManager;
}
protected internal override void Draw(in OverlayDrawArgs args)
{
const float stubLength = 0.25f;
var worldHandle = (DrawingHandleWorld) args.DrawingHandle;
var xformQuery = _entityManager.GetEntityQuery<TransformComponent>();
foreach (var entity in _lookup.GetEntitiesIntersecting(args.MapId, args.WorldBounds))
{
var (center, worldRotation) = xformQuery.GetComponent(entity).GetWorldPositionRotation();
var drawLine = worldRotation.RotateVec(-Vector2.UnitY);
worldHandle.DrawLine(center, center + drawLine * stubLength, Color.Red);
}
}
}
}
}

View File

@@ -46,7 +46,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.Player;
@@ -128,8 +128,8 @@ namespace Robust.Client.Debugging
CollisionManager.GetPointStates(ref state1, ref state2, oldManifold, manifold);
Span<Vector2> points = stackalloc Vector2[2];
var transformA = _physics.GetPhysicsTransform(fixtureA.Body.Owner);
var transformB = _physics.GetPhysicsTransform(fixtureB.Body.Owner);
var transformA = _physics.GetPhysicsTransform(contact.EntityA);
var transformB = _physics.GetPhysicsTransform(contact.EntityB);
contact.GetWorldManifold(transformA, transformB, out var normal, points);
ContactPoint cp = Points[PointCount];
@@ -206,6 +206,7 @@ namespace Robust.Client.Debugging
private readonly Font _font;
private HashSet<Joint> _drawnJoints = new();
private List<Entity<MapGridComponent>> _grids = new();
public PhysicsDebugOverlay(IEntityManager entityManager, IEyeManager eyeManager, IInputManager inputManager, IMapManager mapManager, IPlayerManager playerManager, IResourceCache cache, DebugPhysicsSystem system, EntityLookupSystem lookup, SharedPhysicsSystem physicsSystem)
{
@@ -217,7 +218,7 @@ namespace Robust.Client.Debugging
_debugPhysicsSystem = system;
_lookup = lookup;
_physicsSystem = physicsSystem;
_font = new VectorFont(cache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Regular.ttf"), 10);
_font = new VectorFont(cache.GetResource<FontResource>("/EngineFonts/NotoSans/NotoSans-Regular.ttf"), 10);
}
private void DrawWorld(DrawingHandleWorld worldHandle, OverlayDrawArgs args)
@@ -230,32 +231,33 @@ namespace Robust.Client.Debugging
{
foreach (var physBody in _physicsSystem.GetCollidingEntities(mapId, viewBounds))
{
if (_entityManager.HasComponent<MapGridComponent>(physBody.Owner)) continue;
if (_entityManager.HasComponent<MapGridComponent>(physBody)) continue;
var xform = _physicsSystem.GetPhysicsTransform(physBody.Owner);
var xform = _physicsSystem.GetPhysicsTransform(physBody);
var comp = physBody.Comp;
const float AlphaModifier = 0.2f;
foreach (var fixture in _entityManager.GetComponent<FixturesComponent>(physBody.Owner).Fixtures.Values)
foreach (var fixture in _entityManager.GetComponent<FixturesComponent>(physBody).Fixtures.Values)
{
// Invalid shape - Box2D doesn't check for IsSensor but we will for sanity.
if (physBody.BodyType == BodyType.Dynamic && fixture.Density == 0f && fixture.Hard)
if (comp.BodyType == BodyType.Dynamic && fixture.Density == 0f && fixture.Hard)
{
DrawShape(worldHandle, fixture, xform, Color.Red.WithAlpha(AlphaModifier));
}
else if (!physBody.CanCollide)
else if (!comp.CanCollide)
{
DrawShape(worldHandle, fixture, xform, new Color(0.5f, 0.5f, 0.3f).WithAlpha(AlphaModifier));
}
else if (physBody.BodyType == BodyType.Static)
else if (comp.BodyType == BodyType.Static)
{
DrawShape(worldHandle, fixture, xform, new Color(0.5f, 0.9f, 0.5f).WithAlpha(AlphaModifier));
}
else if ((physBody.BodyType & (BodyType.Kinematic | BodyType.KinematicController)) != 0x0)
else if ((comp.BodyType & (BodyType.Kinematic | BodyType.KinematicController)) != 0x0)
{
DrawShape(worldHandle, fixture, xform, new Color(0.5f, 0.5f, 0.9f).WithAlpha(AlphaModifier));
}
else if (!physBody.Awake)
else if (!comp.Awake)
{
DrawShape(worldHandle, fixture, xform, new Color(0.6f, 0.6f, 0.6f).WithAlpha(AlphaModifier));
}
@@ -274,15 +276,18 @@ namespace Robust.Client.Debugging
foreach (var physBody in _physicsSystem.GetCollidingEntities(mapId, viewBounds))
{
var color = Color.Purple.WithAlpha(Alpha);
var transform = _physicsSystem.GetPhysicsTransform(physBody.Owner);
worldHandle.DrawCircle(Transform.Mul(transform, physBody.LocalCenter), 0.2f, color);
var transform = _physicsSystem.GetPhysicsTransform(physBody);
worldHandle.DrawCircle(Transform.Mul(transform, physBody.Comp.LocalCenter), 0.2f, color);
}
foreach (var grid in _mapManager.FindGridsIntersecting(mapId, viewBounds))
_grids.Clear();
_mapManager.FindGridsIntersecting(mapId, viewBounds, ref _grids);
foreach (var grid in _grids)
{
var physBody = _entityManager.GetComponent<PhysicsComponent>(grid.Owner);
var physBody = _entityManager.GetComponent<PhysicsComponent>(grid);
var color = Color.Orange.WithAlpha(Alpha);
var transform = _physicsSystem.GetPhysicsTransform(grid.Owner);
var transform = _physicsSystem.GetPhysicsTransform(grid);
worldHandle.DrawCircle(Transform.Mul(transform, physBody.LocalCenter), 1f, color);
}
}
@@ -291,14 +296,14 @@ namespace Robust.Client.Debugging
{
foreach (var physBody in _physicsSystem.GetCollidingEntities(mapId, viewBounds))
{
if (_entityManager.HasComponent<MapGridComponent>(physBody.Owner)) continue;
if (_entityManager.HasComponent<MapGridComponent>(physBody)) continue;
var xform = _physicsSystem.GetPhysicsTransform(physBody.Owner);
var xform = _physicsSystem.GetPhysicsTransform(physBody);
const float AlphaModifier = 0.2f;
Box2? aabb = null;
foreach (var fixture in _entityManager.GetComponent<FixturesComponent>(physBody.Owner).Fixtures.Values)
foreach (var fixture in _entityManager.GetComponent<FixturesComponent>(physBody).Fixtures.Values)
{
for (var i = 0; i < fixture.Shape.ChildCount; i++)
{
@@ -317,10 +322,11 @@ namespace Robust.Client.Debugging
{
_drawnJoints.Clear();
foreach (var jointComponent in _entityManager.EntityQuery<JointComponent>(true))
var query = _entityManager.AllEntityQueryEnumerator<JointComponent>();
while (query.MoveNext(out var uid, out var jointComponent))
{
if (jointComponent.JointCount == 0 ||
!_entityManager.TryGetComponent(jointComponent.Owner, out TransformComponent? xf1) ||
!_entityManager.TryGetComponent(uid, out TransformComponent? xf1) ||
!viewAABB.Contains(xf1.WorldPosition)) continue;
foreach (var (_, joint) in jointComponent.Joints)
@@ -360,6 +366,9 @@ namespace Robust.Client.Debugging
_debugPhysicsSystem.PointCount = 0;
}
worldHandle.UseShader(null);
worldHandle.SetTransform(Matrix3.Identity);
}
private void DrawScreen(DrawingHandleScreen screenHandle, OverlayDrawArgs args)
@@ -369,28 +378,31 @@ namespace Robust.Client.Debugging
if ((_debugPhysicsSystem.Flags & PhysicsDebugFlags.ShapeInfo) != 0x0)
{
var hoverBodies = new List<PhysicsComponent>();
var bounds = Box2.UnitCentered.Translated(_eyeManager.ScreenToMap(mousePos.Position).Position);
var hoverBodies = new List<Entity<PhysicsComponent>>();
var bounds = Box2.UnitCentered.Translated(_eyeManager.PixelToMap(mousePos.Position).Position);
foreach (var physBody in _physicsSystem.GetCollidingEntities(mapId, bounds))
{
if (_entityManager.HasComponent<MapGridComponent>(physBody.Owner)) continue;
hoverBodies.Add(physBody);
var uid = physBody.Owner;
if (_entityManager.HasComponent<MapGridComponent>(uid)) continue;
hoverBodies.Add((uid, physBody));
}
var lineHeight = _font.GetLineHeight(1f);
var drawPos = mousePos.Position + new Vector2(20, 0) + new Vector2(0, -(hoverBodies.Count * 4 * lineHeight / 2f));
int row = 0;
foreach (var body in hoverBodies)
foreach (var bodyEnt in hoverBodies)
{
if (body != hoverBodies[0])
if (bodyEnt != hoverBodies[0])
{
screenHandle.DrawString(_font, drawPos + new Vector2(0, row * lineHeight), "------");
row++;
}
screenHandle.DrawString(_font, drawPos + new Vector2(0, row * lineHeight), $"Ent: {body.Owner}");
var body = bodyEnt.Comp;
screenHandle.DrawString(_font, drawPos + new Vector2(0, row * lineHeight), $"Ent: {bodyEnt.Owner}");
row++;
screenHandle.DrawString(_font, drawPos + new Vector2(0, row * lineHeight), $"Layer: {Convert.ToString(body.CollisionLayer, 2)}");
row++;
@@ -403,7 +415,7 @@ namespace Robust.Client.Debugging
if ((_debugPhysicsSystem.Flags & PhysicsDebugFlags.Distance) != 0x0)
{
var mapPos = _eyeManager.ScreenToMap(mousePos);
var mapPos = _eyeManager.PixelToMap(mousePos);
if (mapPos.MapId != args.MapId)
return;
@@ -429,6 +441,9 @@ namespace Robust.Client.Debugging
}
}
}
screenHandle.UseShader(null);
screenHandle.SetTransform(Matrix3.Identity);
}
protected internal override void Draw(in OverlayDrawArgs args)
@@ -450,11 +465,26 @@ namespace Robust.Client.Debugging
{
switch (fixture.Shape)
{
case ChainShape cShape:
{
var count = cShape.Count;
var vertices = cShape.Vertices;
var v1 = Transform.Mul(xform, vertices[0]);
for (var i = 1; i < count; ++i)
{
var v2 = Transform.Mul(xform, vertices[i]);
worldHandle.DrawLine(v1, v2, color);
v1 = v2;
}
}
break;
case PhysShapeCircle circle:
var center = Transform.Mul(xform, circle.Position);
worldHandle.DrawCircle(center, circle.Radius, color);
break;
case EdgeShape edge:
{
var v1 = Transform.Mul(xform, edge.Vertex1);
var v2 = Transform.Mul(xform, edge.Vertex2);
worldHandle.DrawLine(v1, v2, color);
@@ -464,10 +494,11 @@ namespace Robust.Client.Debugging
worldHandle.DrawCircle(v1, 0.1f, color);
worldHandle.DrawCircle(v2, 0.1f, color);
}
}
break;
case PolygonShape poly:
Span<Vector2> verts = stackalloc Vector2[poly.Vertices.Length];
Span<Vector2> verts = stackalloc Vector2[poly.VertexCount];
for (var i = 0; i < verts.Length; i++)
{

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.Debugging;

View File

@@ -27,7 +27,7 @@ internal partial class GameController
// Otherwise abuse could happen.
DebugTools.AssertNotNull(_mainLoop);
Logger.Info($"Attempting redial of {address}: {text ?? "no reason given"}");
_logger.Info($"Attempting redial of {address}: {text ?? "no reason given"}");
if (!_mainLoop!.Running)
{

View File

@@ -3,6 +3,7 @@ using System.IO;
using System.Reflection;
using System.Runtime.Loader;
using Robust.Client.WebViewHook;
using Robust.Shared.ContentPack;
using Robust.Shared.Log;
using Robust.Shared.Utility;
@@ -20,7 +21,7 @@ namespace Robust.Client
LoadRobustWebView(mode);
break;
default:
Logger.Error($"Unknown Robust module: {module}");
_logger.Error($"Unknown Robust module: {module}");
return;
}
}
@@ -28,7 +29,7 @@ namespace Robust.Client
private void LoadRobustWebView(GameController.DisplayMode mode)
{
Logger.Debug("Loading Robust.Client.WebView");
_logger.Debug("Loading Robust.Client.WebView");
var alc = CreateModuleLoadContext("Robust.Client.WebView");
var assembly = alc.LoadFromAssemblyName(new AssemblyName("Robust.Client.WebView"));
@@ -39,7 +40,7 @@ namespace Robust.Client
_webViewHook = (IWebViewManagerHook)Activator.CreateInstance(managerType)!;
_webViewHook.PreInitialize(_dependencyCollection, mode);
Logger.Debug("Done pre-initializing Robust.Client.WebView");
_logger.Debug("Done pre-initializing Robust.Client.WebView");
}
/// <summary>

View File

@@ -10,7 +10,7 @@ using Robust.Shared.Utility;
namespace Robust.Client
{
internal partial class GameController
internal partial class GameController : IPostInjectInit
{
private IGameLoop? _mainLoop;
@@ -20,6 +20,7 @@ namespace Robust.Client
private static bool _hasStarted;
private Thread? _gameThread;
private ISawmill _logger = default!;
public static void Main(string[] args)
{
@@ -73,7 +74,7 @@ namespace Robust.Client
{
if (!StartupSystemSplash(options, logHandlerFactory))
{
Logger.Fatal("Failed to start game controller!");
_logger.Fatal("Failed to start game controller!");
return;
}
@@ -96,7 +97,7 @@ namespace Robust.Client
if (_gameThread.IsAlive)
{
Logger.Debug("Window loop exited; waiting for game thread to exit");
_logger.Debug("Window loop exited; waiting for game thread to exit");
_gameThread.Join();
}
}
@@ -107,7 +108,7 @@ namespace Robust.Client
CleanupWindowThread();
Logger.Debug("Goodbye");
_logger.Debug("Goodbye");
_dependencyCollection.Clear();
}
@@ -125,7 +126,7 @@ namespace Robust.Client
{
if (!StartupContinue(mode))
{
Logger.Fatal("Failed to start game controller!");
_logger.Fatal("Failed to start game controller!");
return;
}
@@ -134,5 +135,10 @@ namespace Robust.Client
CleanupGameThread();
}
void IPostInjectInit.PostInject()
{
_logger = _logManager.GetSawmill("game");
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime;
using System.Threading.Tasks;
@@ -10,11 +11,13 @@ using Robust.Client.GameStates;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.Placement;
using Robust.Client.Replays.Loading;
using Robust.Client.Replays.Playback;
using Robust.Client.ResourceManagement;
using Robust.Client.State;
using Robust.Client.Upload;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.RichText;
using Robust.Client.UserInterface.Themes;
using Robust.Client.Utility;
using Robust.Client.ViewVariables;
using Robust.Client.WebViewHook;
@@ -30,10 +33,13 @@ using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Profiling;
using Robust.Shared.Prototypes;
using Robust.Shared.Reflection;
using Robust.Shared.Replays;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Threading;
using Robust.Shared.Timing;
using Robust.Shared.Upload;
using Robust.Shared.Utility;
using YamlDotNet.RepresentationModel;
@@ -75,6 +81,12 @@ namespace Robust.Client
[Dependency] private readonly IRuntimeLog _runtimeLog = default!;
[Dependency] private readonly ISerializationManager _serializationManager = default!;
[Dependency] private readonly MarkupTagManager _tagManager = default!;
[Dependency] private readonly IGamePrototypeLoadManager _protoLoadMan = default!;
[Dependency] private readonly NetworkResourceManager _netResMan = default!;
[Dependency] private readonly IReplayLoadManager _replayLoader = default!;
[Dependency] private readonly IReplayPlaybackManager _replayPlayback = default!;
[Dependency] private readonly IReplayRecordingManagerInternal _replayRecording = default!;
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
private IWebViewManagerHook? _webViewHook;
@@ -115,12 +127,8 @@ namespace Robust.Client
var disableSandbox = Environment.GetEnvironmentVariable("ROBUST_DISABLE_SANDBOX") == "1";
_modLoader.SetEnableSandboxing(!disableSandbox && Options.Sandboxing);
var assemblyPrefix = Options.ContentModulePrefix ?? _resourceManifest!.AssemblyPrefix ?? "Content.";
if (!_modLoader.TryLoadModulesFrom(Options.AssemblyDirectory, assemblyPrefix))
{
Logger.Fatal("Errors while loading content assemblies.");
if (!LoadModules())
return false;
}
foreach (var loadedModule in _modLoader.LoadedModules)
{
@@ -156,10 +164,9 @@ namespace Robust.Client
// before prototype load.
ProgramShared.FinishCheckBadFileExtensions(checkBadExtensions);
_reflectionManager.Initialize();
_prototypeManager.Initialize();
_prototypeManager.LoadDirectory(new ResourcePath("/EnginePrototypes/"));
_prototypeManager.LoadDirectory(Options.PrototypeDirectory);
_prototypeManager.ResolveResults();
_prototypeManager.LoadDefaultPrototypes();
_userInterfaceManager.Initialize();
_eyeManager.Initialize();
_entityManager.Initialize();
@@ -170,9 +177,14 @@ namespace Robust.Client
_scriptClient.Initialize();
_client.Initialize();
_discord.Initialize();
_modLoader.BroadcastRunLevel(ModRunLevel.PostInit);
_tagManager.Initialize();
_protoLoadMan.Initialize();
_netResMan.Initialize();
_replayLoader.Initialize();
_replayPlayback.Initialize();
_replayRecording.Initialize();
_userInterfaceManager.PostInitialize();
_modLoader.BroadcastRunLevel(ModRunLevel.PostInit);
if (_commandLineArgs?.Username != null)
{
@@ -190,7 +202,12 @@ namespace Robust.Client
// Setup main loop
if (_mainLoop == null)
{
_mainLoop = new GameLoop(_gameTiming, _runtimeLog, _prof)
_mainLoop = new GameLoop(
_gameTiming,
_runtimeLog,
_prof,
_logManager.GetSawmill("eng"),
GameLoopOptions.FromCVars(_configurationManager))
{
SleepMode = displayMode == DisplayMode.Headless ? SleepMode.Delay : SleepMode.None
};
@@ -242,60 +259,32 @@ namespace Robust.Client
return true;
}
private ResourceManifestData LoadResourceManifest()
private bool LoadModules()
{
// 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>(), null, null, null, null, true);
DebugTools.Assert(_resourceManifest != null);
var yamlStream = new YamlStream();
using (stream)
var assemblyPrefix = Options.ContentModulePrefix ?? _resourceManifest!.AssemblyPrefix ?? "Content.";
var assemblyDir = Options.AssemblyDirectory;
bool result;
if (_resourceManifest.ClientAssemblies is { } clientAssemblies)
{
using var streamReader = new StreamReader(stream, EncodingHelpers.UTF8);
yamlStream.Load(streamReader);
// We have client assemblies. Load only the assemblies listed in the content manifest.
var paths = clientAssemblies.Select(p => assemblyDir / $"{p}.dll");
result = _modLoader.TryLoadModules(paths);
}
else
{
result = _modLoader.TryLoadModulesFrom(assemblyDir, assemblyPrefix);
}
if (yamlStream.Documents.Count == 0)
return new ResourceManifestData(Array.Empty<string>(), null, null, null, null, true);
if (yamlStream.Documents.Count != 1 || yamlStream.Documents[0].RootNode is not YamlMappingNode mapping)
if (!result)
{
throw new InvalidOperationException(
"Expected a single YAML document with root mapping for /manifest.yml");
_logger.Fatal("Errors while loading content assemblies.");
return false;
}
var modules = Array.Empty<string>();
if (mapping.TryGetNode("modules", out var modulesMap))
{
var sequence = (YamlSequenceNode)modulesMap;
modules = new string[sequence.Children.Count];
for (var i = 0; i < modules.Length; i++)
{
modules[i] = sequence[i].AsString();
}
}
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();
bool autoConnect = true;
if (mapping.TryGetNode("autoConnect", out var autoConnectNode))
autoConnect = autoConnectNode.AsBool();
return new ResourceManifestData(modules, assemblyPrefix, defaultWindowTitle, windowIconSet, splashLogo, autoConnect);
return true;
}
internal bool StartupSystemSplash(
@@ -387,7 +376,7 @@ namespace Robust.Client
{
foreach (var (api, prefix) in mounts)
{
_resourceCache.MountLoaderApi(api, "", new ResourcePath(prefix));
_resourceCache.MountLoaderApi(api, "", new(prefix));
}
}
@@ -396,7 +385,7 @@ namespace Robust.Client
_modLoader.VerifierExtraLoadHandler = VerifierExtraLoadHandler;
}
_resourceManifest = LoadResourceManifest();
_resourceManifest = ResourceManifestData.LoadResourceManifest(_resourceCache);
{
// Handle GameControllerOptions implicit CVar overrides.
@@ -457,7 +446,7 @@ namespace Robust.Client
if (uri.Scheme != "udp")
{
Logger.Warning($"connect-address '{uri}' does not have URI scheme of udp://..");
_logger.Warning($"connect-address '{uri}' does not have URI scheme of udp://..");
}
LaunchState = new InitialLaunchState(
@@ -480,11 +469,11 @@ namespace Robust.Client
if (reason != null)
{
Logger.Info($"Shutting down! Reason: {reason}");
_logger.Info($"Shutting down! Reason: {reason}");
}
else
{
Logger.Info("Shutting down!");
_logger.Info("Shutting down!");
}
_mainLoop.Running = false;
@@ -506,6 +495,11 @@ namespace Robust.Client
{
_taskManager.ProcessPendingTasks(); // tasks like connect
}
using (_prof.Group("Content post engine"))
{
_modLoader.BroadcastUpdate(ModUpdateLevel.InputPostEngine, frameEventArgs);
}
}
private void Tick(FrameEventArgs frameEventArgs)
@@ -544,9 +538,9 @@ namespace Robust.Client
{
using (_prof.Group("Entity"))
{
if (ContentEntityTickUpdate != null)
if (TickUpdateOverride != null)
{
ContentEntityTickUpdate.Invoke(frameEventArgs);
TickUpdateOverride.Invoke(frameEventArgs);
}
else
{
@@ -638,7 +632,6 @@ namespace Robust.Client
logManager.GetSawmill("ogl.debug.other").Level = LogLevel.Warning;
logManager.GetSawmill("gdparse").Level = LogLevel.Error;
logManager.GetSawmill("discord").Level = LogLevel.Warning;
logManager.GetSawmill("net.predict").Level = LogLevel.Info;
logManager.GetSawmill("szr").Level = LogLevel.Info;
logManager.GetSawmill("loc").Level = LogLevel.Warning;
@@ -702,6 +695,8 @@ namespace Robust.Client
internal void CleanupGameThread()
{
_replayRecording.Shutdown();
_modLoader.Shutdown();
// CEF specifically makes a massive silent stink of it if we don't shut it down from the correct thread.
@@ -718,15 +713,6 @@ namespace Robust.Client
_clydeAudio.Shutdown();
}
private sealed record ResourceManifestData(
string[] Modules,
string? AssemblyPrefix,
string? DefaultWindowTitle,
string? WindowIconSet,
string? SplashLogo,
bool AutoConnect
);
public event Action<FrameEventArgs>? ContentEntityTickUpdate;
public event Action<FrameEventArgs>? TickUpdateOverride;
}
}

View File

@@ -51,22 +51,22 @@ namespace Robust.Client
/// <summary>
/// Directory to load all assemblies from.
/// </summary>
public ResourcePath AssemblyDirectory { get; init; } = new(@"/Assemblies/");
public ResPath AssemblyDirectory { get; init; } = new(@"/Assemblies/");
/// <summary>
/// Directory to load all prototypes from.
/// </summary>
public ResourcePath PrototypeDirectory { get; init; } = new(@"/Prototypes/");
public ResPath PrototypeDirectory { get; init; } = new(@"/Prototypes/");
/// <summary>
/// Directory resource path containing window icons to load.
/// </summary>
public ResourcePath? WindowIconSet { get; init; }
public ResPath? WindowIconSet { get; init; }
/// <summary>
/// Resource path for splash image to show when the game starts up.
/// </summary>
public ResourcePath? SplashLogo { get; init; }
public ResPath? SplashLogo { get; init; }
/// <summary>
/// Whether to disable mounting the "Resources/" folder on FULL_RELEASE.

View File

@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Utility;
namespace Robust.Client.GameObjects;
public sealed partial class ClientEntityManager
{
protected override NetEntity GenerateNetEntity() => new(NextNetworkId++ | NetEntity.ClientEntity);
/// <summary>
/// If the client fails to resolve a NetEntity then during component state handling or the likes we
/// flag that comp state as requiring re-running if that NetEntity comes in.
/// </summary>
/// <returns></returns>
internal readonly Dictionary<NetEntity, List<(Type type, EntityUid Owner)>> PendingNetEntityStates = new();
public override bool IsClientSide(EntityUid uid, MetaDataComponent? metadata = null)
{
// Can't log false because some content code relies on invalid UIDs.
if (!MetaQuery.Resolve(uid, ref metadata, false))
return false;
return metadata.NetEntity.IsClientSide();
}
public override EntityUid EnsureEntity<T>(NetEntity nEntity, EntityUid callerEntity)
{
if (!nEntity.Valid)
{
return EntityUid.Invalid;
}
if (NetEntityLookup.TryGetValue(nEntity, out var entity))
{
return entity.Item1;
}
// Flag the callerEntity to have their state potentially re-run later.
var pending = PendingNetEntityStates.GetOrNew(nEntity);
pending.Add((typeof(T), callerEntity));
return entity.Item1;
}
public override EntityCoordinates EnsureCoordinates<T>(NetCoordinates netCoordinates, EntityUid callerEntity)
{
var entity = EnsureEntity<T>(netCoordinates.NetEntity, callerEntity);
return new EntityCoordinates(entity, netCoordinates.Position);
}
}

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Prometheus;
using Robust.Client.GameStates;
using Robust.Client.Player;
@@ -9,6 +8,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Network;
using Robust.Shared.Network.Messages;
using Robust.Shared.Replays;
using Robust.Shared.Utility;
namespace Robust.Client.GameObjects
@@ -16,15 +16,14 @@ namespace Robust.Client.GameObjects
/// <summary>
/// Manager for entities -- controls things like template loading and instantiation
/// </summary>
public sealed class ClientEntityManager : EntityManager, IClientEntityManagerInternal
public sealed partial class ClientEntityManager : EntityManager, IClientEntityManagerInternal
{
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IClientNetManager _networkManager = default!;
[Dependency] private readonly IClientGameTiming _gameTiming = default!;
[Dependency] private readonly IClientGameStateManager _stateMan = default!;
[Dependency] private readonly IBaseClient _client = default!;
protected override int NextEntityUid { get; set; } = EntityUid.ClientUid + 1;
[Dependency] private readonly IReplayRecordingManager _replayRecording = default!;
public override void Initialize()
{
@@ -36,13 +35,16 @@ namespace Robust.Client.GameObjects
public override void FlushEntities()
{
// Server doesn't network deletions on client shutdown so we need to
// manually clear these out or risk stale data getting used.
PendingNetEntityStates.Clear();
using var _ = _gameTiming.StartStateApplicationArea();
base.FlushEntities();
}
EntityUid IClientEntityManagerInternal.CreateEntity(string? prototypeName, EntityUid uid)
EntityUid IClientEntityManagerInternal.CreateEntity(string? prototypeName, out MetaDataComponent metadata)
{
return base.CreateEntity(prototypeName, uid);
return base.CreateEntity(prototypeName, out metadata, out _);
}
void IClientEntityManagerInternal.InitializeEntity(EntityUid entity, MetaDataComponent? meta)
@@ -63,20 +65,45 @@ namespace Robust.Client.GameObjects
base.DirtyEntity(uid, meta);
}
public override void QueueDeleteEntity(EntityUid? uid)
{
if (uid == null)
return;
if (IsClientSide(uid.Value))
{
base.QueueDeleteEntity(uid);
return;
}
if (ShuttingDown)
return;
// Client-side entity deletion is not supported and will cause errors.
if (_client.RunLevel == ClientRunLevel.Connected || _client.RunLevel == ClientRunLevel.InGame)
LogManager.RootSawmill.Error($"Predicting the queued deletion of a networked entity: {ToPrettyString(uid.Value)}. Trace: {Environment.StackTrace}");
}
/// <inheritdoc />
public override void Dirty(Component component, MetaDataComponent? meta = null)
public override void Dirty(EntityUid uid, IComponent component, MetaDataComponent? meta = null)
{
Dirty(new Entity<IComponent>(uid, component), meta);
}
/// <inheritdoc />
public override void Dirty<T>(Entity<T> ent, MetaDataComponent? meta = null)
{
// Client only dirties during prediction
if (_gameTiming.InPrediction)
base.Dirty(component, meta);
base.Dirty(ent, meta);
}
public override EntityStringRepresentation ToPrettyString(EntityUid uid)
public override EntityStringRepresentation ToPrettyString(EntityUid uid, MetaDataComponent? metaDataComponent = null)
{
if (_playerManager.LocalPlayer?.ControlledEntity == uid)
return base.ToPrettyString(uid) with { Session = _playerManager.LocalPlayer.Session };
else
return base.ToPrettyString(uid);
return base.ToPrettyString(uid);
}
public override void RaisePredictiveEvent<T>(T msg)
@@ -143,7 +170,7 @@ namespace Robust.Client.GameObjects
}
/// <inheritdoc />
public void SendSystemNetworkMessage(EntityEventArgs message, INetChannel channel)
public void SendSystemNetworkMessage(EntityEventArgs message, INetChannel? channel)
{
throw new NotSupportedException();
}
@@ -167,6 +194,12 @@ namespace Robust.Client.GameObjects
switch (message.Type)
{
case EntityMessageType.SystemMessage:
// TODO REPLAYS handle late messages.
// If a message was received late, it will be recorded late here.
// Maybe process the replay to prevent late messages when playing back?
_replayRecording.RecordReplayMessage(message.SystemMessage);
DispatchReceivedNetworkMsg(message.SystemMessage);
return;
}

View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using Robust.Client.Animations;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using static Robust.Client.Animations.AnimationPlaybackShared;
namespace Robust.Client.GameObjects
@@ -11,7 +9,7 @@ namespace Robust.Client.GameObjects
/// Plays back <see cref="Animation"/>s on entities.
/// </summary>
[RegisterComponent]
public sealed class AnimationPlayerComponent : Component
public sealed partial class AnimationPlayerComponent : Component
{
// TODO: Give this component a friend someday. Way too much content shit to change atm ._.
@@ -21,42 +19,5 @@ namespace Robust.Client.GameObjects
= new();
internal bool HasPlayingAnimation = false;
/// <summary>
/// Start playing an animation.
/// </summary>
/// <param name="animation">The animation to play.</param>
/// <param name="key">
/// The key for this animation play. This key can be used to stop playback short later.
/// </param>
[Obsolete("Use AnimationPlayerSystem.Play() instead")]
public void Play(Animation animation, string key)
{
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<AnimationPlayerSystem>().AddComponent(this);
var playback = new AnimationPlayback(animation);
PlayingAnimations.Add(key, playback);
}
[Obsolete("Use AnimationPlayerSystem.HasRunningAnimation() instead")]
public bool HasRunningAnimation(string key)
{
return PlayingAnimations.ContainsKey(key);
}
[Obsolete("Use AnimationPlayerSystem.Stop() instead")]
public void Stop(string key)
{
PlayingAnimations.Remove(key);
}
[Obsolete("Temporary method until the event is replaced with eventbus")]
internal void AnimationComplete(string key)
{
AnimationCompleted?.Invoke(key);
}
[Obsolete("Use AnimationCompletedEvent instead")]
public event Action<string>? AnimationCompleted;
}
}

View File

@@ -1,32 +0,0 @@
using System;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Robust.Client.GameObjects;
/// <summary>
/// Handles the visualization of data inside of an appearance component.
/// Implementations of this class are NOT bound to a specific entity, they are flyweighted across multiple.
/// </summary>
[ImplicitDataDefinitionForInheritors]
public abstract class AppearanceVisualizer
{
/// <summary>
/// Initializes an entity to be managed by this appearance controller.
/// DO NOT assume this is your only entity. Visualizers are shared.
/// </summary>
[Obsolete("Subscribe to your component being initialised instead.")]
public virtual void InitializeEntity(EntityUid entity)
{
}
/// <summary>
/// Called whenever appearance data for an entity changes.
/// Update its visuals here.
/// </summary>
/// <param name="component">The appearance component of the entity that might need updating.</param>
[Obsolete("Subscribe to AppearanceChangeEvent instead.")]
public virtual void OnChangeData(AppearanceComponent component)
{
}
}

View File

@@ -1,27 +0,0 @@
using System.Collections.Generic;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Robust.Client.GameObjects;
/// <summary>
/// This is the client instance of <see cref="AppearanceComponent"/>.
/// </summary>
[RegisterComponent]
[ComponentReference(typeof(AppearanceComponent)), Access(typeof(AppearanceSystem))]
public sealed class ClientAppearanceComponent : AppearanceComponent
{
[DataField("visuals")]
internal List<AppearanceVisualizer> Visualizers = new();
/// <summary>
/// If true, then this entity's visuals will get updated in the next frame update regardless of whether or not
/// this entity is currently inside of PVS range.
/// </summary>
/// <remarks>
/// This defaults to true, because it is possible for an entity to both be initialized and detached to null
/// during the same tick. This can happen because entity states & pvs-departure messages are sent & handled
/// separately. However, we want to ensure that each entity has an initial appearance update.
/// </remarks>
internal bool UpdateDetached = true;
}

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