Compare commits

...

98 Commits

Author SHA1 Message Date
metalgearsloth
fefcc7cba3 Physics (#1602)
* Physics worlds

* Paul's a good boy

* Build working

* Ingame and not lagging to hell

* Why didn't you commit ahhhhh

* Hard collisions working

* Solver parity

* Decent broadphase work done

* BroadPhase outline done

* BroadPhase working

* waiting for pvs

* Fix static PVS AABB

* Stop static bodies from awakening

* Optimise a bunch of stuff

* Even more broadphase stuff

* I'm fucking stupid

* Optimise fixture updates

* Collision solver start

* Building

* A is for Argumentative

* Fix contact caching island flags

* Circle shapes actually workeded

* Damping

* DS2 consumables only

* Slightly more stable

* Even slightlier more stablier

* VV your heart out

* Initial joint support

* 90% of joints I just wanted to push as I'd scream if I lost progress

* JOINT PURGATORY

* Joints barely functional lmao

* Okay these joints slightly more functional

* Remove station FrictionJoint

* Also that

* Some Box2D ports

* Cleanup mass

* Edge shape

* Active contacts

* Fix active contacts

* Optimise active contacts even more

* Boxes be stacking

* I would die for smug oh my fucking god

* In which everything is fixed

* Distance joints working LETS GO

* Remove frequency on distancejoint

* Fix some stuff and break joints

* Crashing fixed mehbeh

* ICollideSpecial and more resilience

* auto-clear

* showbb vera

* Slap that TODO in there

* Fix restartround crash

* Random fixes

* Fix fixture networking

* Add intersection method for broadphase

* Fix contacts

* Licenses done

* Optimisations

* Fix wall clips

* Config caching for island

* allocations optimisations

* Optimise casts

* Optimise events queue for physics

* Contact manager optimisations

* Optimise controllers

* Sloth joint or something idk

* Controller graph

* Remove content cvar

* Random cleanup

* Finally remove VirtualController

* Manifold structs again

* Optimise this absolute retardation

* Optimise

* fix license

* Cleanup physics interface

* AHHHHHHHHHHHHH

* Fix collisions again

* snivybus

* Fix potential nasty manifold bug

* Tests go snivy

Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
2021-03-01 03:09:36 +11:00
Paul
30df989e8d Merge branch 'serialization_v3_nodataclasses' of https://github.com/PaulRitter/RobustToolbox into master 2021-02-28 15:55:26 +01:00
Acruid
86bfea6bd4 ICommonSession Improvements + Player Filter (#1600)
* Removed IBaseSession, pushed all members down to ICommonSession.

* Pulled all members of client IPlayerSession into ICommonSession.
Marked client IPlayerSession as obsolete, use the base ICommonSession.

* Restricted setter access for properties in ICommonSession, only engine should be setting them.

* Fixed ping implementation on server.

* Moved AttachedEntityUid to ICommonSession.

* Added a shared IPlayerManager and pulled some common properties down to it.

* Added a shared player Filter class that holds a set of recipients in a networked call. Very useful for selecting recipients in a shared context.
2021-02-27 20:42:54 -08:00
Paul
d890f168c2 Spawner windows remember positions - engine commit 2021-02-27 12:27:46 +01:00
Paul
f888a810bf fixes that pesky warning 2021-02-27 11:58:51 +01:00
tmtmtl30
16249a4dde doubles default gain value (#1593) 2021-02-26 20:54:43 -08:00
Manel Navola
e33488ba55 Implemented erasing rectangular areas (#1419)
* Added support for erasing rectangular areas

* Apply suggestions from code review

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>

* Switched sending start coordinate + end coordinate to sending start coordinate + rect selection size for preventing different parented positions, general code improvements

* Rewritten certain code part so the checks pass

* Added unshaded shader to rect erasing

* Tweaked alpha of erasing rectangle for better visualizing

Co-authored-by: Manel Navola <ManelNavola@users.noreply.github.com>
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
2021-02-26 20:52:12 -08:00
RemieRichards
bfe6eeddb1 Localization Fixes. Stop double-localizing localizationID-sourced names, PROPER returning "True" or "False" instead of "true" or "false" 2021-02-27 01:04:04 +00:00
RemieRichards
7f540e741c Add myself to CODEOWNERS for fluent translations. 2021-02-25 20:30:57 +00:00
Pieter-Jan Briers
b7855f5af5 Fix reloading localizations. 2021-02-25 20:47:17 +01:00
Pieter-Jan Briers
91391e1205 Update NetSerializer submodule 2021-02-25 12:06:28 +01:00
Pieter-Jan Briers
d5199ec459 Update NuGet packages. 2021-02-25 12:06:05 +01:00
Vera Aguilera Puerto
e1e6f4fd10 ContainerHelpers EmptyContainer now has an argument to attach removed entities to grid or map 2021-02-25 11:43:09 +01:00
Leo
e5b6fccf67 Add a scroll speed property to ScrollContainer (#1590)
Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
2021-02-25 10:39:53 +00:00
RemberBL
95a912c329 Adds args.Handle(); into UI code for scrolling (#1595) 2021-02-25 11:08:19 +01:00
Pieter-Jan Briers
2b4833fc4e Allow content to read assembly versions in sandbox. 2021-02-24 12:18:44 +01:00
Pieter-Jan Briers
b814fc851a Fix more scrollbar DPI scaling bugs. 2021-02-24 12:18:29 +01:00
Pieter-Jan Briers
e87863203b Use DataFieldCached for AppearanceComponent.
What could go wrong?
2021-02-23 23:56:41 +01:00
Pieter-Jan Briers
33b66d9e18 Fix OpenCentered and OpenToLeft window methods. 2021-02-23 23:24:58 +01:00
Pieter-Jan Briers
fd406f7897 Selector-based VV windows have correct size.
Fixes #1594.
2021-02-23 23:10:58 +01:00
Pieter-Jan Briers
7a836d1018 Work around broken nullability.
Revert "Fix nullability errors"

This reverts commit a7f31f9ebf.

Revert "NotNullWhen()"

This reverts commit b332644d48.

Work around broken nullability.
2021-02-23 23:07:19 +01:00
Alex Evgrashin
393c15c44a Post shader will use real sprite bounding box (#1536)
Co-authored-by: Alex Evgrashin <evgrashin.adl@gmail.com>
Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
2021-02-23 22:54:48 +01:00
Pieter-Jan Briers
a7f31f9ebf Fix nullability errors 2021-02-23 22:53:38 +01:00
RemieRichards
b332644d48 NotNullWhen() 2021-02-23 21:40:33 +00:00
RemieRichards
510f7c0e7c Merge branch 'master' of https://github.com/space-wizards/RobustToolbox into localization_grammar 2021-02-23 21:33:06 +00:00
RemieRichards
fdd05e3d3a Fix GrammarComponent gender parsing, Add tests for GENDER() function (which covers custom types (Enum) and custom functions (GENDER)) 2021-02-23 21:31:13 +00:00
Pieter-Jan Briers
6d41958853 Fix nullability of TryIndex<T>. 2021-02-23 22:25:48 +01:00
Pieter-Jan Briers
cecc4dfcf2 Improve SharedTransformSystem:
Do not fire events for deleted entities.
Optimize to remove allocations & LINQ.
2021-02-23 22:05:49 +01:00
Pieter-Jan Briers
4ac40f2e90 Make norot on sprites default for the time being.
To band aid the pulling issues.
2021-02-23 21:32:00 +01:00
Pieter-Jan Briers
3e12d44173 Bool/enum/entity handling for localization parameters. 2021-02-23 20:59:21 +01:00
RemieRichards
a42b39bd84 Adds GENDER(), PROPER() and ATTRIB() localization functions, GrammarComponent. 2021-02-23 19:53:56 +00:00
DrSmugleaf
22affccf24 Add individual layer offset (#1583)
* Add individual layer offset

* Fix error message

* Bring back layer offsetting
2021-02-23 12:55:45 +01:00
Pieter-Jan Briers
028724c47b Localization improvements:
*Allow content to define localization functions.
* Add rldloc command to reload localizations.
* Doc comments
* Error handling
* Parallelize loading of localization files, since I can only assume we'll have a lot eventually.
* Type system stuff to allow content to pass custom data types into fluent.
* Code cleanup.
2021-02-23 11:35:54 +01:00
Pieter-Jan Briers
0114bff2fc Add IFormattable to sandbox whitelist. 2021-02-23 11:27:51 +01:00
Pieter-Jan Briers
4ddbd644eb Add helper method to set up logging inside unit tests. 2021-02-23 11:27:42 +01:00
Pieter-Jan Briers
f0366531ef Inject the csi directly into my master. 2021-02-23 01:39:33 +01:00
Pieter-Jan Briers
6bd5814f4a Automatically fetch names and descs from loc. 2021-02-22 11:11:11 +01:00
Pieter-Jan Briers
78c132fdab Mute loc warnings for the time being. 2021-02-22 08:57:30 +01:00
Remie Richards
460cf57d7c Fluent Localization (#1584) 2021-02-22 00:36:02 +01:00
Pieter-Jan Briers
a3190a8aca Improvements to SpriteComponent for new angle changes: (#1589)
1. Fixes CopyFrom with new rotation parameters.
2. Adds a couple APIs for ClickableComponent content side.
2021-02-22 00:30:16 +01:00
Pieter-Jan Briers
6921fb2fbf Make UserInterfaceManager not dispose root control on game shutdown.
No real reason to do this and it only risks breaking something.
2021-02-21 23:52:09 +01:00
Fortune117
9954d571de Fix for Crash Caused by the Entity Spawn Menu (#1588) 2021-02-21 20:16:01 +01:00
Pieter-Jan Briers
17fe000a1e Fix math tests due to angle/direction changes. 2021-02-21 20:06:39 +01:00
Pieter-Jan Briers
fba415e765 Bit of work to make Direction.South == Angle.Zero.
This makes Direction no longer follow a cartesian trig circle but oh well. Also helper methods to work with this.

Math tests currently fail, pushing this so Acruid can see about fixing SpriteComponent.
2021-02-21 19:47:42 +01:00
Pieter-Jan Briers
583b7ebf38 WPF layout (#1581) 2021-02-21 12:28:13 +01:00
Acruid
771a256925 Fixes bug with an exception being throw when trying to overwrite a deleted Component. (#1587)
Entity now uses constructor injection instead of property injection.
2021-02-20 23:30:09 -08:00
Acruid
ae79e89347 Added a shared PointLightComponent interface. (#1585)
* Added a shared PointLightComponent interface.

* Fix unit tests.
2021-02-20 16:06:34 -08:00
Acruid
6c7eeb95eb Marks Register and RegisterReference obsolete in IComponentFactory. (#1582) 2021-02-20 12:18:37 -08:00
Acruid
de0bd1887f Sprite Rendering Bugfixes (#1551)
* Added documentation to Clyde on the sprite rendering calls.

* Added a rotation debug entity.

* Non-directional RSIs and raw textures are now rotated properly.

* Directional RSIs and Sprite Smoothing work.

* Remove the Directional flag usages.

* Supports layers with different numbers of directions.

* Fixes window rendering.
2021-02-20 11:06:08 -08:00
metalgearsloth
eb3a815d48 Remove AiLogicProcessor (#1568)
Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
2021-02-19 21:52:32 -08:00
DrSmugleaf
e2a4dcdff1 Fix comparing by name and not ID for entity prototype updates (#1578) 2021-02-20 02:41:51 +01:00
DrSmugleaf
68b0d7bf2e Fix not clearing the queue after hot reload (#1576) 2021-02-20 01:43:56 +01:00
DrSmugleaf
a9b163992b Fix and add test for PrototypeManager LoadString (#1574) 2021-02-20 01:43:43 +01:00
DrSmugleaf
2409965cf8 Fix build (#1575) 2021-02-20 00:15:43 +01:00
DrSmugleaf
eada37378a Add YAML hot reloading (#1571)
* Implement hot reloading for entity prototypes

* Implement automatic prototype hot-reloading

* Merge fixes

* Add yaml hot reloading and a message to notify the client

* Add reloading only changed files, remove cooldown, add retries and remove IPrototype

* Remove reload command

* Make the client listen for reloads instead and only when focused

* Fix errors

* Only queue a reload when the queue has items in it

* Make fails after 10 retries log instead of throw if reloading

Co-authored-by: Jackson Lewis <inquisitivepenguin@protonmail.com>
2021-02-20 00:02:04 +01:00
DrSmugleaf
0f1da1ba2a Add window focused callback to Clyde (#1573) 2021-02-19 22:10:03 +01:00
Acruid
e0cdcd228e Fixed Timer Namespace in unit tests. 2021-02-18 20:35:34 -08:00
Acruid
fdb5e014b5 PauseManager moved to Shared (#1553)
* Moved IPauseManager from server to shared.

* Moved ITimerManager from Timers to Timing.

* Added missing IConsoleHost to server/client RegisterIoC. Tests work again.
2021-02-18 20:12:26 -08:00
DrSmugleaf
cefcad775b Make addcomp and rmcomp give better feedback and case insensitive (#1570)
* Make addcomp and rmcomp case insensitive

* Fix up names

* Make addcomp and rmcomp give better feedback

* Make addcomp and rmcomp less fail happy
2021-02-18 20:01:14 -08:00
Vera Aguilera Puerto
e40feac1f1 Adds VV autorefresh when right-clicking the refresh button. (#1558)
* Adds VV autorefresh when right-clicking the refresh button.

* cancel token on close

* button tooltip
2021-02-18 00:14:11 -08:00
DrSmugleaf
3ef4ac7452 Make component states dependant on the player getting them (#1569) 2021-02-17 23:48:17 -08:00
Pieter-Jan Briers
93bf1b09e7 Fix disconnecting while connecting causes you to be locked out of the server. 2021-02-17 23:22:11 +01:00
DrSmugleaf
a1e557e870 Add IPrototypeManager method to load a string (#1567) 2021-02-17 13:20:39 -08:00
Pieter-Jan Briers
864adb7445 Add DateTimeStyles to sandbox. 2021-02-17 11:52:36 +01:00
mirrorcult
9e3f3f0c1c vec2i serializer (#1563)
Co-authored-by: cyclowns <cyclowns@protonmail.ch>
2021-02-16 12:19:45 -08:00
DrSmugleaf
a40c4a435c Fix file not found exceptions when starting up the game with a debugger (#1562)
* Fix exceptions when starting up the game

* Remove try catches
2021-02-16 20:05:22 +01:00
DrSmugleaf
17182dd0e8 Engine PR for enabling nullability in Content.Client (#1565) 2021-02-16 20:05:06 +01:00
DrSmugleaf
d8b50044a2 Add (de)serialization for immutable lists (#1549) 2021-02-16 20:04:28 +01:00
Pieter-Jan Briers
4dc396e73d Fixes warning in TypePropertySerialization_Test.cs 2021-02-16 09:20:06 +01:00
Pieter-Jan Briers
6ae0b0e892 Fix [GenerateTypedNameReferences] with sealed types.
Fixes #1546
2021-02-16 09:19:57 +01:00
Pieter-Jan Briers
7162ca3456 Probably fix the bug where people get locked out of the server due to duplicate connction attempts. 2021-02-16 09:02:14 +01:00
Pieter-Jan Briers
1b44c1a1b8 Allow NotImplementedException in sandbox. 2021-02-15 17:57:38 +01:00
Clyybber
5b80b33e00 Change GetFileSystemInfos to EnumerateFileSystemInfos for iteration (#1561) 2021-02-15 16:26:16 +01:00
DrSmugleaf
f05c1b2395 Add Attribute generic constraint to IReflectionManager.FindTypesWithAttribute (#1548) 2021-02-14 02:14:00 +01:00
Pieter-Jan Briers
d9b2c73440 XamlUI improvements.
1. Add XAML namespaces https://spacestation14.io with Avalonia hacks.
2. Make markup extensions work with Avalonia hacks.
3. Add LocExtension for localized strings.
4. Add Vector2 parsing type converter to XAML compilation.
5. Make SS14Window better thanks to these improvements.
2021-02-14 02:09:37 +01:00
Pieter-Jan Briers
29a39f8e0a Adds LocExtension markup extension for XAML.
Does Loc.GetString().
2021-02-13 15:13:05 +01:00
Pieter-Jan Briers
2d72a2bdb5 Server timing improvements.
Add helpers.
Fix desynchronized NetTime.
2021-02-13 11:42:12 +01:00
Pieter-Jan Briers
91da635631 Fix Robust.Shared.Interfaces namespace in ScriptInstanceShared 2021-02-13 11:42:12 +01:00
chairbender
68ab3d504a Various fixes to support new chatbox (#1547)
* #272 no arrow, actually change id on channel changer

* #272 ability to apply style class to child

* #272 try methods for selecting items in OptionButton.cs

* #272 allow escaping right angle bracket in formatted message

* #272 ability to detect when local player is set / unset

* #272 make RemoveModal public since PushModal is as well, so modals can be removed on-demand if needed rather than relying on a click elsewhere

* #272 revert
2021-02-12 18:20:29 -08:00
Pieter-Jan Briers
5187040a64 Remove unsafe code from GrowableStack 2021-02-13 00:47:05 +01:00
DrSmugleaf
e0c63e7ce6 Add SerializedType attribute to specify the id used in !type tags (#1545)
* Add SerializedType attribute to serialize types without the !type tag

* Fix nulls in tests

* Fix null in tests maybe

* Return to type tags

* Fix imports
2021-02-11 13:50:55 -08:00
Acruid
0ba2272cab Remove all dependencies from LocalizationManager.
Remove IoCManager calls from EntityPrototype.
Add missing using statements preventing EXCEPTION_TOLERANCE from building.
2021-02-11 00:39:12 -08:00
Acruid
2183cd7ca1 Massive Namespace Cleanup (#1544)
* Removed the Interfaces folder.
* All objects inside the GameObjects subfolders are now in the GameObjects namespace.
* Added a Resharper DotSettings file to mark the GameObjects subfolders as not providing namespaces.
* Simplified Robust.client.Graphics namespace.
* Automated remove redundant using statements.
2021-02-10 23:27:19 -08:00
DrSmugleaf
cbf01f0aa5 Fix ComponentChangedSerialized test (#1543) 2021-02-09 21:24:28 +01:00
Pieter-Jan Briers
6973d43006 Network timing synchronization.
Lidgren NetTime.Now is now synchronized to IGameTiming.RealTime.

NetChannel is now a nested class of NetManager.

Add IGameTiming.ServerTime, INetChannel.RemoteTimeOffset, INetChannel.RemoteTime
2021-02-09 14:28:20 +01:00
Pieter-Jan Briers
c5a961d9a0 Even better: use argStr. 2021-02-09 14:28:20 +01:00
Acruid
b4f7d71ee7 Server console can forward commands to a client. 2021-02-09 04:16:15 -08:00
metalgearsloth
cd3684e575 Guard against client appearancecomp changes (#1540)
Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
2021-02-09 13:13:05 +01:00
Pieter-Jan Briers
317b8ce965 Fix sudo command mangling quotes. 2021-02-09 12:29:23 +01:00
Pieter-Jan Briers
ff96140afa Fix messed up \n. 2021-02-09 03:17:27 +01:00
Pieter-Jan Briers
bade95f6b7 Fix unit tests 2021-02-09 02:37:27 +01:00
Pieter-Jan Briers
69daaca399 Remove CVar.SECURE and replace auth CVars with env variables. 2021-02-09 01:50:42 +01:00
DrSmugleaf
5af7e60043 Add KeyValuePair YAML serialization (#1538) 2021-02-08 21:49:08 +01:00
DrSmugleaf
ab823dcd12 Add component registration lookup with case insensitive names (#1535) 2021-02-08 18:07:23 +01:00
Paul Ritter
b3976eb8d7 Analyzer Bongaloo 2: The Return (#1512)
Co-authored-by: Paul <ritter.paul1+git@googlemail.com>
2021-02-08 18:05:27 +01:00
Pieter-Jan Briers
91759cdd3c Harder DynamicTree against NaN.
B2DynamicTree<T> has asserts, DynamicTree<T> handles them gracefully.

NaNs in DynamicTree were causing the internal state to corrupt resulting in the sprite flickering issues.

Fixes https://github.com/space-wizards/space-station-14/issues/2896
2021-02-08 05:03:56 +01:00
Pieter-Jan Briers
b000c3178b FileLogHandler is now internal.
Sandboxing thing.
2021-02-07 23:07:57 +01:00
Vera Aguilera Puerto
63b3ecdd13 Fix SpawnRepeating timer extensions 2021-02-07 17:04:43 +01:00
833 changed files with 21733 additions and 8770 deletions

17
.github/CODEOWNERS vendored
View File

@@ -1,14 +1,7 @@
# Lines starting with '#' are comments.
# Each line is a file pattern followed by one or more owners.
# Last match in file takes precedence.
# These owners will be the default owners for everything in the repo.
# * @defunkt
* @Acruid @PJB3005 @Silvertorch5
# Be they Fluent translations or Freemarker templates, I know them both!
*.ftl @RemieRichards
# Order is important. The last matching pattern has the most precedence.
# So if a pull request only touches javascript files, only these owners
# will be requested to review.
# *.js @octocat @github/js
# You can also use email addresses if you prefer.
# docs/* docs@example.com
# Ping for all PRs
* @Acruid @PJB3005 @Silvertorch5

View File

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

View File

@@ -1,2 +1,3 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
<Import Project="Robust.Analyzers.targets" />
</Project>

View File

@@ -574,29 +574,22 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
- name: NGetText
- name: Fluent.Net
license: |
The MIT License (MIT)
blushingpenguin and Contributors
Copyright (c) 2012 Vitaly Zilnik
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
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
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
http://www.apache.org/licenses/LICENSE-2.0
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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.
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.
- name: NetSerializer
license: |

View File

@@ -0,0 +1,40 @@
- type: entity
id: debugRotation1
name: dbg_rotation1
components:
- type: Clickable
- type: InteractionOutline
- type: Sprite
netsync: false
visible: true
sprite: debugRotation.rsi
state: direction1
placement:
mode: AlignTileAny
- type: entity
id: debugRotation4
name: dbg_rotation4
components:
- type: Clickable
- type: InteractionOutline
- type: Sprite
netsync: false
visible: true
sprite: debugRotation.rsi
state: direction4
placement:
mode: AlignTileAny
- type: entity
id: debugRotationTex
name: dbg_rotationTex
components:
- type: Clickable
- type: InteractionOutline
- type: Sprite
netsync: false
visible: true
texture: debugRotation.rsi/direction1.png
placement:
mode: AlignTileAny

View File

@@ -0,0 +1,4 @@
- type: entity
name: blank entity
id: BlankEntity
abstract: true

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

View File

@@ -0,0 +1,17 @@
{
"version": 1,
"size": {
"x": 32,
"y": 32
},
"states": [{
"name": "direction1",
"directions": 1,
"delays": [[1.0]]
}, {
"name": "direction4",
"directions": 4,
"delays": [[1.0], [1.0], [1.0], [1.0]]
}
]
}

Binary file not shown.

View File

@@ -0,0 +1,92 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
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 Microsoft.CodeAnalysis.Diagnostics;
using Document = Microsoft.CodeAnalysis.Document;
namespace Robust.Analyzers
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class ExplicitInterfaceAnalyzer : DiagnosticAnalyzer
{
public readonly SyntaxKind[] ExcludedModifiers =
{
SyntaxKind.VirtualKeyword,
SyntaxKind.AbstractKeyword,
SyntaxKind.OverrideKeyword
};
public const string DiagnosticId = "RA0000";
private const string Title = "No explicit interface specified";
private const string MessageFormat = "No explicit interface specified";
private const string Description = "Make sure to specify the interface in your method-declaration.";
private const string Category = "Usage";
[SuppressMessage("ReSharper", "RS2008")] private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: Description);
private const string RequiresExplicitImplementationAttributeMetadataName =
"Robust.Shared.Analyzers.RequiresExplicitImplementationAttribute";
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.MethodDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.PropertyDeclaration);
}
private void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
ISymbol symbol;
Location location;
switch (context.Node)
{
//we already have a explicit interface specified, no need to check further
case MethodDeclarationSyntax methodDecl when methodDecl.ExplicitInterfaceSpecifier != null || methodDecl.Modifiers.Any(m => ExcludedModifiers.Contains(m.Kind())):
return;
case PropertyDeclarationSyntax propertyDecl when propertyDecl.ExplicitInterfaceSpecifier != null || propertyDecl.Modifiers.Any(m => ExcludedModifiers.Contains(m.Kind())):
return;
case MethodDeclarationSyntax methodDecl:
symbol = context.SemanticModel.GetDeclaredSymbol(methodDecl);
location = methodDecl.Identifier.GetLocation();
break;
case PropertyDeclarationSyntax propertyDecl:
symbol = context.SemanticModel.GetDeclaredSymbol(propertyDecl);
location = propertyDecl.Identifier.GetLocation();
break;
default:
return;
}
var attrSymbol = context.Compilation.GetTypeByMetadataName(RequiresExplicitImplementationAttributeMetadataName);
var isInterfaceMember = symbol?.ContainingType.AllInterfaces.Any(
i =>
i.GetMembers().Any(m => SymbolEqualityComparer.Default.Equals(symbol, symbol.ContainingType.FindImplementationForInterfaceMember(m)))
&& i.GetAttributes().Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, attrSymbol))
) ?? false;
if (isInterfaceMember)
{
//we do not have an explicit interface specified. bad!
var diagnostic = Diagnostic.Create(
Rule,
location);
context.ReportDiagnostic(diagnostic);
}
}
}
}

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="3.8.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,150 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
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 Microsoft.CodeAnalysis.Diagnostics;
namespace Robust.Analyzers
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class SerializableAnalyzer : DiagnosticAnalyzer
{
// Metadata of the analyzer
public const string DiagnosticId = "RA0001";
// You could use LocalizedString but it's a little more complicated for this sample
private const string Title = "Class not marked as (Net)Serializable";
private const string MessageFormat = "Class not marked as (Net)Serializable";
private const string Description = "The class should be marked as (Net)Serializable.";
private const string Category = "Usage";
private const string RequiresSerializableAttributeMetadataName = "Robust.Shared.Analyzers.RequiresSerializableAttribute";
private const string SerializableAttributeMetadataName = "System.SerializableAttribute";
private const string NetSerializableAttributeMetadataName = "Robust.Shared.Serialization.NetSerializableAttribute";
[SuppressMessage("ReSharper", "RS2008")] private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: Description);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ClassDeclaration);
}
private bool Marked(INamedTypeSymbol namedTypeSymbol, INamedTypeSymbol attrSymbol)
{
if (namedTypeSymbol == null) return false;
if (namedTypeSymbol.GetAttributes()
.Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, attrSymbol))) return true;
return Marked(namedTypeSymbol.BaseType, attrSymbol);
}
private void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var attrSymbol = context.Compilation.GetTypeByMetadataName(RequiresSerializableAttributeMetadataName);
var classDecl = (ClassDeclarationSyntax) context.Node;
var classSymbol = context.SemanticModel.GetDeclaredSymbol(classDecl);
if (classSymbol == null) return;
if (Marked(classSymbol, attrSymbol))
{
var attributes = classSymbol.GetAttributes();
var serAttr = context.Compilation.GetTypeByMetadataName(SerializableAttributeMetadataName);
var netSerAttr = context.Compilation.GetTypeByMetadataName(NetSerializableAttributeMetadataName);
var hasSerAttr = attributes.Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, serAttr));
var hasNetSerAttr =
attributes.Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, netSerAttr));
if (!hasSerAttr || !hasNetSerAttr)
{
var requiredAttributes = new List<string>();
if(!hasSerAttr) requiredAttributes.Add(SerializableAttributeMetadataName);
if(!hasNetSerAttr) requiredAttributes.Add(NetSerializableAttributeMetadataName);
context.ReportDiagnostic(
Diagnostic.Create(
Rule,
classDecl.Identifier.GetLocation(),
ImmutableDictionary.CreateRange(new Dictionary<string, string>()
{
{
"requiredAttributes", string.Join(",", requiredAttributes)
}
})));
}
}
}
}
[ExportCodeFixProvider(LanguageNames.CSharp)]
public class SerializableCodeFixProvider : CodeFixProvider
{
private const string Title = "Annotate class as (Net)Serializable.";
public override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
foreach (var diagnostic in context.Diagnostics)
{
var span = diagnostic.Location.SourceSpan;
var classDecl = root.FindToken(span.Start).Parent.AncestorsAndSelf().OfType<ClassDeclarationSyntax>().First();
if(!diagnostic.Properties.TryGetValue("requiredAttributes", out var requiredAttributes)) return;
context.RegisterCodeFix(
CodeAction.Create(
Title,
c => FixAsync(context.Document, classDecl, requiredAttributes, c),
Title),
diagnostic);
}
}
private async Task<Document> FixAsync(Document document, ClassDeclarationSyntax classDecl,
string requiredAttributes, CancellationToken cancellationToken)
{
var attributes = new List<AttributeSyntax>();
var namespaces = new List<string>();
foreach (var attribute in requiredAttributes.Split(','))
{
var tempSplit = attribute.Split('.');
namespaces.Add(string.Join(".",tempSplit.Take(tempSplit.Length-1)));
var @class = tempSplit.Last();
@class = @class.Substring(0, @class.Length - 9); //cut out "Attribute" at the end
attributes.Add(SyntaxFactory.Attribute(SyntaxFactory.ParseName(@class)));
}
var newClassDecl =
classDecl.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(attributes)));
var root = (CompilationUnitSyntax) await document.GetSyntaxRootAsync(cancellationToken);
root = root.ReplaceNode(classDecl, newClassDecl);
foreach (var ns in namespaces)
{
if(root.Usings.Any(u => u.Name.ToString() == ns)) continue;
root = root.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(ns)));
}
return document.WithSyntaxRoot(root);
}
public sealed override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(SerializableAnalyzer.DiagnosticId);
public override FixAllProvider GetFixAllProvider()
{
return WellKnownFixAllProviders.BatchFixer;
}
}
}

View File

@@ -0,0 +1,37 @@
using System.Linq;
using Pidgin;
using static Pidgin.Parser;
namespace Robust.Build.Tasks
{
public static class MathParsing
{
public static Parser<char, float> Single { get; } = Real.Select(c => (float) c);
public static Parser<char, float> Single1 { get; }
= Single.Between(SkipWhitespaces);
public static Parser<char, (float, float)> Single2 { get; }
= Single.Before(SkipWhitespaces).Repeat(2).Select(e =>
{
var arr = e.ToArray();
return (arr[0], arr[1]);
});
public static Parser<char, (float, float, float, float)> Single4 { get; }
= Single.Before(SkipWhitespaces).Repeat(4).Select(e =>
{
var arr = e.ToArray();
return (arr[0], arr[1], arr[2], arr[3]);
});
public static Parser<char, float[]> Thickness { get; }
= SkipWhitespaces.Then(
OneOf(
Try(Single4.Select(c => new[] {c.Item1, c.Item2, c.Item3, c.Item4})),
Try(Single2.Select(c => new[] {c.Item1, c.Item2})),
Try(Single1.Select(c => new[] {c}))
));
}
}

View File

@@ -0,0 +1,32 @@
using System.Reflection.Emit;
using XamlX.Ast;
using XamlX.Emit;
using XamlX.IL;
using XamlX.TypeSystem;
namespace Robust.Build.Tasks
{
internal class RXamlColorAstNode
: XamlAstNode, IXamlAstValueNode, IXamlAstILEmitableNode
{
private readonly IXamlMethod _method;
private readonly string _color;
public RXamlColorAstNode(IXamlLineInfo lineInfo, RXamlWellKnownTypes types, string color) : base(lineInfo)
{
_color = color;
Type = new XamlAstClrTypeReference(lineInfo, types.Color, false);
_method = types.ColorFromXaml;
}
public IXamlAstTypeReference Type { get; }
public XamlILNodeEmitResult Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
codeGen.Ldstr(_color);
codeGen.EmitCall(_method);
return XamlILNodeEmitResult.Type(0, Type.GetClrType());
}
}
}

View File

@@ -0,0 +1,93 @@
using System;
using System.Linq;
using System.Reflection.Emit;
using XamlX.Ast;
using XamlX.Emit;
using XamlX.IL;
using XamlX.TypeSystem;
namespace Robust.Build.Tasks
{
public abstract class RXamlVecLikeConstAstNode<T>
: XamlAstNode, IXamlAstValueNode, IXamlAstILEmitableNode
where T : unmanaged
{
private readonly IXamlConstructor _constructor;
protected readonly T[] Values;
public RXamlVecLikeConstAstNode(
IXamlLineInfo lineInfo,
IXamlType type, IXamlConstructor constructor,
IXamlType componentType, T[] values)
: base(lineInfo)
{
_constructor = constructor;
Values = values;
var @params = constructor.Parameters;
if (@params.Count != values.Length)
throw new ArgumentException("Invalid amount of parameters");
if (@params.Any(c => c != componentType))
throw new ArgumentException("Invalid constructor: not all parameters match component type");
Type = new XamlAstClrTypeReference(lineInfo, type, false);
}
public IXamlAstTypeReference Type { get; }
public virtual XamlILNodeEmitResult Emit(
XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context,
IXamlILEmitter codeGen)
{
codeGen.Newobj(_constructor);
return XamlILNodeEmitResult.Type(0, Type.GetClrType());
}
}
public sealed class RXamlSingleVecLikeConstAstNode : RXamlVecLikeConstAstNode<float>
{
public RXamlSingleVecLikeConstAstNode(
IXamlLineInfo lineInfo,
IXamlType type, IXamlConstructor constructor,
IXamlType componentType, float[] values)
: base(lineInfo, type, constructor, componentType, values)
{
}
public override XamlILNodeEmitResult Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context,
IXamlILEmitter codeGen)
{
foreach (var value in Values)
{
codeGen.Emit(OpCodes.Ldc_R4, value);
}
return base.Emit(context, codeGen);
}
}
public sealed class RXamlInt32VecLikeConstAstNode : RXamlVecLikeConstAstNode<int>
{
public RXamlInt32VecLikeConstAstNode(
IXamlLineInfo lineInfo,
IXamlType type, IXamlConstructor constructor,
IXamlType componentType, int[] values)
: base(lineInfo, type, constructor, componentType, values)
{
}
public override XamlILNodeEmitResult Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context,
IXamlILEmitter codeGen)
{
foreach (var value in Values)
{
codeGen.Emit(OpCodes.Ldc_I4, value);
}
return base.Emit(context, codeGen);
}
}
}

View File

@@ -0,0 +1,58 @@
using System.Linq;
using XamlX.Transform;
using XamlX.TypeSystem;
namespace Robust.Build.Tasks
{
class RXamlWellKnownTypes
{
public XamlTypeWellKnownTypes XamlIlTypes { get; }
public IXamlType Single { get; }
public IXamlType Int32 { get; }
public IXamlType Vector2 { get; }
public IXamlConstructor Vector2ConstructorFull { get; }
public IXamlType Vector2i { get; }
public IXamlConstructor Vector2iConstructorFull { get; }
public IXamlType Thickness { get; }
public IXamlConstructor ThicknessConstructorFull { get; }
public IXamlType Color { get; }
public IXamlMethod ColorFromXaml { get; }
public RXamlWellKnownTypes(TransformerConfiguration cfg)
{
var ts = cfg.TypeSystem;
XamlIlTypes = cfg.WellKnownTypes;
Single = ts.GetType("System.Single");
Int32 = ts.GetType("System.Int32");
(Vector2, Vector2ConstructorFull) = GetNumericTypeInfo("Robust.Shared.Maths.Vector2", Single, 2);
(Vector2i, Vector2iConstructorFull) = GetNumericTypeInfo("Robust.Shared.Maths.Vector2i", Int32, 2);
(Thickness, ThicknessConstructorFull) = GetNumericTypeInfo("Robust.Shared.Maths.Thickness", Single, 4);
(IXamlType, IXamlConstructor) GetNumericTypeInfo(string name, IXamlType componentType, int componentCount)
{
var type = cfg.TypeSystem.GetType(name);
var ctor = type.GetConstructor(Enumerable.Repeat(componentType, componentCount).ToList());
return (type, ctor);
}
Color = cfg.TypeSystem.GetType("Robust.Shared.Maths.Color");
ColorFromXaml = Color.GetMethod(new FindMethodMethodSignature("FromXaml", Color, XamlIlTypes.String)
{
IsStatic = true
});
}
}
static class RXamlWellKnownTypesExtensions
{
public static RXamlWellKnownTypes GetRobustTypes(this AstTransformationContext ctx)
{
if (ctx.TryGetItem<RXamlWellKnownTypes>(out var rv))
return rv;
ctx.SetItem(rv = new RXamlWellKnownTypes(ctx.Configuration));
return rv;
}
}
}

View File

@@ -8,6 +8,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Build.Framework" Version="16.8.0" />
<PackageReference Include="Mono.Cecil" Version="0.11.3" />
<PackageReference Include="Pidgin" Version="2.5.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -6,6 +6,7 @@ using Microsoft.Build.Framework;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
using Pidgin;
using XamlX;
using XamlX.Ast;
using XamlX.Emit;
@@ -70,7 +71,7 @@ namespace Robust.Build.Tasks
{
XmlnsAttributes =
{
typeSystem.GetType("Robust.Client.UserInterface.XAML.XmlnsDefinitionAttribute"),
typeSystem.GetType("Avalonia.Metadata.XmlnsDefinitionAttribute"),
},
ContentAttributes =
@@ -98,7 +99,7 @@ namespace Robust.Build.Tasks
typeSystem,
typeSystem.TargetAssembly,
xamlLanguage,
XamlXmlnsMappings.Resolve(typeSystem, xamlLanguage));
XamlXmlnsMappings.Resolve(typeSystem, xamlLanguage), CustomValueConverter);
var contextDef = new TypeDefinition("CompiledRobustXaml", "XamlIlContext",
TypeAttributes.Class, asm.MainModule.TypeSystem.Object);
@@ -297,6 +298,112 @@ namespace Robust.Build.Tasks
return true;
}
private static bool CustomValueConverter(
AstTransformationContext context,
IXamlAstValueNode node,
IXamlType type,
out IXamlAstValueNode result)
{
if (!(node is XamlAstTextNode textNode))
{
result = null;
return false;
}
var text = textNode.Text;
var types = context.GetRobustTypes();
if (type.Equals(types.Vector2))
{
var foo = MathParsing.Single2.Parse(text);
if (!foo.Success)
throw new XamlLoadException($"Unable to parse \"{text}\" as a Vector2", node);
var (x, y) = foo.Value;
result = new RXamlSingleVecLikeConstAstNode(
node,
types.Vector2, types.Vector2ConstructorFull,
types.Single, new[] {x, y});
return true;
}
if (type.Equals(types.Thickness))
{
var foo = MathParsing.Thickness.Parse(text);
if (!foo.Success)
throw new XamlLoadException($"Unable to parse \"{text}\" as a Thickness", node);
var val = foo.Value;
float[] full;
if (val.Length == 1)
{
var u = val[0];
full = new[] {u, u, u, u};
}
else if (val.Length == 2)
{
var h = val[0];
var v = val[1];
full = new[] {h, v, h, v};
}
else // 4
{
full = val;
}
result = new RXamlSingleVecLikeConstAstNode(
node,
types.Thickness, types.ThicknessConstructorFull,
types.Single, full);
return true;
}
if (type.Equals(types.Thickness))
{
var foo = MathParsing.Thickness.Parse(text);
if (!foo.Success)
throw new XamlLoadException($"Unable to parse \"{text}\" as a Thickness", node);
var val = foo.Value;
float[] full;
if (val.Length == 1)
{
var u = val[0];
full = new[] {u, u, u, u};
}
else if (val.Length == 2)
{
var h = val[0];
var v = val[1];
full = new[] {h, v, h, v};
}
else // 4
{
full = val;
}
result = new RXamlSingleVecLikeConstAstNode(
node,
types.Thickness, types.ThicknessConstructorFull,
types.Single, full);
return true;
}
if (type.Equals(types.Color))
{
// TODO: Interpret these colors at XAML compile time instead of at runtime.
result = new RXamlColorAstNode(node, types, text);
return true;
}
result = null;
return false;
}
public const string ContextNameScopeFieldName = "RobustNameScope";
private static void EmitNameScopeField(XamlLanguageTypeMappings xamlLanguage, CecilTypeSystem typeSystem, IXamlTypeBuilder<IXamlILEmitter> typeBuilder, IXamlILEmitter constructor)

View File

@@ -24,6 +24,7 @@ namespace Robust.Client.NameGenerator
{
private const string AttributeName = "Robust.Client.AutoGenerated.GenerateTypedNameReferencesAttribute";
private const string AttributeFile = "GenerateTypedNameReferencesAttribute";
private const string AttributeCode = @"// <auto-generated />
using System;
namespace Robust.Client.AutoGenerated
@@ -54,8 +55,8 @@ namespace Robust.Client.AutoGenerated
{
var clrtype = objectNode.Type.GetClrType();
var isControl = IsControl(clrtype);
//clrtype.Interfaces.Any(i =>
//i.IsInterface && i.FullName == "Robust.Client.UserInterface.IControl");
//clrtype.Interfaces.Any(i =>
//i.IsInterface && i.FullName == "Robust.Client.UserInterface.IControl");
if (!isControl)
return node;
@@ -80,9 +81,13 @@ namespace Robust.Client.AutoGenerated
return node;
}
public void Push(IXamlAstNode node) { }
public void Push(IXamlAstNode node)
{
}
public void Pop() { }
public void Pop()
{
}
}
private static string GenerateSourceCode(
@@ -97,16 +102,20 @@ namespace Robust.Client.AutoGenerated
var compiler =
new XamlILCompiler(
new TransformerConfiguration(typeSystem, typeSystem.Assemblies[0],
new XamlLanguageTypeMappings(typeSystem)),
new XamlLanguageTypeMappings(typeSystem)
{
XmlnsAttributes = {typeSystem.GetType("Avalonia.Metadata.XmlnsDefinitionAttribute")}
}),
new XamlLanguageEmitMappings<IXamlILEmitter, XamlILNodeEmitResult>(), false);
compiler.Transformers.Add(new TypeReferenceResolver());
compiler.Transform(parsed);
var initialRoot = (XamlAstObjectNode) parsed.Root;
var names = NameVisitor.GetNames(initialRoot);
var fieldAccess = classSymbol.IsSealed ? "private" : "protected";
//var names = NameVisitor.GetNames((XamlAstObjectNode)XDocumentXamlParser.Parse(xamlFile).Root);
var namedControls = names.Select(info => " " +
$"protected global::{info.type} {info.name} => " +
$"this.FindControl<global::{info.type}>(\"{info.name}\");");
$"{fieldAccess} global::{info.type} {info.name} => " +
$"this.FindControl<global::{info.type}>(\"{info.name}\");");
return $@"// <auto-generated />
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
@@ -124,7 +133,7 @@ namespace {nameSpace}
public void Execute(GeneratorExecutionContext context)
{
var comp = (CSharpCompilation) context.Compilation;
if(comp.GetTypeByMetadataName(AttributeName) == null)
if (comp.GetTypeByMetadataName(AttributeName) == null)
context.AddSource(AttributeFile, SourceText.From(AttributeCode, Encoding.UTF8));
if (!(context.SyntaxReceiver is NameReferenceSyntaxReceiver receiver))
{
@@ -132,7 +141,7 @@ namespace {nameSpace}
}
var symbols = UnpackAnnotatedTypes(context, comp, receiver);
if(symbols == null)
if (symbols == null)
return;
foreach (var typeSymbol in symbols)
@@ -168,7 +177,8 @@ namespace {nameSpace}
"Usage",
DiagnosticSeverity.Error,
true),
Location.Create(xamlFileName, new TextSpan(0,0), new LinePositionSpan(new LinePosition(0,0),new LinePosition(0,0)))));
Location.Create(xamlFileName, new TextSpan(0, 0),
new LinePositionSpan(new LinePosition(0, 0), new LinePosition(0, 0)))));
continue;
}
@@ -194,7 +204,8 @@ namespace {nameSpace}
}
}
private IReadOnlyList<INamedTypeSymbol> UnpackAnnotatedTypes(in GeneratorExecutionContext context, CSharpCompilation comp, NameReferenceSyntaxReceiver receiver)
private IReadOnlyList<INamedTypeSymbol> UnpackAnnotatedTypes(in GeneratorExecutionContext context,
CSharpCompilation comp, NameReferenceSyntaxReceiver receiver)
{
var options = (CSharpParseOptions) comp.SyntaxTrees[0].Options;
var compilation =

View File

@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using Robust.Client.GameObjects.Components.Animations;
using Robust.Client.GameObjects;
namespace Robust.Client.Animations
{

View File

@@ -1,7 +1,7 @@
using System;
using JetBrains.Annotations;
using Robust.Shared.Animations;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.GameObjects;
namespace Robust.Client.Animations
{

View File

@@ -1,8 +1,7 @@
using System;
using Robust.Client.Animations;
using Robust.Shared.Animations;
namespace Content.Client.Animations
namespace Robust.Client.Animations
{
public class AnimationTrackControlProperty : AnimationTrackProperty
{

View File

@@ -1,11 +1,8 @@
using System;
using System.Collections.Generic;
using Robust.Client.GameObjects.EntitySystems;
using Robust.Client.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Utility;
using Robust.Shared.GameObjects;
namespace Robust.Client.Animations
{

View File

@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Interfaces.GameObjects.Components;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Utility;
namespace Robust.Client.Animations

View File

@@ -1,6 +1,5 @@
using System;
using Robust.Client.Graphics;
using Robust.Client.Graphics.Clyde;
namespace Robust.Client.Audio
{

View File

@@ -4,16 +4,16 @@ using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using NFluidsynth;
using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Log;
using Robust.Shared.Interfaces.Physics;
using Robust.Shared.Interfaces.Resources;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.ContentPack;
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.Broadphase;
using Robust.Shared.Utility;
using Logger = Robust.Shared.Log.Logger;
@@ -72,6 +72,8 @@ namespace Robust.Client.Audio.Midi
[Dependency] private readonly IResourceManagerInternal _resourceManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
private SharedBroadPhaseSystem _broadPhaseSystem = default!;
public bool IsAvailable
{
get
@@ -155,6 +157,7 @@ namespace Robust.Client.Audio.Midi
_midiThread = new Thread(ThreadUpdate);
_midiThread.Start();
_broadPhaseSystem = EntitySystem.Get<SharedBroadPhaseSystem>();
FluidsynthInitialized = true;
}
@@ -299,7 +302,7 @@ namespace Robust.Client.Audio.Midi
var occlusion = 0f;
if (sourceRelative.Length > 0)
{
occlusion = IoCManager.Resolve<IPhysicsManager>().IntersectRayPenetration(
occlusion = _broadPhaseSystem.IntersectRayPenetration(
pos.MapId,
new CollisionRay(
pos.Position,

View File

@@ -1,11 +1,9 @@
using System;
using System.IO;
using System.Runtime.Intrinsics.X86;
using NFluidsynth;
using Robust.Client.Interfaces.Graphics;
using Robust.Client.Graphics;
using Robust.Shared.Asynchronous;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Log;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;

View File

@@ -1,20 +1,18 @@
using System;
using System.Net;
using Robust.Client.Interfaces;
using Robust.Client.Interfaces.Debugging;
using Robust.Client.Interfaces.GameObjects;
using Robust.Client.Interfaces.GameStates;
using Robust.Client.Interfaces.Utility;
using Robust.Client.Debugging;
using Robust.Client.GameObjects;
using Robust.Client.GameStates;
using Robust.Client.Player;
using Robust.Client.Utility;
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.Enums;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Robust.Client

View File

@@ -1,33 +1,16 @@
using System;
using System;
using Robust.Client.Audio.Midi;
using Robust.Client.Console;
using Robust.Client.Debugging;
using Robust.Client.GameObjects;
using Robust.Client.GameStates;
using Robust.Client.Graphics;
using Robust.Client.Graphics.ClientEye;
using Robust.Client.Graphics.Clyde;
using Robust.Client.Graphics.Lighting;
using Robust.Client.Graphics.Overlays;
using Robust.Client.Input;
using Robust.Client.Interfaces;
using Robust.Client.Interfaces.Debugging;
using Robust.Client.Interfaces.GameObjects;
using Robust.Client.Interfaces.GameStates;
using Robust.Client.Interfaces.Graphics;
using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Client.Interfaces.Graphics.Lighting;
using Robust.Client.Interfaces.Graphics.Overlays;
using Robust.Client.Interfaces.Input;
using Robust.Client.Interfaces.Map;
using Robust.Client.Interfaces.Placement;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Client.Interfaces.State;
using Robust.Client.Interfaces.UserInterface;
using Robust.Client.Interfaces.Utility;
using Robust.Client.Map;
using Robust.Client.Placement;
using Robust.Client.Player;
using Robust.Client.Prototypes;
using Robust.Client.Reflection;
using Robust.Client.ResourceManagement;
using Robust.Client.State;
@@ -35,15 +18,14 @@ using Robust.Client.UserInterface;
using Robust.Client.Utility;
using Robust.Client.ViewVariables;
using Robust.Shared;
using Robust.Shared.Console;
using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Interfaces.Reflection;
using Robust.Shared.Interfaces.Resources;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
using Robust.Shared.Reflection;
namespace Robust.Client
{
@@ -53,7 +35,7 @@ namespace Robust.Client
{
SharedIoC.RegisterIoC();
IoCManager.Register<IPrototypeManager, PrototypeManager>();
IoCManager.Register<IPrototypeManager, ClientPrototypeManager>();
IoCManager.Register<IEntityManager, ClientEntityManager>();
IoCManager.Register<IComponentFactory, ClientComponentFactory>();
IoCManager.Register<ITileDefinitionManager, ClydeTileDefinitionManager>();
@@ -79,9 +61,11 @@ namespace Robust.Client
IoCManager.Register<ILightManager, LightManager>();
IoCManager.Register<IDiscordRichPresence, DiscordRichPresence>();
IoCManager.Register<IClientConsoleHost, ClientConsoleHost>();
IoCManager.Register<IConsoleHost, ClientConsoleHost>();
IoCManager.Register<IFontManager, FontManager>();
IoCManager.Register<IFontManagerInternal, FontManager>();
IoCManager.Register<IMidiManager, MidiManager>();
IoCManager.Register<IAuthManager, AuthManager>();
switch (mode)
{
case GameController.DisplayMode.Headless:

View File

@@ -36,7 +36,7 @@ namespace Robust.Client.Console
Message = message;
}
}
/// <inheritdoc cref="IClientConsoleHost" />
internal class ClientConsoleHost : ConsoleHost, IClientConsoleHost
{
@@ -47,12 +47,20 @@ namespace Robust.Client.Console
{
NetManager.RegisterNetMessage<MsgConCmdReg>(MsgConCmdReg.NAME, HandleConCmdReg);
NetManager.RegisterNetMessage<MsgConCmdAck>(MsgConCmdAck.NAME, HandleConCmdAck);
NetManager.RegisterNetMessage<MsgConCmd>(MsgConCmd.NAME);
NetManager.RegisterNetMessage<MsgConCmd>(MsgConCmd.NAME, ProcessCommand);
Reset();
LogManager.RootSawmill.AddHandler(new DebugConsoleLogHandler(this));
}
private void ProcessCommand(MsgConCmd message)
{
string? text = message.Text;
LogManager.GetSawmill(SawmillName).Info($"SERVER:{text}");
ExecuteCommand(null, text);
}
/// <inheritdoc />
public void Reset()
{
@@ -104,14 +112,14 @@ namespace Robust.Client.Console
args.RemoveAt(0);
command1.Execute(new ConsoleShell(this, null), command, args.ToArray());
}
else if (!NetManager.IsConnected)
else
WriteError(null, "Unknown command: " + commandName);
}
/// <inheritdoc />
public override void RemoteExecuteCommand(ICommonSession? session, string command)
{
if (!NetManager.IsConnected)
if (!NetManager.IsConnected) // we don't care about session on client
return;
var msg = NetManager.CreateNetMessage<MsgConCmd>();

View File

@@ -1,8 +1,6 @@
using JetBrains.Annotations;
using Robust.Client.Player;
using Robust.Shared.Console;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
namespace Robust.Client.Console.Commands

View File

@@ -1,7 +1,7 @@
using JetBrains.Annotations;
using Robust.Client.Player;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
namespace Robust.Client.Console.Commands

View File

@@ -3,9 +3,7 @@ using System.Linq;
using JetBrains.Annotations;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
namespace Robust.Client.Console.Commands
{

View File

@@ -2,11 +2,7 @@
// Not some generic console command type.
// Couldn't think of a better name sorry.
using System;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.Random;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
namespace Robust.Client.Console.Commands
{

View File

@@ -6,20 +6,12 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using Robust.Client.Input;
using System.Threading;
using Robust.Client.Interfaces;
using Robust.Client.Interfaces.Debugging;
using Robust.Client.Interfaces.Graphics;
using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Client.Interfaces.Graphics.Lighting;
using Robust.Client.Interfaces.Input;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Client.Interfaces.State;
using Robust.Client.Interfaces.UserInterface;
using Robust.Client.Debugging;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Client.ResourceManagement.ResourceTypes;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
@@ -28,15 +20,11 @@ using Robust.Shared.Asynchronous;
using Robust.Shared.Console;
using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components.Transform;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Interfaces.Reflection;
using Robust.Shared.Interfaces.Resources;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Network;
using Robust.Shared.Reflection;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
@@ -493,6 +481,8 @@ namespace Robust.Client.Console.Commands
{
_writeNode(root, 0, writer);
}
shell.WriteLine("Saved guidump");
}
private static void _writeNode(Control control, int indents, TextWriter writer)
@@ -554,7 +544,7 @@ namespace Robust.Client.Console.Commands
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
var window = new SS14Window { CustomMinimumSize = (500, 400)};
var window = new SS14Window { MinSize = (500, 400)};
var tabContainer = new TabContainer();
window.Contents.AddChild(tabContainer);
var scroll = new ScrollContainer();
@@ -574,7 +564,7 @@ namespace Robust.Client.Console.Commands
optionButton.OnItemSelected += eventArgs => optionButton.SelectId(eventArgs.Id);
vBox.AddChild(optionButton);
var tree = new Tree { SizeFlagsVertical = Control.SizeFlags.FillExpand };
var tree = new Tree { VerticalExpand = true };
var root = tree.CreateItem();
root.Text = "Honk!";
var child = tree.CreateItem();
@@ -611,7 +601,7 @@ namespace Robust.Client.Console.Commands
{
grid.AddChild(new Button
{
CustomMinimumSize = (50, 50),
MinSize = (50, 50),
Text = $"{x}, {y}"
});
}
@@ -643,6 +633,29 @@ namespace Robust.Client.Console.Commands
}
});
tabContainer.AddChild(new HSplitContainer
{
Children =
{
new PanelContainer
{
PanelOverride = new StyleBoxFlat {BackgroundColor = Color.Red},
Children =
{
new Label{ Text = "FOOBARBAZ"},
}
},
new PanelContainer
{
PanelOverride = new StyleBoxFlat {BackgroundColor = Color.Blue},
Children =
{
new Label{ Text = "FOOBARBAZ"},
}
},
}
});
window.OpenCentered();
}
}

View File

@@ -1,7 +1,6 @@
using System;
using Robust.Shared.Console;
using Robust.Shared.ContentPack;
using Robust.Shared.Maths;
namespace Robust.Client.Console.Commands
{

View File

@@ -1,8 +1,7 @@
using System.Linq;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Network;
namespace Robust.Client.Console.Commands
{

View File

@@ -1,13 +1,13 @@
#if !FULL_RELEASE
using System;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Robust.Client.Utility;
using Robust.Shared;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.IoC;
using Robust.Shared.Network;
namespace Robust.Client.Console.Commands
{
@@ -39,9 +39,9 @@ namespace Robust.Client.Console.Commands
var token = login.Token.Token;
var userId = login.UserId;
var cfg = IoCManager.Resolve<IConfigurationManagerInternal>();
cfg.SetSecureCVar(CVars.AuthUserId, userId);
cfg.SetSecureCVar(CVars.AuthToken, token);
var cfg = IoCManager.Resolve<IAuthManager>();
cfg.Token = token;
cfg.UserId = new NetUserId(Guid.Parse(userId));
}
private sealed class LauncherConfig

View File

@@ -1,6 +1,5 @@
using System.Linq;
using System.Runtime.Loader;
using System.Text;
using JetBrains.Annotations;
using Robust.Shared.Console;

View File

@@ -1,5 +1,4 @@
using Robust.Shared.Log;
using Robust.Shared.Maths;
using System;
using Robust.Shared.Console;

View File

@@ -0,0 +1,41 @@
using Robust.Client.Debugging;
using Robust.Shared.Console;
using Robust.Shared.GameObjects;
namespace Robust.Client.Console.Commands
{
public sealed class PhysicsOverlayCommands : IConsoleCommand
{
public string Command => "physics";
public string Description => $"{Command} <contactnormals / contactpoints / shapes>";
public string Help => $"{Command} <overlay>";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 1)
{
shell.WriteLine($"Invalid number of args supplied");
return;
}
var system = EntitySystem.Get<DebugPhysicsSystem>();
switch (args[0])
{
case "contactnormals":
system.Flags ^= PhysicsDebugFlags.ContactNormals;
break;
case "contactpoints":
system.Flags ^= PhysicsDebugFlags.ContactPoints;
break;
case "shapes":
system.Flags ^= PhysicsDebugFlags.Shapes;
break;
default:
shell.WriteLine($"{args[0]} is not a recognised overlay");
return;
}
return;
}
}
}

View File

@@ -0,0 +1,20 @@
using Robust.Shared.Console;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
namespace Robust.Client.Console.Commands
{
internal sealed class ReloadLocalizationsCommand : IConsoleCommand
{
public string Command => "rldloc";
public string Description => "Reloads localization (client & server)";
public string Help => "Usage: rldloc";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
IoCManager.Resolve<ILocalizationManager>().ReloadLocalizations();
shell.RemoteExecuteCommand("sudo rldloc");
}
}
}

View File

@@ -1,7 +1,6 @@
using Robust.Shared.Console;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
namespace Robust.Client.Console.Commands
{

View File

@@ -1,5 +1,4 @@
using Robust.Shared.Console;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.IoC;
using Robust.Shared.Network;

View File

@@ -1,5 +1,5 @@
using JetBrains.Annotations;
using Robust.Client.Interfaces.Input;
using Robust.Client.Input;
using Robust.Shared.Console;
using Robust.Shared.IoC;

View File

@@ -0,0 +1,17 @@
using Robust.Client.GameObjects;
using Robust.Shared.Console;
using Robust.Shared.GameObjects;
namespace Robust.Client.Console.Commands
{
public class VelocitiesCommand : IConsoleCommand
{
public string Command => "showvelocities";
public string Description => "Displays your angular and linear velocities";
public string Help => $"{Command}";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
EntitySystem.Get<VelocityDebugSystem>().Enabled ^= true;
}
}
}

View File

@@ -1,6 +1,4 @@
using System;
namespace Robust.Client.Console
namespace Robust.Client.Console
{
public interface IClientConGroupController : IClientConGroupImplementation
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.IoC;
using Robust.Shared.Network;
using Robust.Shared.Network.Messages;
namespace Robust.Client.Console

View File

@@ -1,5 +1,7 @@
#if CLIENT_SCRIPTING
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
@@ -10,10 +12,10 @@ using Microsoft.CodeAnalysis.Scripting;
using Microsoft.CodeAnalysis.Text;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.ViewVariables;
using Robust.Shared.Interfaces.Reflection;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Reflection;
using Robust.Shared.Scripting;
using Robust.Shared.Utility;
@@ -36,6 +38,8 @@ namespace Robust.Client.Console
private readonly ScriptGlobals _globals;
private ScriptState? _state;
private (string[] imports, string code)? _autoImportRepeatBuffer;
public ScriptConsoleClient()
{
Title = Loc.GetString("Robust C# Interactive (CLIENT)");
@@ -54,38 +58,56 @@ namespace Robust.Client.Console
var code = InputBar.Text;
InputBar.Clear();
// Remove > or . at the end of the output panel.
OutputPanel.RemoveEntry(^1);
_inputBuffer.AppendLine(code);
_linesEntered += 1;
var tree = SyntaxFactory.ParseSyntaxTree(SourceText.From(_inputBuffer.ToString()), ScriptInstanceShared.ParseOptions);
if (!SyntaxFactory.IsCompleteSubmission(tree))
if (_autoImportRepeatBuffer.HasValue && code == "y")
{
if (_linesEntered == 1)
var (imports, repeatCode) = _autoImportRepeatBuffer.Value;
var sb = new StringBuilder();
foreach (var import in imports)
{
OutputPanel.AddText($"> {code}");
sb.AppendFormat("using {0};\n", import);
}
else
{
OutputPanel.AddText($". {code}");
}
OutputPanel.AddText(".");
return;
sb.Append(repeatCode);
code = sb.ToString();
}
code = _inputBuffer.ToString().Trim();
// Remove echo of partial submission from the output panel.
for (var i = 1; i < _linesEntered; i++)
else
{
// Remove > or . at the end of the output panel.
OutputPanel.RemoveEntry(^1);
}
_inputBuffer.Clear();
_linesEntered = 0;
_inputBuffer.AppendLine(code);
_linesEntered += 1;
var tree = SyntaxFactory.ParseSyntaxTree(SourceText.From(_inputBuffer.ToString()),
ScriptInstanceShared.ParseOptions);
if (!SyntaxFactory.IsCompleteSubmission(tree))
{
if (_linesEntered == 1)
{
OutputPanel.AddText($"> {code}");
}
else
{
OutputPanel.AddText($". {code}");
}
OutputPanel.AddText(".");
return;
}
code = _inputBuffer.ToString().Trim();
// Remove echo of partial submission from the output panel.
for (var i = 1; i < _linesEntered; i++)
{
OutputPanel.RemoveEntry(^1);
}
_inputBuffer.Clear();
_linesEntered = 0;
}
Script newScript;
@@ -135,6 +157,8 @@ namespace Robust.Client.Console
OutputPanel.AddMessage(msg);
OutputPanel.AddText(">");
PromptAutoImports(e.Diagnostics, code);
return;
}
@@ -155,6 +179,17 @@ namespace Robust.Client.Console
OutputPanel.AddText(">");
}
private void PromptAutoImports(IEnumerable<Diagnostic> diags, string code)
{
if (!ScriptInstanceShared.CalcAutoImports(_reflectionManager, diags, out var found))
return;
OutputPanel.AddText($"Auto-import {string.Join(", ", found)} (enter 'y')?");
_autoImportRepeatBuffer = (found.ToArray(), code);
}
private sealed class ScriptGlobalsImpl : ScriptGlobals
{
private readonly ScriptConsoleClient _owner;

View File

@@ -7,10 +7,10 @@ using Microsoft.CodeAnalysis.Scripting;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Interfaces.Reflection;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Reflection;
using Robust.Shared.Scripting;
using Robust.Shared.Timing;
@@ -20,8 +20,6 @@ namespace Robust.Client.Console
{
private readonly IReflectionManager _reflectionManager;
protected override Vector2? CustomSize => (300, 300);
private readonly VBoxContainer _watchesVBox;
private readonly LineEdit _addWatchEdit;
private readonly Button _addWatchButton;
@@ -37,12 +35,12 @@ namespace Robust.Client.Console
var mainVBox = new VBoxContainer
{
CustomMinimumSize = (500, 300),
MinSize = (500, 300),
Children =
{
(_watchesVBox = new VBoxContainer
{
SizeFlagsVertical = SizeFlags.FillExpand
VerticalExpand = true
}),
new HBoxContainer
{
@@ -50,7 +48,7 @@ namespace Robust.Client.Console
{
(_addWatchEdit = new HistoryLineEdit
{
SizeFlagsHorizontal = SizeFlags.FillExpand,
HorizontalExpand = true,
PlaceHolder = Loc.GetString("Add watch (C# interactive)")
}),
(_addWatchButton = new Button
@@ -66,6 +64,8 @@ namespace Robust.Client.Console
_addWatchEdit.OnTextEntered += _ => AddWatch();
Contents.AddChild(mainVBox);
SetSize = (300, 300);
}
private void AddWatch()
@@ -113,7 +113,7 @@ namespace Robust.Client.Console
{
(_outputLabel = new Label
{
SizeFlagsHorizontal = SizeFlags.FillExpand,
HorizontalExpand = true,
ClipText = true
}),
(delButton = new Button
@@ -176,7 +176,7 @@ namespace Robust.Client.Console
{
Text = message,
ClipText = true,
SizeFlagsHorizontal = SizeFlags.FillExpand
HorizontalExpand = true
},
(delButton = new Button {Text = Loc.GetString("Remove")})
}

View File

@@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.IO;
using Robust.Shared.Interfaces.Resources;
using Robust.Shared.ContentPack;
using Robust.Shared.IoC;
using Robust.Shared.Utility;
using YamlDotNet.RepresentationModel;

View File

@@ -1,21 +1,15 @@
using System;
using System.Collections.Generic;
using Robust.Client.Graphics;
using Robust.Client.Graphics.Drawing;
using Robust.Client.Graphics.Overlays;
using Robust.Client.Graphics.Shaders;
using Robust.Client.Interfaces.Debugging;
using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Client.Interfaces.Graphics.Overlays;
using Robust.Client.Interfaces.Input;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Client.Input;
using Robust.Client.ResourceManagement;
using Robust.Shared.GameObjects.Components;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Physics;
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Broadphase;
using Robust.Shared.Prototypes;
namespace Robust.Client.Debugging
@@ -145,7 +139,7 @@ namespace Robust.Client.Debugging
row++;
DrawString(screenHandle, _font, drawPos + new Vector2(0, row * lineHeight), $"Mask: {Convert.ToString(body.CollisionMask, 2)}");
row++;
DrawString(screenHandle, _font, drawPos + new Vector2(0, row * lineHeight), $"Enabled: {body.CanCollide}, Hard: {body.Hard}, Anchored: {((IPhysicsComponent)body).Anchored}");
DrawString(screenHandle, _font, drawPos + new Vector2(0, row * lineHeight), $"Enabled: {body.CanCollide}, Hard: {body.Hard}, Anchored: {(body).BodyType == BodyType.Static}");
row++;
}
@@ -167,19 +161,22 @@ namespace Robust.Client.Debugging
var mapId = _eyeManager.CurrentMap;
foreach (var physBody in _physicsManager.GetCollidingEntities(mapId, viewport))
foreach (var physBody in EntitySystem.Get<SharedBroadPhaseSystem>().GetCollidingEntities(mapId, viewport))
{
// all entities have a TransformComponent
var transform = physBody.Entity.Transform;
var worldBox = physBody.WorldAABB;
var worldBox = physBody.GetWorldAABB();
if (worldBox.IsEmpty()) continue;
var colorEdge = Color.Red.WithAlpha(0.33f);
var sleepThreshold = IoCManager.Resolve<IConfigurationManager>().GetCVar(CVars.TimeToSleep);
foreach (var shape in physBody.PhysicsShapes)
foreach (var fixture in physBody.Fixtures)
{
shape.DebugDraw(drawing, transform.WorldMatrix, in viewport, physBody.SleepAccumulator / (float) physBody.SleepThreshold);
var shape = fixture.Shape;
var sleepPercent = physBody.Awake ? physBody.SleepTime / sleepThreshold : 1.0f;
shape.DebugDraw(drawing, transform.WorldMatrix, in viewport, sleepPercent);
}
if (worldBox.Contains(mouseWorldPos))
@@ -242,6 +239,16 @@ namespace Robust.Client.Debugging
_handle.DrawCircle(origin, radius, color);
}
public override void DrawPolygonShape(Vector2[] vertices, in Color color)
{
_handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, vertices, color);
}
public override void DrawLine(Vector2 start, Vector2 end, in Color color)
{
_handle.DrawLine(start, end, color);
}
public override void SetTransform(in Matrix3 transform)
{
_handle.SetTransform(transform);

View File

@@ -1,15 +1,11 @@
using Robust.Client.Interfaces.Debugging;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.IoC;
using Robust.Shared.IoC;
using Robust.Shared.Network.Messages;
using System;
using System.Collections.Generic;
using Robust.Client.Graphics.Overlays;
using Robust.Client.Graphics.Drawing;
using Robust.Client.Graphics;
using Robust.Shared.Maths;
using Robust.Client.Interfaces.Graphics.Overlays;
using Robust.Shared.Timing;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.Network;
namespace Robust.Client.Debugging
{

View File

@@ -0,0 +1,149 @@
using System;
using Robust.Client.Graphics;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Physics.Collision;
using Robust.Shared.Physics.Dynamics;
using Robust.Shared.Physics.Dynamics.Contacts;
// TODO: Copy farseer licence here coz it's heavily inspired by it.
namespace Robust.Client.Debugging
{
internal sealed class DebugPhysicsSystem : EntitySystem
{
/*
* Used for debugging shapes, controllers, joints, contacts
*/
private const int MaxContactPoints = 2048;
internal int PointCount;
internal ContactPoint[] _points = new ContactPoint[MaxContactPoints];
public PhysicsDebugFlags Flags
{
get => _flags;
set
{
if (value == _flags) return;
if (_flags == PhysicsDebugFlags.None)
IoCManager.Resolve<IOverlayManager>().AddOverlay(new PhysicsDebugOverlay(this));
if (value == PhysicsDebugFlags.None)
IoCManager.Resolve<IOverlayManager>().RemoveOverlay(nameof(PhysicsDebugOverlay));
_flags = value;
}
}
private PhysicsDebugFlags _flags;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PreSolveMessage>(HandlePreSolve);
}
private void HandlePreSolve(PreSolveMessage message)
{
Contact contact = message.Contact;
Manifold oldManifold = message.OldManifold;
if ((Flags & PhysicsDebugFlags.ContactPoints) != 0)
{
Manifold manifold = contact.Manifold;
if (manifold.PointCount == 0)
return;
Fixture fixtureA = contact.FixtureA!;
PointState[] state1, state2;
CollisionManager.GetPointStates(out state1, out state2, oldManifold, manifold);
Vector2[] points;
Vector2 normal;
contact.GetWorldManifold(out normal, out points);
for (int i = 0; i < manifold.PointCount && PointCount < MaxContactPoints; ++i)
{
if (fixtureA == null)
_points[i] = new ContactPoint();
ContactPoint cp = _points[PointCount];
cp.Position = points[i];
cp.Normal = normal;
cp.State = state2[i];
_points[PointCount] = cp;
++PointCount;
}
}
}
internal struct ContactPoint
{
public Vector2 Normal;
public Vector2 Position;
public PointState State;
}
}
[Flags]
internal enum PhysicsDebugFlags : byte
{
None = 0,
ContactPoints = 1 << 0,
ContactNormals = 1 << 1,
Shapes = 1 << 2,
}
internal sealed class PhysicsDebugOverlay : Overlay
{
private DebugPhysicsSystem _physics = default!;
public override OverlaySpace Space => OverlaySpace.WorldSpace;
public PhysicsDebugOverlay(DebugPhysicsSystem system) : base(nameof(PhysicsDebugOverlay))
{
_physics = system;
}
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
{
if (_physics.Flags == PhysicsDebugFlags.None) return;
var worldHandle = (DrawingHandleWorld) handle;
if ((_physics.Flags & PhysicsDebugFlags.Shapes) != 0)
{
// Port DebugDrawing over.
}
if ((_physics.Flags & PhysicsDebugFlags.ContactPoints) != 0)
{
const float axisScale = 0.3f;
for (int i = 0; i < _physics.PointCount; ++i)
{
DebugPhysicsSystem.ContactPoint point = _physics._points[i];
if (point.State == PointState.Add)
worldHandle.DrawCircle(point.Position, 0.5f, new Color(255, 77, 243, 77));
else if (point.State == PointState.Persist)
worldHandle.DrawCircle(point.Position, 0.5f, new Color(255, 77, 77, 77));
if ((_physics.Flags & PhysicsDebugFlags.ContactNormals) != 0)
{
Vector2 p1 = point.Position;
Vector2 p2 = p1 + point.Normal * axisScale;
worldHandle.DrawLine(p1, p2, new Color(255, 102, 230, 102));
}
}
_physics.PointCount = 0;
}
}
}
}

View File

@@ -1,4 +1,4 @@
namespace Robust.Client.Interfaces.Debugging
namespace Robust.Client.Debugging
{
/// <summary>
/// A collection of visual debug overlays for the client game.

View File

@@ -1,11 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Robust.Shared.Timing;
namespace Robust.Client.Interfaces.Debugging
namespace Robust.Client.Debugging
{
public interface IDebugDrawingManager
{

View File

@@ -3,18 +3,15 @@ using System.IO;
using System.Net;
using System.Threading.Tasks;
using Robust.Client.Console;
using Robust.Client.Interfaces;
using Robust.Client.Interfaces.GameObjects;
using Robust.Client.Interfaces.GameStates;
using Robust.Client.Interfaces.Graphics;
using Robust.Client.Interfaces.Graphics.Overlays;
using Robust.Client.Interfaces.Input;
using Robust.Client.Interfaces.Placement;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Client.Interfaces.State;
using Robust.Client.Interfaces.UserInterface;
using Robust.Client.Interfaces.Utility;
using Robust.Client.GameObjects;
using Robust.Client.GameStates;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.Placement;
using Robust.Client.Player;
using Robust.Client.ResourceManagement;
using Robust.Client.State;
using Robust.Client.UserInterface;
using Robust.Client.Utility;
using Robust.Client.ViewVariables;
using Robust.LoaderApi;
@@ -22,15 +19,11 @@ using Robust.Shared;
using Robust.Shared.Asynchronous;
using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;
using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Log;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Interfaces.Serialization;
using Robust.Shared.Interfaces.Timers;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Timing;
@@ -67,6 +60,7 @@ namespace Robust.Client
[Dependency] private readonly IComponentManager _componentManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IRobustMappedStringSerializer _stringSerializer = default!;
[Dependency] private readonly IAuthManager _authManager = default!;
private CommandLineArgs? _commandLineArgs;
private bool _disableAssemblyLoadContext;
@@ -168,6 +162,7 @@ namespace Robust.Client
_serializer.Initialize();
_inputManager.Initialize();
_consoleHost.Initialize();
_prototypeManager.Initialize();
_prototypeManager.LoadDirectory(new ResourcePath(@"/Prototypes/"));
_prototypeManager.Resync();
_mapManager.Initialize();
@@ -186,6 +181,8 @@ namespace Robust.Client
_client.PlayerNameOverride = _commandLineArgs.Username;
}
_authManager.LoadFromEnv();
_clyde.Ready();
if ((_commandLineArgs?.Connect == true || _commandLineArgs?.Launcher == true)
@@ -321,6 +318,7 @@ namespace Robust.Client
logManager.GetSawmill("discord").Level = LogLevel.Warning;
logManager.GetSawmill("net.predict").Level = LogLevel.Info;
logManager.GetSawmill("szr").Level = LogLevel.Info;
logManager.GetSawmill("loc").Level = LogLevel.Error;
#if DEBUG_ONLY_FCE_INFO
#if DEBUG_ONLY_FCE_LOG

View File

@@ -1,4 +1,4 @@
using Robust.Client.Input;
using Robust.Client.Input;
namespace Robust.Client
{

View File

@@ -1,67 +1,9 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Robust.Client.Graphics.Clyde;
using Robust.Client.Console;
using Robust.Client.Debugging;
using Robust.Client.GameObjects;
using Robust.Client.GameStates;
using Robust.Client.Graphics;
using Robust.Client.Graphics.ClientEye;
using Robust.Client.Graphics.Lighting;
using Robust.Client.Graphics.Overlays;
using Robust.Client.Input;
using Robust.Client.Interfaces;
using Robust.Client.Interfaces.Debugging;
using Robust.Client.Interfaces.GameObjects;
using Robust.Client.Interfaces.GameStates;
using Robust.Client.Interfaces.Graphics;
using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Client.Interfaces.Graphics.Lighting;
using Robust.Client.Interfaces.Graphics.Overlays;
using Robust.Client.Interfaces.Input;
using Robust.Client.Interfaces.Map;
using Robust.Client.Interfaces.Placement;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Client.Interfaces.State;
using Robust.Client.Interfaces.UserInterface;
using Robust.Client.Interfaces.Utility;
using Robust.Client.Map;
using Robust.Client.Placement;
using Robust.Client.Player;
using Robust.Client.Reflection;
using Robust.Client.ResourceManagement;
using Robust.Client.State;
using Robust.Client.UserInterface;
using Robust.Client.Utility;
using Robust.Client.ViewVariables;
using Robust.Shared;
using Robust.Shared.Asynchronous;
using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;
using Robust.Shared.Exceptions;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Log;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Interfaces.Physics;
using Robust.Shared.Interfaces.Reflection;
using Robust.Shared.Interfaces.Resources;
using Robust.Shared.Interfaces.Serialization;
using Robust.Shared.Interfaces.Timers;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Network;
using Robust.Shared.Physics;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Timers;
using Robust.Shared.Timing;
using Robust.Shared.Reflection;
namespace Robust.Client
{

View File

@@ -1,4 +1,4 @@
using Robust.Client;
using Robust.Client;
using Robust.LoaderApi;
[assembly: LoaderEntryPoint(typeof(GameController.LoaderEntryPoint))]
@@ -11,7 +11,7 @@ namespace Robust.Client
{
public void Main(IMainArgs args)
{
GameController.Start(args.Args, contentStart: false, args);
Start(args.Args, contentStart: false, args);
}
}
}

View File

@@ -1,7 +1,5 @@
using System;
using Robust.Client.Interfaces;
using System;
using Robust.LoaderApi;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Timing;

View File

@@ -0,0 +1,3 @@
Everything in this folder and subfolders needs to be in:
Robust.Client.GameObjects

View File

@@ -1,18 +1,4 @@
using Robust.Client.GameObjects.Components;
using Robust.Client.GameObjects.Components.Animations;
using Robust.Client.GameObjects.Components.Containers;
using Robust.Client.GameObjects.Components.UserInterface;
using Robust.Client.Interfaces.GameObjects.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components;
using Robust.Shared.GameObjects.Components.Appearance;
using Robust.Shared.GameObjects.Components.Eye;
using Robust.Shared.GameObjects.Components.Map;
using Robust.Shared.GameObjects.Components.Renderable;
using Robust.Shared.GameObjects.Components.Timers;
using Robust.Shared.GameObjects.Components.Transform;
using Robust.Shared.GameObjects.Components.UserInterface;
using Robust.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.Physics;
namespace Robust.Client.GameObjects
@@ -37,9 +23,8 @@ namespace Robust.Client.GameObjects
Register<PhysicsComponent>();
RegisterReference<PhysicsComponent, IPhysBody>();
RegisterReference<PhysicsComponent, IPhysicsComponent>();
RegisterIgnore("KeyBindingInput");
Register<PointLightComponent>();
Register<InputComponent>();

View File

@@ -1,11 +1,8 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using Robust.Client.Interfaces.GameObjects;
using Robust.Shared.Exceptions;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;

View File

@@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using Robust.Client.Interfaces.GameStates;
using Robust.Client.GameStates;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Network;
using Robust.Shared.Network.Messages;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Robust.Client.GameObjects

View File

@@ -5,7 +5,7 @@ using Robust.Client.Animations;
using Robust.Shared.GameObjects;
using static Robust.Client.Animations.AnimationPlaybackShared;
namespace Robust.Client.GameObjects.Components.Animations
namespace Robust.Client.GameObjects
{
/// <summary>
/// Plays back <see cref="Animation"/>s on entities.

View File

@@ -1,13 +1,9 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Robust.Client.GameObjects.EntitySystems;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components.Appearance;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Reflection;
using Robust.Shared.IoC;
using Robust.Shared.Reflection;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
@@ -78,6 +74,8 @@ namespace Robust.Client.GameObjects
private void SetData(object key, object value)
{
if (data.TryGetValue(key, out var existing) && existing.Equals(value)) return;
data[key] = value;
MarkDirty();
@@ -85,10 +83,9 @@ namespace Robust.Client.GameObjects
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
{
if (curState == null)
if (curState is not AppearanceComponentState actualState)
return;
var actualState = (AppearanceComponentState) curState;
data = actualState.Data;
MarkDirty();
}
@@ -119,7 +116,7 @@ namespace Robust.Client.GameObjects
_didRegisterSerializer = true;
}
serializer.DataField(ref Visualizers, "visuals", new List<AppearanceVisualizer>());
serializer.DataFieldCached(ref Visualizers, "visuals", new List<AppearanceVisualizer>());
}
public override void Initialize()

View File

@@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Robust.Client.GameObjects.EntitySystems;
using Robust.Server.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.ViewVariables;
namespace Robust.Client.GameObjects.Components.Containers
namespace Robust.Client.GameObjects
{
public sealed partial class ContainerManagerComponent
{
@@ -65,14 +63,14 @@ namespace Robust.Client.GameObjects.Components.Containers
public void DoInsert(IEntity entity)
{
Entities.Add(entity);
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new EntInsertedIntoContainerMessage(entity, this));
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new UpdateContainerOcclusionMessage(entity));
}
public void DoRemove(IEntity entity)
{
Entities.Remove(entity);
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new EntRemovedFromContainerMessage(entity, this));
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new UpdateContainerOcclusionMessage(entity));
}

View File

@@ -2,14 +2,10 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Robust.Client.GameObjects.EntitySystems;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components.Containers;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.ViewVariables;
namespace Robust.Client.GameObjects.Components.Containers
namespace Robust.Client.GameObjects
{
public sealed partial class ContainerManagerComponent : SharedContainerManagerComponent
{

View File

@@ -1,8 +1,5 @@
using Robust.Client.Graphics.ClientEye;
using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Client.Graphics;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components.Eye;
using Robust.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;

View File

@@ -1,9 +1,9 @@
using Robust.Client.Graphics;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Client.ResourceManagement;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;

View File

@@ -1,12 +0,0 @@
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components;
namespace Robust.Client.GameObjects.Components
{
[RegisterComponent]
[ComponentReference(typeof(SharedIgnorePauseComponent))]
public sealed class IgnorePauseComponent : SharedIgnorePauseComponent
{
}
}

View File

@@ -1,10 +1,9 @@
using Robust.Client.GameObjects.EntitySystems;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Input;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
namespace Robust.Client.GameObjects.Components
namespace Robust.Client.GameObjects
{
/// <summary>
/// Defines data fields used in the <see cref="InputSystem"/>.

View File

@@ -1,7 +1,5 @@
using System;
using Robust.Client.GameObjects.EntitySystems;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components.Transform;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.ViewVariables;

View File

@@ -1,21 +1,22 @@
using Robust.Client.GameObjects.EntitySystems;
using System;
using Robust.Client.Graphics;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Client.ResourceManagement;
using Robust.Shared.Animations;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
using System;
namespace Robust.Client.GameObjects
{
public class PointLightComponent : Component
[RegisterComponent]
[ComponentReference(typeof(IPointLightComponent))]
public class PointLightComponent : Component, IPointLightComponent
{
[Dependency] private readonly IResourceCache _resourceCache = default!;
public override string Name => "PointLight";
public override uint? NetID => NetIDs.POINT_LIGHT;
@@ -68,6 +69,21 @@ namespace Robust.Client.GameObjects
set => _rotation = value;
}
/// <inheritdoc />
/// <summary>
/// The resource path to the mask texture the light will use.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public string? MaskPath
{
get => _maskPath;
set
{
_maskPath = value;
UpdateMask();
}
}
/// <summary>
/// Set a mask texture that will be applied to the light while rendering.
/// The mask's red channel will be linearly multiplied.p
@@ -120,7 +136,7 @@ namespace Robust.Client.GameObjects
private float _radius = 5;
private bool _visibleNested = true;
private bool _lightOnParent = false;
private bool _lightOnParent;
private Color _color = Color.White;
private Vector2 _offset;
private bool _enabled = true;
@@ -128,6 +144,7 @@ namespace Robust.Client.GameObjects
private Angle _rotation;
private float _energy;
private float _softness;
private string? _maskPath;
/// <summary>
/// Radius, in meters.
@@ -144,6 +161,20 @@ namespace Robust.Client.GameObjects
}
}
private void UpdateMask()
{
if (_maskPath is not null)
Mask = _resourceCache.GetResource<TextureResource>(_maskPath);
else
Mask = null;
}
public override void Initialize()
{
base.Initialize();
UpdateMask();
}
/// <inheritdoc />
public override void HandleMessage(ComponentMessage message, IComponent? component)
{
@@ -183,11 +214,7 @@ namespace Robust.Client.GameObjects
serializer.DataFieldCached(ref _softness, "softness", 1f);
serializer.DataFieldCached(ref _maskAutoRotate, "autoRot", false);
serializer.DataFieldCached(ref _visibleNested, "nestedvisible", true);
if (serializer.Reading && serializer.TryReadDataField<string>("mask", out var value))
{
Mask = IoCManager.Resolve<IResourceCache>().GetResource<TextureResource>(value);
}
serializer.DataFieldCached(ref _maskPath, "mask", null);
}
public override void OnRemove()

View File

@@ -1,9 +1,8 @@
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
namespace Robust.Client.Interfaces.GameObjects
namespace Robust.Client.GameObjects
{
public interface IRenderableComponent : IComponent
{

View File

@@ -1,14 +1,12 @@
using System;
using System;
using System.Collections.Generic;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Graphics.Shaders;
using Robust.Shared.Animations;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
namespace Robust.Client.Interfaces.GameObjects.Components
namespace Robust.Client.GameObjects
{
public interface ISpriteComponent : IComponent, IAnimationProperties
{
@@ -51,8 +49,26 @@ namespace Robust.Client.Interfaces.GameObjects.Components
/// Rotation transformations on individual layers still apply.
/// If false, all layers get locked to south and rotation is a transformation.
/// </summary>
[Obsolete("Use NoRotation and/or DirectionOverride")]
bool Directional { get; set; }
/// <summary>
/// All sprite rotation is locked, and will always be drawn upright on
/// the screen, regardless of world or view orientation.
/// </summary>
bool NoRotation {get; set; }
/// <summary>
/// Enables overriding the calculated directional RSI state for this sprite.
/// The state to use is defined in <see cref="DirectionOverride"/>.
/// </summary>
bool EnableDirectionOverride { get; set; }
/// <summary>
/// The directional RSI state that will always be displayed, regardless of orientation.
/// </summary>
Direction DirectionOverride { get; set; }
// NOTE: The below are ALL designed to NOT throw exceptions ever,
// instead making a bunch of noisy error logs.
@@ -66,6 +82,8 @@ namespace Robust.Client.Interfaces.GameObjects.Components
uint RenderOrder { get; set; }
bool IsInert { get; }
Matrix3 GetLocalMatrix();
/// <summary>
/// Sets a layer key to the layer map, creating it if it does not exist.
/// </summary>
@@ -204,30 +222,12 @@ namespace Robust.Client.Interfaces.GameObjects.Components
ISpriteLayer this[object layerKey] { get; }
IEnumerable<ISpriteLayer> AllLayers { get; }
}
public interface ISpriteLayer
{
SpriteComponent.DirectionOffset DirOffset { get; set; }
int GetLayerDirectionCount(ISpriteLayer layer);
RSI? Rsi { get; set; }
RSI.StateId RsiState { get; set; }
RSI? ActualRsi { get; }
Texture? Texture { get; set; }
Angle Rotation { get; set; }
Vector2 Scale { get; set; }
bool Visible { get; set; }
Color Color { get; set; }
float AnimationTime { get; set; }
int AnimationFrame { get; }
bool AutoAnimated { get; set; }
RSI.State.Direction EffectiveDirection(Angle worldRotation);
Vector2 LocalToLayer(Vector2 localPos);
/// <summary>
/// Calculate sprite bounding box in world-space coordinates.
/// </summary>
Box2 CalculateBoundingBox();
}
}

View File

@@ -0,0 +1,42 @@
using Robust.Client.Graphics;
using Robust.Shared.Maths;
namespace Robust.Client.GameObjects
{
public interface ISpriteLayer
{
SpriteComponent.DirectionOffset DirOffset { get; set; }
RSI? Rsi { get; set; }
RSI.StateId RsiState { get; set; }
RSI? ActualRsi { get; }
Texture? Texture { get; set; }
Angle Rotation { get; set; }
Vector2 Scale { get; set; }
bool Visible { get; set; }
Color Color { get; set; }
float AnimationTime { get; set; }
int AnimationFrame { get; }
bool AutoAnimated { get; set; }
RSI.State.Direction EffectiveDirection(Angle worldRotation);
Vector2 LocalToLayer(Vector2 localPos);
/// <summary>
/// Layer size in pixels.
/// Don't account layer scale or sprite world transform.
/// </summary>
Vector2i PixelSize { get; }
/// <summary>
/// Calculate layer bounding box in sprite local-space coordinates.
/// </summary>
/// <returns>Bounding box in sprite local-space coordinates.</returns>
Box2 CalculateBoundingBox();
}
}

View File

@@ -1,33 +1,24 @@
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Text;
using Robust.Client.GameObjects.EntitySystems;
using Robust.Client.Graphics;
using Robust.Client.Graphics.ClientEye;
using Robust.Client.Graphics.Drawing;
using Robust.Client.Graphics.Shaders;
using Robust.Client.Interfaces.GameObjects.Components;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Client.ResourceManagement;
using Robust.Client.Utility;
using Robust.Shared.Animations;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components.Renderable;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Reflection;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
using Robust.Shared.Reflection;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using System.Linq;
using Robust.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
using DrawDepthTag = Robust.Shared.GameObjects.DrawDepth;
@@ -110,6 +101,7 @@ namespace Robust.Client.GameObjects
/// If false, all layers get locked to south and rotation is a transformation.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[Obsolete("Use NoRotation and/or DirectionOverride")]
public bool Directional
{
get => _directional;
@@ -197,34 +189,42 @@ namespace Robust.Client.GameObjects
public void CopyFrom(SpriteComponent other)
{
//deep copying things to avoid entanglement
this._baseRsi = other._baseRsi;
this._directional = other._directional;
this._visible = other._visible;
this._layerMapShared = other._layerMapShared;
this.color = other.color;
this.offset = other.offset;
this.rotation = other.rotation;
this.scale = other.scale;
this.drawDepth = other.drawDepth;
this.Layers = new List<Layer>(other.Layers.Count);
_baseRsi = other._baseRsi;
_directional = other._directional;
_visible = other._visible;
_layerMapShared = other._layerMapShared;
color = other.color;
offset = other.offset;
rotation = other.rotation;
scale = other.scale;
drawDepth = other.drawDepth;
_screenLock = other._screenLock;
_overrideDirection = other._overrideDirection;
_enableOverrideDirection = other._enableOverrideDirection;
Layers = new List<Layer>(other.Layers.Count);
foreach (var otherLayer in other.Layers)
{
this.Layers.Add(new Layer(otherLayer, this));
Layers.Add(new Layer(otherLayer, this));
}
this.IsInert = other.IsInert;
this.LayerMap = other.LayerMap.ToDictionary(entry => entry.Key,
IsInert = other.IsInert;
LayerMap = other.LayerMap.ToDictionary(entry => entry.Key,
entry => entry.Value);
if (other.PostShader != null)
{
// only need to copy the shader if it's mutable
this.PostShader = other.PostShader.Mutable ? other.PostShader.Duplicate() : other.PostShader;
PostShader = other.PostShader.Mutable ? other.PostShader.Duplicate() : other.PostShader;
}
else
{
this.PostShader = null;
PostShader = null;
}
this.RenderOrder = other.RenderOrder;
RenderOrder = other.RenderOrder;
}
public Matrix3 GetLocalMatrix()
{
return Matrix3.CreateTransform(in offset, in rotation, in scale);
}
/// <inheritdoc />
@@ -945,6 +945,31 @@ namespace Robust.Client.GameObjects
LayerSetAutoAnimated(layer, autoAnimated);
}
public void LayerSetOffset(int layer, Vector2 layerOffset)
{
if (Layers.Count <= layer)
{
Logger.ErrorS(LogCategory,
"Layer with index '{0}' does not exist, cannot set offset! Trace:\n{1}",
layer, Environment.StackTrace);
return;
}
Layers[layer].SetOffset(layerOffset);
}
public void LayerSetOffset(object layerKey, Vector2 layerOffset)
{
if (!LayerMapTryGet(layerKey, out var layer))
{
Logger.ErrorS(LogCategory, "Layer with key '{0}' does not exist, cannot set offset! Trace:\n{1}",
layerKey, Environment.StackTrace);
return;
}
LayerSetOffset(layer, layerOffset);
}
/// <inheritdoc />
public RSI.StateId LayerGetState(int layer)
{
@@ -974,40 +999,60 @@ namespace Robust.Client.GameObjects
public ISpriteLayer this[object layerKey] => this[LayerMap[layerKey]];
public IEnumerable<ISpriteLayer> AllLayers => Layers;
internal void Render(DrawingHandleWorld drawingHandle, in Matrix3 worldTransform, Angle worldRotation,
Direction? overrideDirection = null)
// Lobby SpriteView rendering path
internal void Render(DrawingHandleWorld drawingHandle, Angle worldRotation, Direction? overrideDirection = null)
{
var angle = Rotation;
if (Directional)
RenderInternal(drawingHandle, worldRotation, Vector2.Zero, overrideDirection);
}
private bool _screenLock = false;
private Direction _overrideDirection = Direction.South;
private bool _enableOverrideDirection = false;
/// <inheritdoc />
[ViewVariables(VVAccess.ReadWrite)]
public bool NoRotation { get => _screenLock; set => _screenLock = value; }
/// <inheritdoc />
[ViewVariables(VVAccess.ReadWrite)]
public Direction DirectionOverride { get => _overrideDirection; set => _overrideDirection = value; }
/// <inheritdoc />
[ViewVariables(VVAccess.ReadWrite)]
public bool EnableDirectionOverride { get => _enableOverrideDirection; set => _enableOverrideDirection = value; }
// Sprite rendering path
internal void Render(DrawingHandleWorld drawingHandle, in Angle worldRotation, in Vector2 worldPosition)
{
Direction? overrideDir = null;
if (_enableOverrideDirection)
{
angle -= worldRotation;
overrideDir = _overrideDirection;
}
RenderInternal(drawingHandle, worldRotation, worldPosition, overrideDir);
}
private void CalcModelMatrix(int numDirs, Angle worldRotation, Vector2 worldPosition, out Matrix3 modelMatrix)
{
Angle angle;
if (_screenLock)
{
angle = Angle.Zero;
}
else
{
angle -= new Angle(MathHelper.PiOver2);
angle = CalcRectWorldAngle(worldRotation, numDirs);
}
var mOffset = Matrix3.CreateTranslation(Offset);
var mRotation = Matrix3.CreateRotation(angle);
Matrix3.Multiply(ref mRotation, ref mOffset, out var transform);
// Only apply scale if needed.
if(!Scale.EqualsApprox(Vector2.One)) transform.Multiply(Matrix3.CreateScale(Scale));
transform.Multiply(worldTransform);
RenderInternal(drawingHandle, worldRotation, overrideDirection, transform);
var sWorldRotation = angle;
modelMatrix = Matrix3.CreateTransform(in worldPosition, in sWorldRotation);
}
internal void Render(DrawingHandleWorld drawingHandle, Angle worldRotation, Direction? overrideDirection = null)
private void RenderInternal(DrawingHandleWorld drawingHandle, Angle worldRotation, Vector2 worldPosition, Direction? overrideDirection)
{
RenderInternal(drawingHandle, worldRotation, overrideDirection, Matrix3.Identity);
}
private void RenderInternal(DrawingHandleWorld drawingHandle, Angle worldRotation, Direction? overrideDirection,
in Matrix3 transform)
{
drawingHandle.SetTransform(transform);
var localMatrix = GetLocalMatrix();
foreach (var layer in Layers)
{
@@ -1016,26 +1061,77 @@ namespace Robust.Client.GameObjects
continue;
}
// TODO: Implement layer-specific rotation and scale.
// Oh and when you do update Layer.LocalToLayer so content doesn't break.
var numDirs = GetLayerDirectionCount(layer);
var texture = GetRenderTexture(layer, worldRotation, overrideDirection);
CalcModelMatrix(numDirs, worldRotation, worldPosition, out var modelMatrix);
Matrix3.Multiply(ref localMatrix, ref modelMatrix, out var transformMatrix);
drawingHandle.SetTransform(in transformMatrix);
if (layer.Shader != null)
{
drawingHandle.UseShader(layer.Shader);
}
drawingHandle.DrawTexture(texture, -(Vector2) texture.Size / (2f * EyeManager.PixelsPerMeter),
color * layer.Color);
if (layer.Shader != null)
{
drawingHandle.UseShader(null);
}
RenderLayer(drawingHandle, layer, worldRotation, overrideDirection);
}
}
private void RenderLayer(DrawingHandleWorld drawingHandle, Layer layer, Angle worldRotation, Direction? overrideDirection)
{
var texture = GetRenderTexture(layer, worldRotation, overrideDirection);
if (layer.Shader != null)
{
drawingHandle.UseShader(layer.Shader);
}
var layerColor = color * layer.Color;
var position = -(Vector2) texture.Size / (2f * EyeManager.PixelsPerMeter) + layer.Offset;
var textureSize = texture.Size / (float) EyeManager.PixelsPerMeter;
var quad = Box2.FromDimensions(position, textureSize);
// TODO: Implement layer-specific rotation and scale.
// Apply these directly to the box.
// Oh and when you do update Layer.LocalToLayer so content doesn't break.
// handle.Modulate changes the color
// drawingHandle.SetTransform() is set above, turning the quad into local space vertices
drawingHandle.DrawTextureRectRegion(texture, quad, layerColor);
if (layer.Shader != null)
{
drawingHandle.UseShader(null);
}
}
public static Angle CalcRectWorldAngle(Angle worldAngle, int numDirections)
{
var theta = worldAngle.Theta;
var segSize = (MathF.PI*2) / (numDirections * 2);
var segments = (int)(theta / segSize);
var odd = segments % 2;
var result = theta - (segments * segSize) - (odd * segSize);
return result;
}
public int GetLayerDirectionCount(ISpriteLayer layer)
{
if (!layer.RsiState.IsValid)
return 1;
// Pull texture from RSI state instead.
var rsi = layer.Rsi ?? BaseRSI;
if (rsi == null || !rsi.TryGetState(layer.RsiState, out var state))
{
state = GetFallbackState(resourceCache);
}
return state.Directions switch
{
RSI.State.DirectionType.Dir1 => 1,
RSI.State.DirectionType.Dir4 => 4,
RSI.State.DirectionType.Dir8 => 8,
_ => throw new ArgumentOutOfRangeException()
};
}
private Texture GetRenderTexture(Layer layer, Angle worldRotation, Direction? overrideDirection)
{
var texture = layer.Texture;
@@ -1067,8 +1163,11 @@ namespace Robust.Client.GameObjects
serializer.DataFieldCached(ref drawDepth, "drawdepth", DrawDepthTag.Default,
WithFormat.Constants<DrawDepthTag>());
serializer.DataFieldCached(ref color, "color", Color.White);
serializer.DataFieldCached(ref _directional, "directional", true);
serializer.DataFieldCached(ref _visible, "visible", true);
serializer.DataFieldCached(ref _directional, "directional", true); //TODO: Kill ME
serializer.DataFieldCached(ref _screenLock, "noRot", true);
serializer.DataFieldCached(ref _enableOverrideDirection, "enableOverrideDir", false);
serializer.DataFieldCached(ref _overrideDirection, "overrideDir", Direction.East);
// TODO: Writing?
if (!serializer.Reading)
@@ -1323,7 +1422,6 @@ namespace Robust.Client.GameObjects
Rotation = thestate.Rotation;
Offset = thestate.Offset;
Color = thestate.Color;
Directional = thestate.Directional;
RenderOrder = thestate.RenderOrder;
if (thestate.BaseRsiPath != null && BaseRSI != null)
@@ -1380,16 +1478,28 @@ namespace Robust.Client.GameObjects
}
}
private RSI.State.Direction GetDir(RSI.State.DirectionType type, Angle worldRotation)
private RSI.State.Direction GetDir(RSI.State.DirectionType rsiDirectionType, Angle worldRotation)
{
if (!Directional)
var dir = rsiDirectionType switch
{
return RSI.State.Direction.South;
}
RSI.State.DirectionType.Dir1 => Direction.South,
RSI.State.DirectionType.Dir4 => worldRotation.GetCardinalDir(),
RSI.State.DirectionType.Dir8 => worldRotation.GetDir(),
_ => throw new ArgumentException($"Unknown RSI DirectionType: {rsiDirectionType}.", nameof(rsiDirectionType))
};
var angle = new Angle(worldRotation);
return angle.GetDir().Convert(type);
return dir switch
{
Direction.North => RSI.State.Direction.North,
Direction.South => RSI.State.Direction.South,
Direction.East => RSI.State.Direction.East,
Direction.West => RSI.State.Direction.West,
Direction.SouthEast => RSI.State.Direction.SouthEast,
Direction.SouthWest => RSI.State.Direction.SouthWest,
Direction.NorthEast => RSI.State.Direction.NorthEast,
Direction.NorthWest => RSI.State.Direction.NorthWest,
_ => throw new ArgumentOutOfRangeException(nameof(dir), dir, null)
};
}
private void UpdateIsInert()
@@ -1494,6 +1604,39 @@ namespace Robust.Client.GameObjects
return builder.ToString();
}
/// <inheritdoc/>
public Box2 CalculateBoundingBox()
{
// fast check for empty sprites
if (Layers.Count == 0)
return new Box2();
// we need to calculate bounding box taking into account all nested layers
// because layers can have offsets, scale or rotation we need to calculate a new BB
// based on lowest bottomLeft and hightest topRight points from all layers
var box = Layers[0].CalculateBoundingBox();
for (int i = 1; i < Layers.Count; i++)
{
var layer = Layers[i];
var layerBB = layer.CalculateBoundingBox();
box = box.Union(layerBB);
}
// apply sprite transformations and calculate sprite bounding box
// we can optimize it a bit, if sprite doesn't have rotation
var spriteBox = box.Scale(Scale);
var spriteHasRotation = !Rotation.EqualsApprox(Angle.Zero);
var spriteBB = spriteHasRotation ?
new Box2Rotated(spriteBox, Rotation).CalcBoundingBox() : spriteBox;
// move it all to world transform system (with sprite offset)
var worldPosition = Owner.Transform.WorldPosition;
var worldBB = spriteBB.Translated(Offset + worldPosition);
return worldBB;
}
/// <summary>
/// Enum to "offset" a cardinal direction.
/// </summary>
@@ -1535,16 +1678,25 @@ namespace Robust.Client.GameObjects
[ViewVariables(VVAccess.ReadWrite)]
public Vector2 Scale { get; set; } = Vector2.One;
[ViewVariables(VVAccess.ReadWrite)]
public Angle Rotation { get; set; }
[ViewVariables(VVAccess.ReadWrite)]
public bool Visible = true;
[ViewVariables(VVAccess.ReadWrite)]
public Color Color { get; set; } = Color.White;
[ViewVariables(VVAccess.ReadWrite)]
public bool AutoAnimated = true;
[ViewVariables(VVAccess.ReadWrite)]
public Vector2 Offset { get; set; }
[ViewVariables]
public DirectionOffset DirOffset { get; set; }
[ViewVariables]
public RSI? ActualRsi => RSI ?? _parent.BaseRSI;
@@ -1765,6 +1917,38 @@ namespace Robust.Client.GameObjects
_parent.UpdateIsInert();
}
public void SetOffset(Vector2 offset)
{
Offset = offset;
}
/// <inheritdoc/>
public Vector2i PixelSize
{
get
{
var pixelSize = Vector2i.Zero;
if (Texture != null)
{
pixelSize = Texture.Size;
}
else if (ActualRsi != null)
{
pixelSize = ActualRsi.Size;
}
return pixelSize;
}
}
/// <inheritdoc/>
public Box2 CalculateBoundingBox()
{
// TODO: scale & rotation for layers is currently unimplemented.
return Box2.CenteredAround(Offset, PixelSize / EyeManager.PixelsPerMeter);
}
}
void IAnimationProperties.SetAnimatableProperty(string name, object value)

View File

@@ -1,15 +1,13 @@
using System;
using System.Collections.Generic;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components.UserInterface;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Interfaces.Reflection;
using Robust.Shared.IoC;
using Robust.Shared.Network;
using Robust.Shared.Players;
using Robust.Shared.Reflection;
using Robust.Shared.Serialization;
using IComponent = Robust.Shared.Interfaces.GameObjects.IComponent;
namespace Robust.Client.GameObjects.Components.UserInterface
namespace Robust.Client.GameObjects
{
public class ClientUserInterfaceComponent : SharedUserInterfaceComponent
{

View File

@@ -1,7 +1,6 @@
using Robust.Client.Interfaces.GameStates;
using Robust.Client.GameStates;
using Robust.Client.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Utility;

View File

@@ -1,7 +1,6 @@
using Robust.Client.GameObjects.Components.Animations;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.GameObjects;
namespace Robust.Client.GameObjects.EntitySystems
namespace Robust.Client.GameObjects
{
internal sealed class AnimationPlayerSystem : EntitySystem
{

View File

@@ -1,7 +1,7 @@
using System.Collections.Generic;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.GameObjects;
namespace Robust.Client.GameObjects.EntitySystems
namespace Robust.Client.GameObjects
{
internal sealed class AppearanceSystem : EntitySystem
{

View File

@@ -1,6 +1,6 @@
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.GameObjects;
namespace Robust.Client.GameObjects.EntitySystems
namespace Robust.Client.GameObjects
{
class AppearanceTestSystem : EntitySystem
{

View File

@@ -2,23 +2,19 @@
using System.Collections.Generic;
using JetBrains.Annotations;
using Robust.Client.Audio;
using Robust.Client.Interfaces.Graphics;
using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Interfaces.Physics;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Broadphase;
using Robust.Shared.Utility;
namespace Robust.Client.GameObjects.EntitySystems
namespace Robust.Client.GameObjects
{
[UsedImplicitly]
public class AudioSystem : EntitySystem
@@ -29,6 +25,8 @@ namespace Robust.Client.GameObjects.EntitySystems
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
private SharedBroadPhaseSystem _broadPhaseSystem = default!;
private readonly List<PlayingStream> _playingClydeStreams = new();
public int OcclusionCollisionMask;
@@ -36,10 +34,13 @@ namespace Robust.Client.GameObjects.EntitySystems
/// <inheritdoc />
public override void Initialize()
{
base.Initialize();
SubscribeNetworkEvent<PlayAudioEntityMessage>(PlayAudioEntityHandler);
SubscribeNetworkEvent<PlayAudioGlobalMessage>(PlayAudioGlobalHandler);
SubscribeNetworkEvent<PlayAudioPositionalMessage>(PlayAudioPositionalHandler);
SubscribeNetworkEvent<StopAudioMessageClient>(StopAudioMessageHandler);
_broadPhaseSystem = Get<SharedBroadPhaseSystem>();
}
private void StopAudioMessageHandler(StopAudioMessageClient ev)
@@ -146,7 +147,7 @@ namespace Robust.Client.GameObjects.EntitySystems
var occlusion = 0f;
if (sourceRelative.Length > 0)
{
occlusion = IoCManager.Resolve<IPhysicsManager>().IntersectRayPenetration(
occlusion = _broadPhaseSystem.IntersectRayPenetration(
pos.MapId,
new CollisionRay(
pos.Position,

View File

@@ -3,15 +3,11 @@ using System.Linq;
using JetBrains.Annotations;
using Robust.Client.Physics;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components.Transform;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
namespace Robust.Client.GameObjects.EntitySystems
namespace Robust.Client.GameObjects
{
// NOTE: this class handles both snap grid updates of occluders, as well as occluder tree updates (via its parent).
// This seems like it's doing somewhat double work because it already has an update queue for occluders but...

View File

@@ -1,9 +1,8 @@
using System.Collections.Generic;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.GameObjects;
namespace Robust.Client.GameObjects.EntitySystems
namespace Robust.Client.GameObjects
{
public class ContainerSystem : EntitySystem
{

View File

@@ -1,25 +1,15 @@
using Robust.Client.Graphics;
using Robust.Client.Graphics.Drawing;
using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Client.ResourceManagement;
using Robust.Shared.GameObjects.EntitySystemMessages;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using System;
using System.Collections.Generic;
using Robust.Client.Graphics.Overlays;
using Robust.Client.Graphics.Shaders;
using Robust.Client.Interfaces.Graphics.Overlays;
using Robust.Client.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Log;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Robust.Client.GameObjects

View File

@@ -1,8 +1,8 @@
using System;
using JetBrains.Annotations;
using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Client.Graphics;
using Robust.Client.Physics;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.GameObjects;
using Robust.Shared.Input;
using Robust.Shared.Input.Binding;
using Robust.Shared.IoC;
@@ -10,7 +10,7 @@ using Robust.Shared.Maths;
#nullable enable
namespace Robust.Client.GameObjects.EntitySystems
namespace Robust.Client.GameObjects
{
/// <summary>
/// Updates the position of every Eye every frame, so that the camera follows the player around.

View File

@@ -1,19 +1,15 @@
using System;
using Robust.Client.GameObjects.Components;
using Robust.Client.Interfaces.GameStates;
using Robust.Client.Interfaces.Input;
using Robust.Client.GameStates;
using Robust.Client.Input;
using Robust.Client.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Input;
using Robust.Shared.Input.Binding;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Players;
using Robust.Shared.Utility;
namespace Robust.Client.GameObjects.EntitySystems
namespace Robust.Client.GameObjects
{
/// <summary>
/// Client-side processing of all input commands through the simulation.
@@ -44,7 +40,7 @@ namespace Robust.Client.GameObjects.EntitySystems
/// <param name="message">Arguments for this event.</param>
/// <param name="replay">if true, current cmd state will not be checked or updated - use this for "replaying" an
/// old input that was saved or buffered until further processing could be done</param>
public bool HandleInputCommand(ICommonSession session, BoundKeyFunction function, FullInputCmdMessage message, bool replay = false)
public bool HandleInputCommand(ICommonSession? session, BoundKeyFunction function, FullInputCmdMessage message, bool replay = false)
{
#if DEBUG

View File

@@ -1,8 +1,8 @@
using Robust.Client.Audio.Midi;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
namespace Robust.Client.GameObjects.EntitySystems
namespace Robust.Client.GameObjects
{
public class MidiSystem : EntitySystem
{

View File

@@ -1,16 +1,13 @@
using System.Collections.Generic;
using JetBrains.Annotations;
using Robust.Client.Physics;
using Robust.Shared.GameObjects.Components.Transform;
using Robust.Shared.GameObjects.EntitySystemMessages;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
namespace Robust.Client.GameObjects.EntitySystems
namespace Robust.Client.GameObjects
{
/// <summary>
/// Keeps track of <see cref="DynamicTree{T}"/>s for various rendering-related components.

View File

@@ -1,10 +1,10 @@
using JetBrains.Annotations;
using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Shared.GameObjects.Systems;
using Robust.Client.Graphics;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
namespace Robust.Client.GameObjects.EntitySystems
namespace Robust.Client.GameObjects
{
/// <summary>
/// Updates the layer animation for every visible sprite.

View File

@@ -1,16 +1,14 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Robust.Shared.GameObjects.Components.Transform;
using Robust.Shared.GameObjects.EntitySystemMessages;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
namespace Robust.Client.GameObjects.EntitySystems
namespace Robust.Client.GameObjects
{
/// <summary>
/// Handles interpolation of transform positions.

View File

@@ -0,0 +1,51 @@
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
namespace Robust.Client.GameObjects
{
public class VelocityDebugSystem : EntitySystem
{
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
internal bool Enabled { get; set; }
private Label _label = default!;
public override void Initialize()
{
base.Initialize();
_label = new Label();
IoCManager.Resolve<IUserInterfaceManager>().StateRoot.AddChild(_label);
}
public override void FrameUpdate(float frameTime)
{
base.FrameUpdate(frameTime);
if (!Enabled)
{
_label.Visible = false;
return;
}
var player = _playerManager.LocalPlayer?.ControlledEntity;
if (player == null || !player.TryGetComponent(out PhysicsComponent? body))
{
_label.Visible = false;
return;
}
var screenPos = _eyeManager.WorldToScreen(player.Transform.WorldPosition);
LayoutContainer.SetPosition(_label, screenPos + new Vector2(0, 50));
_label.Visible = true;
_label.Text = $"Speed: {body.LinearVelocity.Length}\nLinear: {body.LinearVelocity.X:0.00}, {body.LinearVelocity.Y:0.00}\nAngular:{body.AngularVelocity}";
}
}
}

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