From fd92c8087606198b29f3c6956db7833fffae56d1 Mon Sep 17 00:00:00 2001 From: hyperion51 Date: Thu, 9 Apr 2020 07:48:45 +0100 Subject: [PATCH] Blueprints & Resources Added the ability to associate simple commodities with resource maps Added resource placement to zone generator Added crafting blueprints and stat addressing system Refactored Thrusters and Shields into Behaviors Fixed server losing database connection Updated icons --- .../.idea/contentModel.xml | 6 +- .idea/.idea.Economy/.idea/contentModel.xml | 5 + Aetheria-Economy.sln | 12 +- Aetheria-Economy.sln.DotSettings | 4 +- Assembly-CSharp-Editor.csproj | 18 +- Assembly-CSharp-firstpass.csproj | 18 +- Assembly-CSharp.csproj | 19 +- Assets/Resources/Sprites/Attribution.txt | 12 +- .../Resources/Sprites/Icons/Stroked/Moon.png | 3 + .../Sprites/Icons/Stroked/Moon.png.meta | 110 +++++ .../Sprites/Icons/Stroked/Planet.png | 4 +- .../Resources/Sprites/Icons/Stroked/Ship.png | 4 +- .../Resources/Sprites/Icons/Stroked/Sun.png | 4 +- .../Sprites/Icons/Stroked/Wormhole.png | 4 +- Assets/Scripts/Editor/DatabaseInspector.cs | 393 ++++++++++++------ Assets/Scripts/Editor/DatabaseView.cs | 65 ++- Assets/Scripts/Editor/EditorDispatch.cs | 4 +- Assets/Scripts/Editor/GalaxyEditor.cs | 5 +- Assets/Scripts/ServerShared/Attributes.cs | 10 + Assets/Scripts/ServerShared/BlueprintData.cs | 55 +++ .../BlueprintData.cs.meta} | 2 +- Assets/Scripts/ServerShared/DatabaseItems.cs | 70 ++-- Assets/Scripts/ServerShared/Enums.cs | 13 + Assets/Scripts/ServerShared/Extensions.cs | 2 + Assets/Scripts/ServerShared/GameContext.cs | 102 ++++- Assets/Scripts/ServerShared/GlobalData.cs | 176 ++++---- .../ServerShared/ItemBehaviors/Afterburner.cs | 47 ++- .../ServerShared/ItemBehaviors/Behaviors.cs | 21 +- .../ServerShared/ItemBehaviors/Cannon.cs | 53 +-- .../ServerShared/ItemBehaviors/Launcher.cs | 72 +--- .../ServerShared/ItemBehaviors/Reactor.cs | 28 +- .../ServerShared/ItemBehaviors/Sensor.cs | 25 +- .../ServerShared/ItemBehaviors/Shield.cs | 52 +++ .../ServerShared/ItemBehaviors/Shield.cs.meta | 3 + .../ServerShared/ItemBehaviors/Thruster.cs | 67 +++ .../ItemBehaviors/Thruster.cs.meta | 3 + .../ServerShared/ItemBehaviors/Turning.cs | 64 +++ .../ItemBehaviors/Turning.cs.meta | 3 + .../ServerShared/ItemBehaviors/Weapon.cs | 34 ++ .../ServerShared/ItemBehaviors/Weapon.cs.meta | 3 + Assets/Scripts/ServerShared/ItemData.cs | 220 ++++------ Assets/Scripts/ServerShared/ItemInstance.cs | 45 +- Assets/Scripts/ServerShared/Messages.cs | 19 +- Assets/Scripts/ServerShared/Ship.cs | 19 +- Assets/Scripts/ServerShared/ZoneData.cs | 97 ++--- Assets/Scripts/ServerShared/ZoneGenerator.cs | 72 +++- Assets/Scripts/StrategyGameManager.cs | 4 +- Assets/Scripts/Targetable.cs | 100 ----- Assets/Scripts/ZoneGeneratorTest.cs | 8 +- Economy.Server/Program.cs | 20 +- .../Debug/netcoreapp3.1/Economy.Server.dll | 4 +- .../Debug/netcoreapp3.1/Economy.Shared.dll | 2 +- ...onomy.Server.csprojAssemblyReference.cache | Bin 108033 -> 107728 bytes .../Debug/netcoreapp3.1/Economy.Server.dll | 4 +- Economy.Shared.Unity.csproj | 23 +- .../Debug/netstandard2.0/Economy.Shared.dll | 2 +- .../Debug/netstandard2.0/Economy.Shared.dll | 2 +- MessagePack.csproj | 18 +- 58 files changed, 1399 insertions(+), 855 deletions(-) create mode 100644 Assets/Resources/Sprites/Icons/Stroked/Moon.png create mode 100644 Assets/Resources/Sprites/Icons/Stroked/Moon.png.meta create mode 100644 Assets/Scripts/ServerShared/BlueprintData.cs rename Assets/Scripts/{Targetable.cs.meta => ServerShared/BlueprintData.cs.meta} (83%) create mode 100644 Assets/Scripts/ServerShared/ItemBehaviors/Shield.cs create mode 100644 Assets/Scripts/ServerShared/ItemBehaviors/Shield.cs.meta create mode 100644 Assets/Scripts/ServerShared/ItemBehaviors/Thruster.cs create mode 100644 Assets/Scripts/ServerShared/ItemBehaviors/Thruster.cs.meta create mode 100644 Assets/Scripts/ServerShared/ItemBehaviors/Turning.cs create mode 100644 Assets/Scripts/ServerShared/ItemBehaviors/Turning.cs.meta create mode 100644 Assets/Scripts/ServerShared/ItemBehaviors/Weapon.cs create mode 100644 Assets/Scripts/ServerShared/ItemBehaviors/Weapon.cs.meta delete mode 100644 Assets/Scripts/Targetable.cs diff --git a/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml b/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml index 3807bb2ff..962d138ae 100644 --- a/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml +++ b/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml @@ -660,6 +660,7 @@ + @@ -674,6 +675,10 @@ + + + + @@ -1089,7 +1094,6 @@ - diff --git a/.idea/.idea.Economy/.idea/contentModel.xml b/.idea/.idea.Economy/.idea/contentModel.xml index 294ffd4c5..08f0909c6 100644 --- a/.idea/.idea.Economy/.idea/contentModel.xml +++ b/.idea/.idea.Economy/.idea/contentModel.xml @@ -6,6 +6,7 @@ + @@ -19,6 +20,10 @@ + + + + diff --git a/Aetheria-Economy.sln b/Aetheria-Economy.sln index 0e57f1069..c422ea2e1 100644 --- a/Aetheria-Economy.sln +++ b/Aetheria-Economy.sln @@ -1,9 +1,9 @@ Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Assembly-CSharp", "Assembly-CSharp.csproj", "{29B684F0-E616-CD9C-EFF8-10A39DB37A52}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Economy.Shared.Unity", "Economy.Shared.Unity.csproj", "{A62B36C2-E9DE-B992-0779-F5FCF5968986}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Assembly-CSharp", "Assembly-CSharp.csproj", "{29B684F0-E616-CD9C-EFF8-10A39DB37A52}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MessagePack", "MessagePack.csproj", "{21EF11C5-27DC-3D88-B027-9A4B6F36BAE4}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Assembly-CSharp-firstpass", "Assembly-CSharp-firstpass.csproj", "{7D8742A4-0DFC-5667-0A98-3CA4312F9253}" @@ -16,14 +16,14 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {29B684F0-E616-CD9C-EFF8-10A39DB37A52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {29B684F0-E616-CD9C-EFF8-10A39DB37A52}.Debug|Any CPU.Build.0 = Debug|Any CPU - {29B684F0-E616-CD9C-EFF8-10A39DB37A52}.Release|Any CPU.ActiveCfg = Release|Any CPU - {29B684F0-E616-CD9C-EFF8-10A39DB37A52}.Release|Any CPU.Build.0 = Release|Any CPU {A62B36C2-E9DE-B992-0779-F5FCF5968986}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A62B36C2-E9DE-B992-0779-F5FCF5968986}.Debug|Any CPU.Build.0 = Debug|Any CPU {A62B36C2-E9DE-B992-0779-F5FCF5968986}.Release|Any CPU.ActiveCfg = Release|Any CPU {A62B36C2-E9DE-B992-0779-F5FCF5968986}.Release|Any CPU.Build.0 = Release|Any CPU + {29B684F0-E616-CD9C-EFF8-10A39DB37A52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {29B684F0-E616-CD9C-EFF8-10A39DB37A52}.Debug|Any CPU.Build.0 = Debug|Any CPU + {29B684F0-E616-CD9C-EFF8-10A39DB37A52}.Release|Any CPU.ActiveCfg = Release|Any CPU + {29B684F0-E616-CD9C-EFF8-10A39DB37A52}.Release|Any CPU.Build.0 = Release|Any CPU {21EF11C5-27DC-3D88-B027-9A4B6F36BAE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {21EF11C5-27DC-3D88-B027-9A4B6F36BAE4}.Debug|Any CPU.Build.0 = Debug|Any CPU {21EF11C5-27DC-3D88-B027-9A4B6F36BAE4}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/Aetheria-Economy.sln.DotSettings b/Aetheria-Economy.sln.DotSettings index 7eca19a47..3c5b52c62 100644 --- a/Aetheria-Economy.sln.DotSettings +++ b/Aetheria-Economy.sln.DotSettings @@ -1,2 +1,4 @@  - True \ No newline at end of file + True + True + True \ No newline at end of file diff --git a/Assembly-CSharp-Editor.csproj b/Assembly-CSharp-Editor.csproj index 9c44c35ee..2cf295a42 100644 --- a/Assembly-CSharp-Editor.csproj +++ b/Assembly-CSharp-Editor.csproj @@ -374,9 +374,18 @@ C:/Program Files/Unity/Hub/Editor/2018.4.17f1/Editor/Data/PlaybackEngines/windowsstandalonesupport/UnityEditor.WindowsStandalone.Extensions.dll + + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Microsoft.Extensions.Logging.Abstractions.dll + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Microsoft.SqlServer.Types.dll + + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Newtonsoft.Json.dll + + + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Remotion.Linq.dll + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/System.Buffers.dll @@ -401,15 +410,6 @@ C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.dll - - C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Newtonsoft.Json.dll - - - C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Microsoft.Extensions.Logging.Abstractions.dll - - - C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Remotion.Linq.dll - C:/Program Files/Unity/Hub/Editor/2018.4.17f1/Editor/Data/MonoBleedingEdge/lib/mono/4.7.1-api/mscorlib.dll diff --git a/Assembly-CSharp-firstpass.csproj b/Assembly-CSharp-firstpass.csproj index b607c50d2..37f3499c6 100644 --- a/Assembly-CSharp-firstpass.csproj +++ b/Assembly-CSharp-firstpass.csproj @@ -288,9 +288,18 @@ C:/Program Files/Unity/Hub/Editor/2018.4.17f1/Editor/Data/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll + + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Microsoft.Extensions.Logging.Abstractions.dll + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Microsoft.SqlServer.Types.dll + + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Newtonsoft.Json.dll + + + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Remotion.Linq.dll + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/System.Buffers.dll @@ -312,15 +321,6 @@ C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.dll - - C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Newtonsoft.Json.dll - - - C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Microsoft.Extensions.Logging.Abstractions.dll - - - C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Remotion.Linq.dll - C:/Program Files/Unity/Hub/Editor/2018.4.17f1/Editor/Data/MonoBleedingEdge/lib/mono/4.7.1-api/mscorlib.dll diff --git a/Assembly-CSharp.csproj b/Assembly-CSharp.csproj index 1b780eb63..a3567d2af 100644 --- a/Assembly-CSharp.csproj +++ b/Assembly-CSharp.csproj @@ -384,7 +384,6 @@ - @@ -654,9 +653,18 @@ C:/Program Files/Unity/Hub/Editor/2018.4.17f1/Editor/Data/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll + + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Microsoft.Extensions.Logging.Abstractions.dll + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Microsoft.SqlServer.Types.dll + + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Newtonsoft.Json.dll + + + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Remotion.Linq.dll + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/System.Buffers.dll @@ -678,15 +686,6 @@ C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.dll - - C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Newtonsoft.Json.dll - - - C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Microsoft.Extensions.Logging.Abstractions.dll - - - C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Remotion.Linq.dll - C:/Program Files/Unity/Hub/Editor/2018.4.17f1/Editor/Data/MonoBleedingEdge/lib/mono/4.7.1-api/mscorlib.dll diff --git a/Assets/Resources/Sprites/Attribution.txt b/Assets/Resources/Sprites/Attribution.txt index c65930fff..eca58db22 100644 --- a/Assets/Resources/Sprites/Attribution.txt +++ b/Assets/Resources/Sprites/Attribution.txt @@ -32,4 +32,14 @@ interlaced unicursal hexagram by Avana Vana wing by prasong tadoungsorn wings by iejank Fire by Bohdan Burmich -Hex Grid by Adam Robinson \ No newline at end of file +Hex Grid by Adam Robinson +solar system by Made by Made +Planet by Paul Krizsan +Planet by Eliricon +Planet by Vicons Design +Moon by Smalllike +spaceship by Thomas + +Other + +Asteroids by lodetobback \ No newline at end of file diff --git a/Assets/Resources/Sprites/Icons/Stroked/Moon.png b/Assets/Resources/Sprites/Icons/Stroked/Moon.png new file mode 100644 index 000000000..ca70d9648 --- /dev/null +++ b/Assets/Resources/Sprites/Icons/Stroked/Moon.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6fd0e241463005c442f670196c6a526fbf872501cd4419207b2daa1238be76fd +size 42072 diff --git a/Assets/Resources/Sprites/Icons/Stroked/Moon.png.meta b/Assets/Resources/Sprites/Icons/Stroked/Moon.png.meta new file mode 100644 index 000000000..9aad2bba4 --- /dev/null +++ b/Assets/Resources/Sprites/Icons/Stroked/Moon.png.meta @@ -0,0 +1,110 @@ +fileFormatVersion: 2 +guid: 823d8a1c4e071994087624c39f62b319 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 9 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 256 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 256 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: WebGL + maxTextureSize: 256 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 3ef44208584e3734393ce0943f312138 + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Sprites/Icons/Stroked/Planet.png b/Assets/Resources/Sprites/Icons/Stroked/Planet.png index 7ea165262..64d3e861e 100644 --- a/Assets/Resources/Sprites/Icons/Stroked/Planet.png +++ b/Assets/Resources/Sprites/Icons/Stroked/Planet.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:89c7279d8a54aaeb70cd6ceb6a20a52f5eb5eac8837c2f7f283f13f710576f79 -size 27655 +oid sha256:ae73e316ab8ff9584cfa45914c39bd9c4211d01daede9e96066818924965f406 +size 17214 diff --git a/Assets/Resources/Sprites/Icons/Stroked/Ship.png b/Assets/Resources/Sprites/Icons/Stroked/Ship.png index 90bc1bd33..cb3908001 100644 --- a/Assets/Resources/Sprites/Icons/Stroked/Ship.png +++ b/Assets/Resources/Sprites/Icons/Stroked/Ship.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:713155ef520612121593bb45bacea73a7e73b9c1234f51b6f9b781f8c9b0f2e8 -size 22397 +oid sha256:48442b7bf966f75c03e1317d8d09366818a588be9bbb8e750184ceb23d45d1e3 +size 25504 diff --git a/Assets/Resources/Sprites/Icons/Stroked/Sun.png b/Assets/Resources/Sprites/Icons/Stroked/Sun.png index 7f066d9bc..15c3581bf 100644 --- a/Assets/Resources/Sprites/Icons/Stroked/Sun.png +++ b/Assets/Resources/Sprites/Icons/Stroked/Sun.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4d721eeb767bdf603a839de402d1c2d0b23e91b0ad8f1f3d59c7cfb23850523 -size 28282 +oid sha256:57df5dc2e6eca09969a67774ccd8c489c41214835e7f25b734d469a2c06ca635 +size 19437 diff --git a/Assets/Resources/Sprites/Icons/Stroked/Wormhole.png b/Assets/Resources/Sprites/Icons/Stroked/Wormhole.png index aa868e20f..22131f2ed 100644 --- a/Assets/Resources/Sprites/Icons/Stroked/Wormhole.png +++ b/Assets/Resources/Sprites/Icons/Stroked/Wormhole.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea1cbeb20429b08923aa6de46c4ffeda1edaabe64cd01d2cb3003fe42b54a95a -size 38073 +oid sha256:e611baee3dadb0bb104b097633492c76819ef58a7eca71e811de9c81270a0b85 +size 17771 diff --git a/Assets/Scripts/Editor/DatabaseInspector.cs b/Assets/Scripts/Editor/DatabaseInspector.cs index b7c82a636..551f600c3 100644 --- a/Assets/Scripts/Editor/DatabaseInspector.cs +++ b/Assets/Scripts/Editor/DatabaseInspector.cs @@ -3,12 +3,12 @@ using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; -using UniRx; using Unity.Mathematics; using UnityEditor; using UnityEngine; -using Object = UnityEngine.Object; using static Unity.Mathematics.math; +using static UnityEditor.EditorGUILayout; +using Object = UnityEngine.Object; public class DatabaseInspector : EditorWindow { @@ -29,6 +29,8 @@ public class DatabaseInspector : EditorWindow private const int width = 100; private const int labelWidth = 20; + public Color LabelColor => EditorGUIUtility.isProSkin ? Color.white : Color.black; + // Set instance on reloading the window, else it gets lost after script reload (due to PlayMode changes, ...). public DatabaseInspector() { @@ -104,7 +106,10 @@ public class DatabaseInspector : EditorWindow else field.SetValue(obj, Inspect(field.Name.SplitCamelCase(), (int) value)); } - else if (type.IsEnum) field.SetValue(obj, Inspect(field.Name.SplitCamelCase(), (int) field.GetValue(obj), Enum.GetNames(field.FieldType))); + else if (type.IsEnum) + field.SetValue(obj, + Inspect(field.Name.SplitCamelCase(), (int) field.GetValue(obj), Enum.GetNames(field.FieldType), + type.GetCustomAttributes().Any())); //else if (field.FieldType == typeof(Color)) Inspect(field.Name, () => (Color) field.GetValue(obj), c => field.SetValue(obj, c)); else if (type == typeof(bool)) field.SetValue(obj, Inspect(field.Name.SplitCamelCase(), (bool) value)); else if (type == typeof(string)) @@ -119,8 +124,8 @@ public class DatabaseInspector : EditorWindow else if (type == typeof(PerformanceStat)) field.SetValue(obj, Inspect(field.Name.SplitCamelCase(), (PerformanceStat) value, obj as CraftedItemData)); else if (type == typeof(PerformanceStat[])) { - EditorGUILayout.LabelField(field.Name.SplitCamelCase(), EditorStyles.boldLabel); - using (new EditorGUILayout.VerticalScope(GUI.skin.box)) + LabelField(field.Name.SplitCamelCase(), EditorStyles.boldLabel); + using (new VerticalScope(GUI.skin.box)) { var stats = (PerformanceStat[]) value; var damageTypes = Enum.GetNames(typeof(DamageType)); @@ -143,24 +148,86 @@ public class DatabaseInspector : EditorWindow var dict = (Dictionary) field.GetValue(obj); Inspect(field.Name.SplitCamelCase(), ref dict); } + else if (type == typeof(List)) + { + var list = (List) field.GetValue(obj); + if(list==null) field.SetValue(obj, list = new List()); + + var blueprint = obj as BlueprintData; + var blueprintItem = DatabaseCache.Get(blueprint.Item); + if (blueprintItem is EquippableItemData equippableBlueprintItem) + { + Space(); + LabelField(field.Name.SplitCamelCase(), EditorStyles.boldLabel); + + using (var v = new VerticalScope(GUI.skin.box)) + { + var ingredients = blueprint.Ingredients.Keys + .Select(i => DatabaseCache.Get(i)) + .Where(i => i is CraftedItemData) + .Cast().ToArray(); + var ingredientNames = ingredients.Select(i => i.Name).ToArray(); + foreach (var effect in list) + { + using (var v2 = new VerticalScope(_list.ListItemStyle)) + { + using (var h = new HorizontalScope()) + { + GUILayout.Label("Ingredient", GUILayout.Width(width)); + if(ingredients.Length==0) + GUILayout.Label("No Ingredients!"); + else + { + var selectedIngredientIndex = + Array.FindIndex(ingredients, item => item.ID == effect.Ingredient); + if (selectedIngredientIndex == -1) + { + selectedIngredientIndex = 0; + GUI.changed = true; + } + var newSelection = Popup(selectedIngredientIndex, ingredientNames); + if (newSelection != selectedIngredientIndex) + GUI.changed = true; + effect.Ingredient = ingredients[newSelection].ID; + } + } + + Inspect(ref effect.StatReference, equippableBlueprintItem); + } + + } + + using (var h = new HorizontalScope(_list.ListItemStyle)) + { + GUILayout.Label($"Add new Stat Effect", GUILayout.ExpandWidth(true)); + var rect = GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight)); + GUI.DrawTexture(rect, Icons.Instance.plus, ScaleMode.StretchToFill, true, 1, LabelColor, 0, 0); + if (GUI.Button(rect, GUIContent.none, GUIStyle.none)) + { + list.Add(new BlueprintStatEffect()); + } + } + } + } + } else if (type == typeof(List) && link != null) { var list = (List) field.GetValue(obj); - if(list==null) field.SetValue(obj, (list = new List())); + if(list==null) field.SetValue(obj, list = new List()); Inspect(field.Name.SplitCamelCase(), ref list, link.EntryType); } else if (type == typeof(Guid) && link != null) field.SetValue(obj, Inspect(field.Name.SplitCamelCase(), (Guid) value, link.EntryType)); else if (type.GetCustomAttribute() != null) { - EditorGUILayout.Space(); - using (new EditorGUILayout.HorizontalScope()) + Space(); + using (new HorizontalScope()) { - EditorGUILayout.LabelField(field.Name.SplitCamelCase(), EditorStyles.boldLabel); + LabelField(field.Name.SplitCamelCase(), EditorStyles.boldLabel); if (type.IsInterface) { var subTypes = type.GetAllInterfaceClasses(); var selected = value != null ? Array.IndexOf(subTypes, value.GetType()) + 1 : 0; - var newSelection = EditorGUILayout.Popup(selected, + var newSelection = Popup(selected, subTypes.Select(t => t.Name.SplitCamelCase()).Prepend("None").ToArray()); if(newSelection != selected) field.SetValue(obj, value = newSelection==0?null:Activator.CreateInstance(subTypes[newSelection-1])); @@ -173,8 +240,8 @@ public class DatabaseInspector : EditorWindow var listType = field.FieldType.GenericTypeArguments[0]; if (listType.GetCustomAttribute() != null) { - EditorGUILayout.Space(); - using (new EditorGUILayout.VerticalScope(GUI.skin.box)) + Space(); + using (new VerticalScope(GUI.skin.box)) { var list = (IList) field.GetValue(obj); if (list == null) @@ -184,16 +251,16 @@ public class DatabaseInspector : EditorWindow } foreach (var o in list) { - using (new EditorGUILayout.VerticalScope(_list.ListItemStyle)) + using (new VerticalScope(_list.ListItemStyle)) { - using (new EditorGUILayout.HorizontalScope()) + using (new HorizontalScope()) { GUILayout.Label(o.GetType().Name.SplitCamelCase(), EditorStyles.boldLabel, GUILayout.ExpandWidth(true)); - var rect = EditorGUILayout.GetControlRect(false, + var rect = GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight)); GUI.DrawTexture(rect, Icons.Instance.minus, ScaleMode.StretchToFill, true, 1, - Color.black, 0, 0); + LabelColor, 0, 0); if (GUI.Button(rect, GUIContent.none, GUIStyle.none)) { list.Remove(o); @@ -201,16 +268,16 @@ public class DatabaseInspector : EditorWindow } } - EditorGUILayout.Space(); + Space(); Inspect(o, inspectablesOnly); } } - using (new EditorGUILayout.HorizontalScope(_list.ListItemStyle)) + using (new HorizontalScope(_list.ListItemStyle)) { GUILayout.Label($"Add new {listType.Name}", GUILayout.ExpandWidth(true)); - var rect = EditorGUILayout.GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight)); - GUI.DrawTexture(rect, Icons.Instance.plus, ScaleMode.StretchToFill, true, 1, Color.black, 0, 0); + var rect = GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight)); + GUI.DrawTexture(rect, Icons.Instance.plus, ScaleMode.StretchToFill, true, 1, LabelColor, 0, 0); if (GUI.Button(rect, GUIContent.none, GUIStyle.none)) { if (listType.IsInterface) @@ -236,8 +303,8 @@ public class DatabaseInspector : EditorWindow } else if (typeof(Object).IsAssignableFrom(listType)) { - EditorGUILayout.Space(); - using (var v = new EditorGUILayout.VerticalScope(GUI.skin.box)) + Space(); + using (var v = new VerticalScope(GUI.skin.box)) { var list = (IList) field.GetValue(obj); if (list == null) @@ -247,20 +314,20 @@ public class DatabaseInspector : EditorWindow } if(list.Count==0) - using (new EditorGUILayout.HorizontalScope(_list.ListItemStyle)) + using (new HorizontalScope(_list.ListItemStyle)) GUILayout.Label($"Add a {listType.Name} by dragging from the project hierarchy."); foreach (var oo in list) { var o = (Object) oo; - using (new EditorGUILayout.HorizontalScope(_list.ListItemStyle)) + using (new HorizontalScope(_list.ListItemStyle)) { GUILayout.Label(o.name.SplitCamelCase(), EditorStyles.boldLabel, GUILayout.ExpandWidth(true)); - var rect = EditorGUILayout.GetControlRect(false, + var rect = GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight)); GUI.DrawTexture(rect, Icons.Instance.minus, ScaleMode.StretchToFill, true, 1, - Color.black, 0, 0); + LabelColor, 0, 0); if (GUI.Button(rect, GUIContent.none, GUIStyle.none)) { list.Remove(o); @@ -291,10 +358,10 @@ public class DatabaseInspector : EditorWindow } else if (typeof(Object).IsAssignableFrom(type)) { - using (new EditorGUILayout.HorizontalScope()) + using (new HorizontalScope()) { GUILayout.Label(field.Name.SplitCamelCase(), GUILayout.Width(width)); - field.SetValue(obj, EditorGUILayout.ObjectField((Object)field.GetValue(obj),type,false)); + field.SetValue(obj, ObjectField((Object)field.GetValue(obj),type,false)); } } // else if (type == typeof(AudioClip)) @@ -310,44 +377,44 @@ public class DatabaseInspector : EditorWindow public bool Inspect(string label, bool value) { - using (var h = new EditorGUILayout.HorizontalScope()) + using (var h = new HorizontalScope()) { GUILayout.Label(label, GUILayout.Width(width)); - return EditorGUILayout.Toggle(value); + return Toggle(value); } } public float Inspect(string label, float value) { - using (var h = new EditorGUILayout.HorizontalScope()) + using (var h = new HorizontalScope()) { GUILayout.Label(label, GUILayout.Width(width)); - return EditorGUILayout.DelayedFloatField(value); + return DelayedFloatField(value); } } public string Inspect(string label, string value, bool area = false) { - using (var h = new EditorGUILayout.HorizontalScope()) + using (var h = new HorizontalScope()) { GUILayout.Label(label, GUILayout.Width(width)); if(area) - return EditorGUILayout.TextArea(value,GUILayout.MaxWidth(300)); - return EditorGUILayout.DelayedTextField(value); + return TextArea(value,GUILayout.MaxWidth(300)); + return DelayedTextField(value); } } public float InspectTemperature(string label, float value) { - using (var h = new EditorGUILayout.HorizontalScope()) + using (var h = new HorizontalScope()) { GUILayout.Label(label, GUILayout.Width(width)); GUILayout.Label("°K", _labelStyle, GUILayout.Width(labelWidth)); - value = EditorGUILayout.DelayedFloatField(value);//, GUILayout.ExpandWidth(false) + value = DelayedFloatField(value);//, GUILayout.ExpandWidth(false) GUILayout.Label("°C", _labelStyle, GUILayout.Width(labelWidth)); - value = EditorGUILayout.DelayedFloatField(value - 273.15f) + 273.15f; + value = DelayedFloatField(value - 273.15f) + 273.15f; GUILayout.Label("°F", _labelStyle, GUILayout.Width(labelWidth)); - value = (EditorGUILayout.DelayedFloatField((value - 273.15f) * 1.8f + 32) - 32) / 1.8f + 273.15f; + value = (DelayedFloatField((value - 273.15f) * 1.8f + 32) - 32) / 1.8f + 273.15f; return value; } @@ -355,55 +422,79 @@ public class DatabaseInspector : EditorWindow public float Inspect(string label, float value, float min, float max) { - using (var h = new EditorGUILayout.HorizontalScope()) + using (var h = new HorizontalScope()) { GUILayout.Label(label, GUILayout.Width(width)); - return EditorGUILayout.Slider(value, min, max); + return Slider(value, min, max); } } public int Inspect(string label, int value) { - using (var h = new EditorGUILayout.HorizontalScope()) + using (var h = new HorizontalScope()) { GUILayout.Label(label, GUILayout.Width(width)); - return EditorGUILayout.DelayedIntField(value); + return DelayedIntField(value); } } public int Inspect(string label, int value, int min, int max) { - using (var h = new EditorGUILayout.HorizontalScope()) + using (var h = new HorizontalScope()) { GUILayout.Label(label, GUILayout.Width(width)); - return EditorGUILayout.IntSlider(value, min, max); + return IntSlider(value, min, max); } } - public int Inspect(string label, int value, string[] enumOptions) + public int Inspect(string label, int value, string[] enumOptions, bool flags) { - using (var h = new EditorGUILayout.HorizontalScope()) + if (flags) { - GUILayout.Label(label, GUILayout.Width(width)); - return EditorGUILayout.Popup(value, enumOptions); + Space(); + LabelField(label, EditorStyles.boldLabel); + using (var v = new VerticalScope(GUI.skin.box)) + { + for (var i = 1; i < enumOptions.Length; i++) + { + using (var h = new HorizontalScope()) + { + GUILayout.Label(enumOptions[i], GUILayout.Width(width)); + var set = Toggle(1 << i == (1 << i & value)); + if (set) + value |= 1 << i; + else value &= ~(1 << i); + } + } + } + + return value; + } + else + { + using (var h = new HorizontalScope()) + { + GUILayout.Label(label, GUILayout.Width(width)); + return Popup(value, enumOptions); + } } } public string InspectGameObject(string label, string value) { - using (var h = new EditorGUILayout.HorizontalScope()) + using (var h = new HorizontalScope()) { GUILayout.Label(label, GUILayout.Width(width)); - return AssetDatabase.GetAssetPath(EditorGUILayout.ObjectField(AssetDatabase.LoadAssetAtPath(value), typeof(GameObject), false)); + return AssetDatabase.GetAssetPath(ObjectField(AssetDatabase.LoadAssetAtPath(value), typeof(GameObject), false)); } } public GameObject Inspect(string label, GameObject value) { - using (var h = new EditorGUILayout.HorizontalScope()) + using (var h = new HorizontalScope()) { GUILayout.Label(label, GUILayout.Width(width)); - return (GameObject) EditorGUILayout.ObjectField(value, typeof(GameObject), false); + return (GameObject) ObjectField(value, typeof(GameObject), false); } } @@ -412,10 +503,10 @@ public class DatabaseInspector : EditorWindow var val = value != null && value.Length > 0 ? new AnimationCurve(value.Select(v => new Keyframe(v.x, v.y, v.z, v.w)).ToArray()) : new AnimationCurve(); - using (var h = new EditorGUILayout.HorizontalScope()) + using (var h = new HorizontalScope()) { GUILayout.Label(label, GUILayout.Width(width)); - val = EditorGUILayout.CurveField(val, Color.yellow, new Rect(0, 0, 1, 1)); + val = CurveField(val, Color.yellow, new Rect(0, 0, 1, 1)); } return val.keys.Select(k => float4(k.time, k.value, k.inTangent, k.outTangent)).ToArray(); @@ -423,12 +514,12 @@ public class DatabaseInspector : EditorWindow public AnimationCurve Inspect(string label, AnimationCurve value) { - using (var h = new EditorGUILayout.HorizontalScope()) + using (var h = new HorizontalScope()) { GUILayout.Label(label, GUILayout.Width(width)); if (value == null) value = new AnimationCurve(); - value = EditorGUILayout.CurveField(value, Color.yellow, new Rect(0, 0, 1, 1)); + value = CurveField(value, Color.yellow, new Rect(0, 0, 1, 1)); } return value; @@ -436,9 +527,9 @@ public class DatabaseInspector : EditorWindow public Guid Inspect(string label, Guid value, Type entryType) { - EditorGUILayout.LabelField(label, EditorStyles.boldLabel); + LabelField(label, EditorStyles.boldLabel); var valueEntry = DatabaseCache.Get(value); - using (var h = new EditorGUILayout.HorizontalScope(GUI.skin.box)) + using (var h = new HorizontalScope(GUI.skin.box)) { GUILayout.Label((valueEntry as INamedEntry)?.EntryName ?? valueEntry?.ID.ToString() ?? $"Assign a {entryType.Name} by dragging from the list panel."); @@ -447,10 +538,10 @@ public class DatabaseInspector : EditorWindow var guid = (Guid) DragAndDrop.GetGenericData("Item"); var dragEntry = DatabaseCache.Get(guid); if(Event.current.type == EventType.DragUpdated) - DragAndDrop.visualMode = dragEntry != null && dragEntry.GetType()==entryType ? DragAndDropVisualMode.Copy : DragAndDropVisualMode.Rejected; + DragAndDrop.visualMode = dragEntry != null && entryType.IsInstanceOfType(dragEntry) ? DragAndDropVisualMode.Copy : DragAndDropVisualMode.Rejected; else if(Event.current.type == EventType.DragPerform) { - if (guid != Guid.Empty && dragEntry.GetType()==entryType) + if (guid != Guid.Empty && entryType.IsInstanceOfType(dragEntry)) { DragAndDrop.AcceptDrag(); GUI.changed = true; @@ -465,27 +556,27 @@ public class DatabaseInspector : EditorWindow public void Inspect(string label, ref Dictionary value) { - EditorGUILayout.Space(); - EditorGUILayout.LabelField(label, EditorStyles.boldLabel); + Space(); + LabelField(label, EditorStyles.boldLabel); - using (var v = new EditorGUILayout.VerticalScope(GUI.skin.box)) + using (var v = new VerticalScope(GUI.skin.box)) { if (value.Count == 0) { - using (var h = new EditorGUILayout.HorizontalScope(_list.ListItemStyle)) + using (var h = new HorizontalScope(_list.ListItemStyle)) { GUILayout.Label("Nothing Here! Add an item by dragging from the list panel."); } } foreach (var ingredient in value.ToArray()) { - using (var h = new EditorGUILayout.HorizontalScope(_list.ListItemStyle)) + using (var h = new HorizontalScope(_list.ListItemStyle)) { GUILayout.Label(DatabaseCache.Get(ingredient.Key).Name); - value[ingredient.Key] = EditorGUILayout.DelayedIntField(value[ingredient.Key], GUILayout.Width(50)); + value[ingredient.Key] = DelayedIntField(value[ingredient.Key], GUILayout.Width(50)); - var rect = EditorGUILayout.GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight)); - GUI.DrawTexture(rect, Icons.Instance.minus, ScaleMode.StretchToFill, true, 1, Color.black, 0, 0); + var rect = GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight)); + GUI.DrawTexture(rect, Icons.Instance.minus, ScaleMode.StretchToFill, true, 1, LabelColor, 0, 0); if (GUI.Button(rect, GUIContent.none, GUIStyle.none) || value[ingredient.Key]==0) value.Remove(ingredient.Key); } @@ -511,27 +602,27 @@ public class DatabaseInspector : EditorWindow public void Inspect(string label, ref Dictionary value) { - EditorGUILayout.Space(); - EditorGUILayout.LabelField(label, EditorStyles.boldLabel); + Space(); + LabelField(label, EditorStyles.boldLabel); - using (var v = new EditorGUILayout.VerticalScope(GUI.skin.box)) + using (var v = new VerticalScope(GUI.skin.box)) { if (value.Count == 0) { - using (var h = new EditorGUILayout.HorizontalScope(_list.ListItemStyle)) + using (var h = new HorizontalScope(_list.ListItemStyle)) { GUILayout.Label("Nothing Here! Add an item by dragging from the list panel."); } } foreach (var ingredient in value.ToArray()) { - using (var h = new EditorGUILayout.HorizontalScope(_list.ListItemStyle)) + using (var h = new HorizontalScope(_list.ListItemStyle)) { GUILayout.Label(DatabaseCache.Get(ingredient.Key).ID.ToString()); - value[ingredient.Key] = EditorGUILayout.DelayedFloatField(value[ingredient.Key], GUILayout.Width(50)); + value[ingredient.Key] = DelayedFloatField(value[ingredient.Key], GUILayout.Width(50)); - var rect = EditorGUILayout.GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight)); - GUI.DrawTexture(rect, Icons.Instance.minus, ScaleMode.StretchToFill, true, 1, Color.black, 0, 0); + var rect = GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight)); + GUI.DrawTexture(rect, Icons.Instance.minus, ScaleMode.StretchToFill, true, 1, LabelColor, 0, 0); if (GUI.Button(rect, GUIContent.none, GUIStyle.none)) value.Remove(ingredient.Key); } @@ -557,28 +648,39 @@ public class DatabaseInspector : EditorWindow public void Inspect(string label, ref List value, Type entryType) { - EditorGUILayout.Space(); - EditorGUILayout.LabelField(label, EditorStyles.boldLabel); + Space(); + LabelField(label, EditorStyles.boldLabel); - using (var v = new EditorGUILayout.VerticalScope(GUI.skin.box)) + using (var v = new VerticalScope(GUI.skin.box)) { if (value.Count == 0) { - using (var h = new EditorGUILayout.HorizontalScope(_list.ListItemStyle)) + using (var h = new HorizontalScope(_list.ListItemStyle)) { GUILayout.Label($"Nothing Here! Add a {entryType.Name} by dragging from the list panel."); } } - foreach (var ingredient in value.ToArray()) + foreach (var guid in value.ToArray()) { - using (var h = new EditorGUILayout.HorizontalScope(_list.ListItemStyle)) + using (var h = new HorizontalScope(_list.ListItemStyle)) { - GUILayout.Label((DatabaseCache.Get(ingredient) as INamedEntry)?.EntryName ?? DatabaseCache.Get(ingredient).ID.ToString()); + var entry = DatabaseCache.Get(guid); + if (entry == null) + { + value.Remove(guid); + GUI.changed = true; + } + else + { + GUILayout.Label((entry as INamedEntry)?.EntryName ?? entry.ID.ToString()); - var rect = EditorGUILayout.GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight)); - GUI.DrawTexture(rect, Icons.Instance.minus, ScaleMode.StretchToFill, true, 1, Color.black, 0, 0); - if (GUI.Button(rect, GUIContent.none, GUIStyle.none)) - value.Remove(ingredient); + var rect = GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight)); + GUI.DrawTexture(rect, Icons.Instance.minus, ScaleMode.StretchToFill, true, 1, LabelColor, 0, 0); + if (GUI.Button(rect, GUIContent.none, GUIStyle.none)) + { + value.Remove(guid); + } + } } } @@ -600,46 +702,101 @@ public class DatabaseInspector : EditorWindow } } } + + public void Inspect(ref StatReference effect, EquippableItemData item) + { + using (new VerticalScope()) + { + var behaviorNames = item.Behaviors.Select(b => b.GetType().Name).ToArray(); + var selectedBehaviorIndex = Array.IndexOf(behaviorNames, effect.Behavior); + if (selectedBehaviorIndex == -1) + { + selectedBehaviorIndex = 0; + GUI.changed = true; + } + using (new HorizontalScope()) + { + GUILayout.Label("Behavior", GUILayout.Width(width)); + if(behaviorNames.Length==0) + GUILayout.Label("No Behaviors!"); + else + { + var newSelection = Popup(selectedBehaviorIndex, behaviorNames); + if (newSelection != selectedBehaviorIndex) + GUI.changed = true; + effect.Behavior = behaviorNames[newSelection]; + } + } + + using (new HorizontalScope()) + { + GUILayout.Label("Stat", GUILayout.Width(width)); + if(behaviorNames.Length==0) + GUILayout.Label("No Behaviors!"); + else + { + var stats = item.Behaviors[selectedBehaviorIndex].GetType().GetFields() + .Where(f => f.FieldType == typeof(PerformanceStat)).ToArray(); + if(stats.Length==0) + GUILayout.Label("No Stats!"); + else + { + var statNames = stats.Select(s => s.Name).ToArray(); + var selectedStatIndex = Array.IndexOf(statNames, effect.Stat); + if (selectedStatIndex == -1) + { + selectedStatIndex = 0; + GUI.changed = true; + } + var newSelection = Popup(selectedStatIndex, statNames); + if (newSelection != selectedStatIndex) + GUI.changed = true; + effect.Stat = statNames[newSelection]; + } + } + } + } + } public PerformanceStat Inspect(string label, PerformanceStat value, CraftedItemData crafted) { - using (new EditorGUILayout.VerticalScope()) + using (new VerticalScope()) { - using (new EditorGUILayout.HorizontalScope()) + using (new HorizontalScope()) { GUILayout.Label(label, GUILayout.Width(width)); GUILayout.Label("Min", _labelStyle, GUILayout.Width(labelWidth)); - value.Min = EditorGUILayout.DelayedFloatField(value.Min); + value.Min = DelayedFloatField(value.Min); GUILayout.Label("Max", _labelStyle, GUILayout.Width(labelWidth + 5)); - value.Max = EditorGUILayout.DelayedFloatField(value.Max); + value.Max = DelayedFloatField(value.Max); } - using (new EditorGUILayout.HorizontalScope()) + using (new HorizontalScope()) { GUILayout.Label("", GUILayout.Width(width)); GUILayout.Label("H", _labelStyle); - value.HeatDependent = EditorGUILayout.Toggle(value.HeatDependent); + value.HeatDependent = Toggle(value.HeatDependent); GUILayout.Label("D", _labelStyle); - value.DurabilityDependent = EditorGUILayout.Toggle(value.DurabilityDependent); + value.DurabilityDependent = Toggle(value.DurabilityDependent); GUILayout.Label("QEx", _labelStyle, GUILayout.Width(labelWidth + 5)); - value.QualityExponent = EditorGUILayout.DelayedFloatField(value.QualityExponent); + value.QualityExponent = DelayedFloatField(value.QualityExponent); } - using (new EditorGUILayout.HorizontalScope()) - { - GUILayout.Label("", GUILayout.Width(width)); - GUILayout.Label("Ingredient", GUILayout.ExpandWidth(false)); - var ingredients = crafted.Ingredients.Keys.Select(DatabaseCache.Get).Where(i => i is CraftedItemData).Cast().ToList(); - var ingredient = value.Ingredient != null ? DatabaseCache.Get(value.Ingredient.Value) as CraftedItemData : null; - var names = ingredients.Select(i => i.Name).Append("None").ToArray(); - var selected = value.Ingredient == null || !crafted.Ingredients.ContainsKey(value.Ingredient.Value) - ? names.Length - 1 - : ingredients.IndexOf(ingredient); - var selection = EditorGUILayout.Popup(selected, names); - value.Ingredient = selection == names.Length - 1 ? (Guid?) null : ingredients[selection].ID; - } + // using (new HorizontalScope()) + // { + // GUILayout.Label("", GUILayout.Width(width)); + // GUILayout.Label("Ingredient", GUILayout.ExpandWidth(false)); + // var ingredients = crafted.Ingredients.Keys.Select(DatabaseCache.Get).Where(i => i is CraftedItemData).Cast().ToList(); + // var ingredient = value.Ingredient != null ? DatabaseCache.Get(value.Ingredient.Value) as CraftedItemData : null; + // var names = ingredients.Select(i => i.Name).Append("None").ToArray(); + // var selected = value.Ingredient == null || !crafted.Ingredients.ContainsKey(value.Ingredient.Value) + // ? names.Length - 1 + // : ingredients.IndexOf(ingredient); + // var selection = Popup(selected, names); + // value.Ingredient = selection == names.Length - 1 ? (Guid?) null : ingredients[selection].ID; + // } - EditorGUILayout.Space(); + Space(); return value; } @@ -647,7 +804,7 @@ public class DatabaseInspector : EditorWindow public void OnGUI() { - _labelStyle = new GUIStyle(EditorStyles.centeredGreyMiniLabel) {normal = {textColor = EditorGUIUtility.isProSkin?Color.white:Color.black}}; + _labelStyle = new GUIStyle(EditorStyles.centeredGreyMiniLabel) {normal = {textColor = LabelColor}}; Event current = Event.current; EventType currentEventType = current.type; @@ -658,11 +815,11 @@ public class DatabaseInspector : EditorWindow if (entry==null) { - EditorGUILayout.LabelField($"{(_list.SelectedItem==Guid.Empty?"No Entry Selected":"Selected Entry Not Found in Database")}\n{_list.SelectedItem}"); + LabelField($"{(_list.SelectedItem==Guid.Empty?"No Entry Selected":"Selected Entry Not Found in Database")}\n{_list.SelectedItem}"); return; } - _view = EditorGUILayout.BeginScrollView( + _view = BeginScrollView( _view, false, false, @@ -676,7 +833,7 @@ public class DatabaseInspector : EditorWindow var dataEntry = entry; - using (new EditorGUILayout.HorizontalScope()) + using (new HorizontalScope()) { if(GUILayout.Button("Print JSON")) Debug.Log(entry.ToJson()); @@ -692,10 +849,10 @@ public class DatabaseInspector : EditorWindow } } - using (var h = new EditorGUILayout.HorizontalScope()) + using (var h = new HorizontalScope()) { GUILayout.Label("ID"); - EditorGUILayout.LabelField(dataEntry.ID.ToString()); + LabelField(dataEntry.ID.ToString()); } Inspect(entry, true); @@ -704,7 +861,7 @@ public class DatabaseInspector : EditorWindow var hull = entry as HullData; if (hull != null) { - EditorGUILayout.Space(); + Space(); // TODO: Hull Hardpoints Inspector @@ -828,7 +985,7 @@ public class DatabaseInspector : EditorWindow DatabaseCache.Add(entry); } - EditorGUILayout.EndScrollView(); + EndScrollView(); } } diff --git a/Assets/Scripts/Editor/DatabaseView.cs b/Assets/Scripts/Editor/DatabaseView.cs index 5b9d2d5d2..fb2bd35a1 100644 --- a/Assets/Scripts/Editor/DatabaseView.cs +++ b/Assets/Scripts/Editor/DatabaseView.cs @@ -44,6 +44,8 @@ public class DatabaseListView : EditorWindow private string _connectionString; private const float LineHeight = 20; + public Color LabelColor => EditorGUIUtility.isProSkin ? Color.white : Color.black; + // Set instance on reloading the window, else it gets lost after script reload (due to PlayMode changes, ...). public DatabaseListView() { @@ -158,26 +160,61 @@ public class DatabaseListView : EditorWindow // When entries are changed locally, push the changes to RethinkDB _databaseCache.OnDataUpdateLocal += async entry => { - var result = await R.Db("Aetheria").Table("Items").Update(entry).RunAsync(_connection); + var table = entry.GetType().GetCustomAttribute()?.TableName ?? "Other"; + var result = await R + .Db("Aetheria") + .Table(table) + .Update(entry) + .RunAsync(_connection); Debug.Log($"Uploaded entry to RethinkDB: {entry.ID} result: {result}"); }; _databaseCache.OnDataInsertLocal += async entry => { - var result = await R.Db("Aetheria").Table("Items").Insert(entry).RunAsync(_connection); + var table = entry.GetType().GetCustomAttribute()?.TableName ?? "Other"; + var result = await R + .Db("Aetheria") + .Table(table) + .Insert(entry) + .RunAsync(_connection); Debug.Log($"Inserted entry to RethinkDB: {entry.ID} result: {result}"); }; _databaseCache.OnDataDeleteLocal += async entry => { - var result = await R.Db("Aetheria").Table("Items").Get(entry.ID).Delete().RunAsync(_connection); + var table = entry.GetType().GetCustomAttribute()?.TableName ?? "Other"; + var result = await R + .Db("Aetheria") + .Table(table) + .Get(entry.ID) + .Delete() + .RunAsync(_connection); Debug.Log($"Deleted entry from RethinkDB: {entry.ID} result: {result}"); }; // Get all item data from RethinkDB Task.Run(async () => { - var result = await R.Db("Aetheria").Table("Items").RunCursorAsync(_connection); + var result = await R + .Db("Aetheria") + .Table("Items") + .RunCursorAsync(_connection); + while (await result.MoveNextAsync()) + { + var entry = result.Current; + Debug.Log($"Received entry from RethinkDB: {entry.ID}"); + _databaseCache.Add(entry, true); + } + }).WrapErrors(); + + // Get all galaxy map layer data from RethinkDB + Task.Run(async () => + { + var result = await R + .Db("Aetheria") + .Table("Galaxy") + .Filter(o => o["$type"]==typeof(GalaxyMapLayerData).Name) + .RunCursorAsync(_connection); while (await result.MoveNextAsync()) { var entry = result.Current; @@ -189,7 +226,10 @@ public class DatabaseListView : EditorWindow // Subscribe to changes from RethinkDB Task.Run(async () => { - var result = await R.Db("Aetheria").Table("Items").Changes() + var result = await R + .Db("Aetheria") + .Table("Items") + .Changes() .RunChangesAsync(_connection); while (await result.MoveNextAsync()) { @@ -228,7 +268,7 @@ public class DatabaseListView : EditorWindow { GUILayout.Space(10); _gearFoldouts[i] = EditorGUILayout.Foldout(_gearFoldouts[i], - ((NameAttribute) _itemTypes[i].GetCustomAttribute(typeof(NameAttribute)))?.Name ?? _itemTypes[i].Name, + ((NameAttribute) _itemTypes[i].GetCustomAttribute(typeof(NameAttribute)))?.Name ?? FormatTypeName(_itemTypes[i].Name), true); } if (_gearFoldouts[i]) @@ -263,7 +303,7 @@ public class DatabaseListView : EditorWindow GUILayout.Space(20); GUILayout.Label("New " + _itemTypes[i].Name); var rect = EditorGUILayout.GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight)); - GUI.DrawTexture(rect, Icons.Instance.plus, ScaleMode.StretchToFill, true, 1, EditorGUIUtility.isProSkin?Color.white:Color.black, 0, 0); + GUI.DrawTexture(rect, Icons.Instance.plus, ScaleMode.StretchToFill, true, 1, LabelColor, 0, 0); } } } @@ -275,7 +315,7 @@ public class DatabaseListView : EditorWindow using (var h = new EditorGUILayout.HorizontalScope(ListItemStyle)) { _entryFoldouts[i] = EditorGUILayout.Foldout(_entryFoldouts[i], - ((NameAttribute) _entryTypes[i].GetCustomAttribute(typeof(NameAttribute)))?.Name ?? _entryTypes[i].Name, + ((NameAttribute) _entryTypes[i].GetCustomAttribute(typeof(NameAttribute)))?.Name ?? FormatTypeName(_entryTypes[i].Name), true); } @@ -312,7 +352,7 @@ public class DatabaseListView : EditorWindow GUILayout.Space(10); GUILayout.Label("New " + _entryTypes[i].Name); var rect = EditorGUILayout.GetControlRect(false, GUILayout.Width(EditorGUIUtility.singleLineHeight)); - GUI.DrawTexture(rect, Icons.Instance.plus, ScaleMode.StretchToFill, true, 1, EditorGUIUtility.isProSkin?Color.white:Color.black, 0, 0); + GUI.DrawTexture(rect, Icons.Instance.plus, ScaleMode.StretchToFill, true, 1, LabelColor, 0, 0); } } } @@ -397,6 +437,13 @@ public class DatabaseListView : EditorWindow //GUI.FocusControl(""); } + private string FormatTypeName(string typeName) + { + return (typeName.EndsWith("Data") + ? typeName.Substring(0, typeName.Length - 4) + : typeName).SplitCamelCase(); + } + private void CreateItem(Type type) { var newEntry = (DatabaseEntry) Activator.CreateInstance(type); diff --git a/Assets/Scripts/Editor/EditorDispatch.cs b/Assets/Scripts/Editor/EditorDispatch.cs index a50580e66..90d63faa9 100644 --- a/Assets/Scripts/Editor/EditorDispatch.cs +++ b/Assets/Scripts/Editor/EditorDispatch.cs @@ -35,8 +35,8 @@ public static class EditorDispatcher timer.Stop(); - if (dispatchCount > 0) - UnityEngine.Debug.Log(string.Format("[EditorDispatcher] Dispatched {0} calls in {1}ms", dispatchCount, timer.Elapsed.TotalMilliseconds)); +// if (dispatchCount > 0) +// UnityEngine.Debug.Log(string.Format("[EditorDispatcher] Dispatched {0} calls in {1}ms", dispatchCount, timer.Elapsed.TotalMilliseconds)); // todo some logic for disconnecting update when the queue is empty } diff --git a/Assets/Scripts/Editor/GalaxyEditor.cs b/Assets/Scripts/Editor/GalaxyEditor.cs index f912a3049..8bc17ca59 100644 --- a/Assets/Scripts/Editor/GalaxyEditor.cs +++ b/Assets/Scripts/Editor/GalaxyEditor.cs @@ -283,11 +283,12 @@ public class GalaxyEditor : Editor }).Run(_connection); } - galaxy.MapData.GlobalData.MapLayers["StarDensity"] = galaxy.MapData.StarDensity.ID = Guid.NewGuid(); + //galaxy.MapData.GlobalData.MapLayers["StarDensity"] = galaxy.MapData.StarDensity.ID = Guid.NewGuid(); + galaxy.MapData.StarDensity.Name = "StarDensity"; R.Db("Aetheria").Table("Galaxy").Insert(galaxy.MapData.StarDensity).Run(_connection); foreach (var data in galaxy.MapData.ResourceDensities) { - galaxy.MapData.GlobalData.MapLayers[data.Name] = data.ID = Guid.NewGuid(); + // galaxy.MapData.GlobalData.MapLayers[data.Name] = data.ID = Guid.NewGuid(); R.Db("Aetheria").Table("Galaxy").Insert(data).Run(_connection); } diff --git a/Assets/Scripts/ServerShared/Attributes.cs b/Assets/Scripts/ServerShared/Attributes.cs index 5306d0ea9..06b99ec0e 100644 --- a/Assets/Scripts/ServerShared/Attributes.cs +++ b/Assets/Scripts/ServerShared/Attributes.cs @@ -81,4 +81,14 @@ public class RangedIntInspectableAttribute : InspectableFieldAttribute Min = min; Max = max; } +} + +public class InspectableTypeAttribute : InspectableFieldAttribute +{ + public readonly Type Type; + + public InspectableTypeAttribute(Type type) + { + Type = type; + } } \ No newline at end of file diff --git a/Assets/Scripts/ServerShared/BlueprintData.cs b/Assets/Scripts/ServerShared/BlueprintData.cs new file mode 100644 index 000000000..00c16d9b7 --- /dev/null +++ b/Assets/Scripts/ServerShared/BlueprintData.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using MessagePack; +using Newtonsoft.Json; +using Unity.Mathematics; +using static Unity.Mathematics.math; + +[RethinkTable("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)] +public class BlueprintData : DatabaseEntry, INamedEntry +{ + [InspectableField, JsonProperty("name"), Key(1)] + public string Name; + + [InspectableField, JsonProperty("ingredients"), Key(2)] + public Dictionary Ingredients = new Dictionary(); + + [InspectableDatabaseLink(typeof(CraftedItemData)), JsonProperty("item"), Key(3)] + public Guid Item; + + [InspectableField, JsonProperty("quantity"), Key(4)] + public int Quantity; + + [InspectableField, JsonProperty("difficulty"), Key(5)] + public int Difficulty; + + [InspectableField, JsonProperty("statEffects"), Key(6)] + public List StatEffects = new List(); + + [IgnoreMember] public string EntryName + { + get => Name; + set => Name = value; + } +} + +[InspectableField, MessagePackObject, JsonObject(MemberSerialization.OptIn)] +public class BlueprintStatEffect +{ + [InspectableField, JsonProperty("ingredient"), Key(1)] + public Guid Ingredient; + + [InspectableField, JsonProperty("stat"), Key(2)] + public StatReference StatReference = new StatReference(); +} + +[InspectableField, MessagePackObject, JsonObject(MemberSerialization.OptIn)] +public class StatReference +{ + [InspectableType(typeof(IItemBehaviorData)), JsonProperty("behavior"), Key(1)] + public string Behavior; + + [InspectableField, JsonProperty("stat"), Key(2)] + public string Stat; +} diff --git a/Assets/Scripts/Targetable.cs.meta b/Assets/Scripts/ServerShared/BlueprintData.cs.meta similarity index 83% rename from Assets/Scripts/Targetable.cs.meta rename to Assets/Scripts/ServerShared/BlueprintData.cs.meta index aa5838e24..c956b95d8 100644 --- a/Assets/Scripts/Targetable.cs.meta +++ b/Assets/Scripts/ServerShared/BlueprintData.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: ae4eaa5cad8b4c744a0740b1eb2e8548 +guid: f2b1f367d240824408eb1e151c60bc79 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/Scripts/ServerShared/DatabaseItems.cs b/Assets/Scripts/ServerShared/DatabaseItems.cs index 952c50711..c833829fb 100644 --- a/Assets/Scripts/ServerShared/DatabaseItems.cs +++ b/Assets/Scripts/ServerShared/DatabaseItems.cs @@ -16,51 +16,42 @@ public interface INamedEntry string EntryName { get; set; } } -[InspectableField] -[MessagePackObject] -[Union(0, typeof(SimpleCommodityData))] -[Union(1, typeof(CompoundCommodityData))] -[Union(2, typeof(GearData))] -[Union(3, typeof(HullData))] -[Union(4, typeof(ShieldData))] -[Union(5, typeof(ThrusterData))] -[Union(6, typeof(SimpleCommodity))] -[Union(7, typeof(CompoundCommodity))] -[Union(8, typeof(Gear))] -[Union(9, typeof(GlobalData))] -[Union(10, typeof(ZoneData))] -[Union(11, typeof(Player))] -[Union(12, typeof(Corporation))] -[Union(13, typeof(Ship))] -[Union(14, typeof(Station))] -[Union(15, typeof(OrbitData))] -[Union(16, typeof(PlanetData))] -[JsonObject(MemberSerialization.OptIn)] -[JsonConverter(typeof(JsonKnownTypesConverter))] +[InspectableField, + MessagePackObject, + Union(0, typeof(SimpleCommodityData)), + Union(1, typeof(CompoundCommodityData)), + Union(2, typeof(GearData)), + Union(3, typeof(HullData)), + Union(6, typeof(SimpleCommodity)), + Union(7, typeof(CompoundCommodity)), + Union(8, typeof(Gear)), + Union(9, typeof(GlobalData)), + Union(10, typeof(ZoneData)), + Union(11, typeof(Player)), + Union(12, typeof(Corporation)), + Union(13, typeof(Ship)), + Union(14, typeof(Station)), + Union(15, typeof(OrbitData)), + Union(16, typeof(PlanetData)), + JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter))] //[Union(21, typeof(ContractData))] //[Union(22, typeof(Station))] public abstract class DatabaseEntry { - [JsonProperty("id")] [Key(0)] public Guid ID = Guid.NewGuid(); + [JsonProperty("id"), Key(0)] public Guid ID = Guid.NewGuid(); [IgnoreMember] public GameContext Context { get; set; } } -[RethinkTable("Users")] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[RethinkTable("Users"), MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class Player : DatabaseEntry, INamedEntry { - [JsonProperty("email")] [Key(1)] - public string Email; - - [JsonProperty("password")] [Key(2)] - public string Password; - - [JsonProperty("username")] [Key(3)] - public string Username; - - [JsonProperty("corporation")] [Key(4)] - public Guid Corporation; + [JsonProperty("email"), Key(1)] public string Email; + + [JsonProperty("password"), Key(2)] public string Password; + + [JsonProperty("username"), Key(3)] public string Username; + + [JsonProperty("corporation"), Key(4)] public Guid Corporation; [IgnoreMember] public string EntryName { @@ -69,13 +60,10 @@ public class Player : DatabaseEntry, INamedEntry } } -[RethinkTable("Galaxy")] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[RethinkTable("Galaxy"), MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class Corporation : DatabaseEntry, INamedEntry { - [JsonProperty("name")] [Key(1)] - public string Name; + [JsonProperty("name"), Key(1)] public string Name; [IgnoreMember] public string EntryName { diff --git a/Assets/Scripts/ServerShared/Enums.cs b/Assets/Scripts/ServerShared/Enums.cs index 23d22cb1b..a24763b95 100644 --- a/Assets/Scripts/ServerShared/Enums.cs +++ b/Assets/Scripts/ServerShared/Enums.cs @@ -1,3 +1,5 @@ +using System; + public enum LauncherCaliber { Micro, @@ -29,4 +31,15 @@ public enum DamageType Thermal, Optical, Ionizing +} + +[Flags] +public enum BodyType +{ + None = 0, + Asteroid = 1 << 0, + Planetoid = 1 << 1, + Planet = 1 << 2, + GasGiant = 1 << 3, + Sun = 1 << 4 } \ No newline at end of file diff --git a/Assets/Scripts/ServerShared/Extensions.cs b/Assets/Scripts/ServerShared/Extensions.cs index 8881887bb..e4f55b858 100644 --- a/Assets/Scripts/ServerShared/Extensions.cs +++ b/Assets/Scripts/ServerShared/Extensions.cs @@ -68,6 +68,8 @@ public static class Extensions private static Random? _random; private static Random Random => (Random) (_random ?? (_random = new Random(1337))); public static T RandomElement(this IEnumerable enumerable) => enumerable.ElementAt(Random.NextInt(0, enumerable.Count())); + public static float NextUnbounded(this Random random) => 1 / (1 - random.NextFloat()) - 1; + public static float NextUnbounded(this Random random, float bias, float power) => 1 / (1 - pow(random.NextFloat(), 1 - pow(clamp(bias,0,.99f), 1 / power))) - 1; private static Dictionary InterfaceClasses = new Dictionary(); public static Type[] GetAllInterfaceClasses(this Type type) diff --git a/Assets/Scripts/ServerShared/GameContext.cs b/Assets/Scripts/ServerShared/GameContext.cs index 90464fe11..9b77e3dc9 100644 --- a/Assets/Scripts/ServerShared/GameContext.cs +++ b/Assets/Scripts/ServerShared/GameContext.cs @@ -6,15 +6,17 @@ using static Unity.Mathematics.math; public class GameContext { + private Action _logger; private DatabaseCache _cache; public GlobalData GlobalData => _cache.GetAll().FirstOrDefault(); - private readonly Dictionary Tier = new Dictionary(); + // private readonly Dictionary Tier = new Dictionary(); - public GameContext(DatabaseCache cache) + public GameContext(DatabaseCache cache, Action logger) { _cache = cache; + _logger = logger; var globalData = _cache.GetAll().FirstOrDefault(); if (globalData == null) { @@ -23,14 +25,14 @@ public class GameContext } } - public int ItemTier(CraftedItemData itemData) - { - if (Tier.ContainsKey(itemData)) return Tier[itemData]; - - Tier[itemData] = itemData.Ingredients.Keys.Max(ci => _cache.Get(ci) is CraftedItemData craftableIngredient ? ItemTier(craftableIngredient) : 0); - - return Tier[itemData]; - } + // public int ItemTier(CraftedItemData itemData) + // { + // if (Tier.ContainsKey(itemData)) return Tier[itemData]; + // + // Tier[itemData] = itemData.Ingredients.Keys.Max(ci => _cache.Get(ci) is CraftedItemData craftableIngredient ? ItemTier(craftableIngredient) : 0); + // + // return Tier[itemData]; + // } public ItemData GetData(ItemInstance item) { @@ -80,21 +82,70 @@ public class GameContext return 0; } + private Dictionary AffectedStats = + new Dictionary(); + + public PerformanceStat GetAffectedStat(BlueprintData blueprint, BlueprintStatEffect effect) + { + // We've already cached this effect's stat, return it directly + if (AffectedStats.ContainsKey(effect)) return AffectedStats[effect]; + + // Get the data for the item the blueprint is for, return null if not found or not equippable + var blueprintItem = _cache.Get(blueprint.Item); + if (blueprintItem == null) + { + _logger($"Attempted to get stat effect but Blueprint {blueprint.ID} is not for an equippable item!"); + return AffectedStats[effect] = null; + } + + // Get the first behavior of the type specified in the blueprint stat effect, return null if not found + var effectBehavior = + blueprintItem.Behaviors.FirstOrDefault(b => b.GetType().Name == effect.StatReference.Behavior); + if (effectBehavior == null) + { + _logger($"Attempted to get stat effect for Blueprint {blueprint.ID} but stat references missing behavior \"{effect.StatReference.Behavior}\"!"); + return AffectedStats[effect] = null; + } + + // Get the first field in the behavior matching the name specified in the stat effect, return null if not found + var type = effectBehavior.GetType(); + var field = type.GetField(effect.StatReference.Stat); + if (field == null) + { + _logger($"Attempted to get stat effect for Blueprint {blueprint.ID} but behavior {effect.StatReference.Behavior} does not have a stat named \"{effect.StatReference.Stat}\"!"); + return AffectedStats[effect] = null; + } + + // Finally we've confirmed the stat effect is valid, return the affected stat + return AffectedStats[effect] = field.GetValue(effectBehavior) as PerformanceStat; + } + // Determine quality of either the item itself or the specific ingredient this stat depends on public float Quality(PerformanceStat stat, Gear item) { - Guid? ingredientID = stat.Ingredient; + + var activeEffects = item.Blueprint.StatEffects.Where(x => GetAffectedStat(item.Blueprint, x) == stat).ToArray(); float quality; - if (ingredientID == null) + if (!activeEffects.Any()) quality = item.CompoundQuality(); else { - var ingredientInstance = - item.Ingredients.FirstOrDefault(i => i.Data == ingredientID) as CraftedItemInstance; - if (ingredientInstance == null) - throw new InvalidOperationException( - $"Item {item.ID} has invalid crafting ingredients!"); - quality = ingredientInstance.CompoundQuality(); + var ingredients = item.Ingredients.Where(i => activeEffects.Any(e => e.Ingredient == i.Data)).ToArray(); + if(ingredients.Length != activeEffects.Length) + { + _logger($"Item {item.ID} does not have the ingredients specified by the stat effects of its blueprint!"); + return 0; + } + + float sum = 0; + foreach (var i in ingredients) + { + if (i is CraftedItemInstance ci) + sum += ci.CompoundQuality(); + else _logger($"Blueprint stat effect for item {item.ID} specifies invalid (non crafted) ingredient!"); + } + + quality = sum / ingredients.Length; } return quality; @@ -143,7 +194,8 @@ public class GameContext ID = Guid.NewGuid() }; - throw new InvalidOperationException("Attempted to create Simple Commodity instance using missing or incorrect item id"); + _logger("Attempted to create Simple Commodity instance using missing or incorrect item id"); + return null; } public CraftedItemInstance CreateInstance(Guid data, float quality) @@ -151,10 +203,18 @@ public class GameContext var item = _cache.Get(data); if (item == null) { - throw new InvalidOperationException("Attempted to create crafted item instance using missing or incorrect item id"); + _logger("Attempted to create crafted item instance using missing or incorrect item id!"); + return null; } - var ingredients = item.Ingredients.SelectMany(ci => + var blueprint = _cache.GetAll().FirstOrDefault(b => b.Item == data); + if (blueprint == null) + { + _logger("Attempted to create crafted item instance which has no blueprint!"); + return null; + } + + var ingredients = blueprint.Ingredients.SelectMany(ci => { var ingredient = _cache.Get(ci.Key); return ingredient is SimpleCommodityData diff --git a/Assets/Scripts/ServerShared/GlobalData.cs b/Assets/Scripts/ServerShared/GlobalData.cs index 847be4f3b..c0822a735 100644 --- a/Assets/Scripts/ServerShared/GlobalData.cs +++ b/Assets/Scripts/ServerShared/GlobalData.cs @@ -8,95 +8,95 @@ using static Unity.Mathematics.math; using static Unity.Mathematics.noise; using static NoiseFbm; -[Serializable] -[RethinkTable("Galaxy")] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[Serializable, RethinkTable("Galaxy"), MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class GlobalData : DatabaseEntry { - [InspectableField] [JsonProperty("targetPersistenceDuration")] [Key(1)] + [InspectableField, JsonProperty("targetPersistenceDuration"), Key(1)] public float TargetPersistenceDuration = 3; - - [InspectableField] [JsonProperty("heatRadiationPower")] [Key(2)] + + [InspectableField, JsonProperty("heatRadiationPower"), Key(2)] public float HeatRadiationPower = 1; - - [InspectableField] [JsonProperty("heatRadiationMultiplier")] [Key(3)] + + [InspectableField, JsonProperty("heatRadiationMultiplier"), Key(3)] public float HeatRadiationMultiplier = 1; - - [InspectableField] [JsonProperty("galaxyArms")] [Key(13)] + + [InspectableField, JsonProperty("galaxyArms"), Key(4)] public int Arms = 4; - - [InspectableField] [JsonProperty("galaxyTwist")] [Key(14)] + + [InspectableField, JsonProperty("galaxyTwist"), Key(5)] public float Twist = 10; - - [InspectableField] [JsonProperty("galaxyTwistPower")] [Key(15)] + + [InspectableField, JsonProperty("galaxyTwistPower"), Key(6)] public float TwistPower = 2; - [InspectableField] [JsonProperty("radiusPower")] [Key(4)] + [InspectableField, JsonProperty("radiusPower"), Key(7)] public float RadiusPower = 1.75f; - [InspectableField] [JsonProperty("massFloor")] [Key(5)] + [InspectableField, JsonProperty("massFloor"), Key(8)] public float MassFloor = 1; - [InspectableField] [JsonProperty("sunMass")] [Key(6)] + [InspectableField, JsonProperty("sunMass"), Key(9)] public float SunMass = 10000; - [InspectableField] [JsonProperty("gasGiantMass")] [Key(7)] + [InspectableField, JsonProperty("gasGiantMass"), Key(10)] public float GasGiantMass = 2000; - - [InspectableField] [JsonProperty("dockingDistance")] [Key(8)] + + [InspectableField, JsonProperty("dockingDistance"), Key(11)] public float DockingDistance = 10; - - [InspectableField] [JsonProperty("satelliteCreationMassFloor")] [Key(9)] + + [InspectableField, JsonProperty("satelliteCreationMassFloor"), Key(12)] public float SatelliteCreationMassFloor = 100; - - [InspectableField] [JsonProperty("satelliteCreationProbability")] [Key(10)] + + [InspectableField, JsonProperty("satelliteCreationProbability"), Key(13)] public float SatelliteCreationProbability = .25f; - - [InspectableField] [JsonProperty("binaryCreationProbability")] [Key(11)] + + [InspectableField, JsonProperty("binaryCreationProbability"), Key(14)] public float BinaryCreationProbability = .25f; - - [InspectableField] [JsonProperty("rosetteProbability")] [Key(12)] + + [InspectableField, JsonProperty("rosetteProbability"), Key(15)] public float RosetteProbability = .25f; - [InspectableField] [JsonProperty("mapLayers")] [Key(16)] - public Dictionary MapLayers = new Dictionary(); - - [InspectableField] [JsonProperty("zoneRadiusMin")] [Key(17)] + // [InspectableField] [JsonProperty("mapLayers")] [Key(16)] + // public Dictionary MapLayers = new Dictionary(); + + [InspectableField, JsonProperty("zoneRadiusMin"), Key(16)] public float MinimumZoneRadius = 500; - - [InspectableField] [JsonProperty("zoneRadiusMax")] [Key(18)] + + [InspectableField, JsonProperty("zoneRadiusMax"), Key(17)] public float MaximumZoneRadius = 2000; - - [InspectableField] [JsonProperty("zoneMassMin")] [Key(19)] + + [InspectableField, JsonProperty("zoneMassMin"), Key(18)] public float MinimumZoneMass = 10000; - - [InspectableField] [JsonProperty("zoneMassMax")] [Key(20)] + + [InspectableField, JsonProperty("zoneMassMax"), Key(19)] public float MaximumZoneMass = 100000; - - [InspectableField] [JsonProperty("orbitPeriodExponent")] [Key(21)] + + [InspectableField, JsonProperty("orbitPeriodExponent"), Key(20)] public float OrbitPeriodExponent = 1.5f; - - [InspectableField] [JsonProperty("orbitPeriodMultiplier")] [Key(22)] + + [InspectableField, JsonProperty("orbitPeriodMultiplier"), Key(21)] public float OrbitPeriodMultiplier = 1f; - - [InspectableField] [JsonProperty("gravityRadiusExponent")] [Key(23)] + + [InspectableField, JsonProperty("gravityRadiusExponent"), Key(22)] public float GravityRadiusExponent = 1.5f; - - [InspectableField] [JsonProperty("gravityRadiusMultiplier")] [Key(24)] + + [InspectableField, JsonProperty("gravityRadiusMultiplier"), Key(23)] public float GravityRadiusMultiplier = 1f; - - [InspectableField] [JsonProperty("beltProbability")] [Key(25)] + + [InspectableField, JsonProperty("beltProbability"), Key(24)] public float BeltProbability = .05f; - - [InspectableField] [JsonProperty("beltMassCeiling")] [Key(26)] + + [InspectableField, JsonProperty("beltMassCeiling"), Key(25)] public float BeltMassCeiling = 500f; - - [InspectableField] [JsonProperty("beltMassRatio")] [Key(27)] + + [InspectableField, JsonProperty("beltMassRatio"), Key(26)] public float BeltMassRatio = 100f; - - [InspectableField] [JsonProperty("beltMassExponent")] [Key(28)] + + [InspectableField, JsonProperty("beltMassExponent"), Key(27)] public float BeltMassExponent = 100f; + + [InspectableField, JsonProperty("planetMass"), Key(28)] + public float PlanetMass = 100f; public float PlanetRadius(float mass) { @@ -104,52 +104,50 @@ public class GlobalData : DatabaseEntry } } -[Serializable] -[RethinkTable("Galaxy")] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] -public class GalaxyMapLayerData : DatabaseEntry +[Inspectable, Serializable, RethinkTable("Galaxy"), MessagePackObject, JsonObject(MemberSerialization.OptIn)] +public class GalaxyMapLayerData : DatabaseEntry, INamedEntry { - [InspectableField] [JsonProperty("coreBoost")] [Key(1)] + [InspectableField, JsonProperty("coreBoost"), Key(1)] public float CoreBoost = 1.05f; - - [InspectableField] [JsonProperty("coreBoostOffset")] [Key(2)] + + [InspectableField, JsonProperty("coreBoostOffset"), Key(2)] public float CoreBoostOffset = .1f; - - [InspectableField] [JsonProperty("coreBoostPower")] [Key(3)] + + [InspectableField, JsonProperty("coreBoostPower"), Key(3)] public float CoreBoostPower = 2.25f; - - [InspectableField] [JsonProperty("spokeScale")] [Key(4)] + + [InspectableField, JsonProperty("spokeScale"), Key(4)] public float SpokeScale = 1; - - [InspectableField] [JsonProperty("spokeOffset")] [Key(5)] + + [InspectableField, JsonProperty("spokeOffset"), Key(5)] public float SpokeOffset = 0; - - [InspectableField] [JsonProperty("edgeReduction")] [Key(6)] + + [InspectableField, JsonProperty("edgeReduction"), Key(6)] public float EdgeReduction = 3; - - [InspectableField] [JsonProperty("noiseOffset")] [Key(7)] + + [InspectableField, JsonProperty("noiseOffset"), Key(7)] public float NoiseOffset = 0; - - [InspectableField] [JsonProperty("noiseAmplitude")] [Key(8)] + + [InspectableField, JsonProperty("noiseAmplitude"), Key(8)] public float NoiseAmplitude = 1.5f; - - [InspectableField] [JsonProperty("noiseGain")] [Key(9)] + + [InspectableField, JsonProperty("noiseGain"), Key(9)] public float NoiseGain = .7f; - - [InspectableField] [JsonProperty("noiseLacunarity")] [Key(10)] + + [InspectableField, JsonProperty("noiseLacunarity"), Key(10)] public float NoiseLacunarity = 2; - - [InspectableField] [JsonProperty("noiseOctaves")] [Key(11)] + + [InspectableField, JsonProperty("noiseOctaves"), Key(11)] public int NoiseOctaves = 7; - - [InspectableField] [JsonProperty("noiseFrequency")] [Key(12)] + + [InspectableField, JsonProperty("noiseFrequency"), Key(12)] public float NoiseFrequency = 1; - - [InspectableField] [JsonProperty("noisePosition")] [Key(13)] + + [InspectableField, JsonProperty("noisePosition"), Key(13)] public float NoisePosition = 1337; - [IgnoreMember] public string Name; + [InspectableField, JsonProperty("name"), Key(14)] + public string Name; public float Evaluate(float2 uv, GlobalData data) { @@ -165,6 +163,12 @@ public class GalaxyMapLayerData : DatabaseEntry return gal; } + + [IgnoreMember] public string EntryName + { + get => Name; + set => Name = value; + } } public static class NoiseFbm diff --git a/Assets/Scripts/ServerShared/ItemBehaviors/Afterburner.cs b/Assets/Scripts/ServerShared/ItemBehaviors/Afterburner.cs index bab7ea30b..073f1b28c 100644 --- a/Assets/Scripts/ServerShared/ItemBehaviors/Afterburner.cs +++ b/Assets/Scripts/ServerShared/ItemBehaviors/Afterburner.cs @@ -1,22 +1,20 @@ using System.Collections.Generic; +using System.Linq; using MessagePack; using Newtonsoft.Json; -[RethinkTable("Items")] -[InspectableField] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[InspectableField, MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class AfterburnerBehaviorData : IItemBehaviorData { - [InspectableField] [JsonProperty("thrust")] [Key(0)] - public PerformanceStat ThrustModifier; + [InspectableField, JsonProperty("thrust"), Key(0)] + public PerformanceStat ThrustModifier = new PerformanceStat(); - [InspectableField] [JsonProperty("speed")] [Key(1)] - public PerformanceStat SpeedModifier; + [InspectableField, JsonProperty("speed"), Key(1)] + public PerformanceStat SpeedModifier = new PerformanceStat(); - [InspectableField] [JsonProperty("torque")] [Key(2)] - public PerformanceStat TorqueModifier; + [InspectableField, JsonProperty("torque"), Key(2)] + public PerformanceStat TorqueModifier = new PerformanceStat(); public IItemBehavior CreateInstance(GameContext context, Ship ship, Gear item) { @@ -28,6 +26,7 @@ public class AfterburnerBehavior : IActivatedItemBehavior { private List> _modifiers = new List>(); private AfterburnerBehaviorData _data; + private ThrusterBehaviorData[] _thrusters; public Ship Ship { get; } public Gear Item { get; } @@ -43,6 +42,11 @@ public class AfterburnerBehavior : IActivatedItemBehavior Item = item; } + public void Initialize() + { + _thrusters = Ship.GetBehaviorData().ToArray(); + } + public void Update(float delta) { } @@ -53,17 +57,22 @@ public class AfterburnerBehavior : IActivatedItemBehavior public void Activate() { - var thrustMod = Ship.GetEquipped().Thrust.GetScaleModifiers(Ship); - _modifiers.Add(thrustMod); - thrustMod.Add(this,Context.Evaluate(_data.ThrustModifier,Item, Ship)); + if (_thrusters.Length == 0) return; - var speedMod = (Ship.Hull.ItemData as HullData).TopSpeed.GetScaleModifiers(Ship); - _modifiers.Add(speedMod); - speedMod.Add(this,Context.Evaluate(_data.SpeedModifier,Item, Ship)); + foreach (var thruster in _thrusters) + { + var thrustMod = thruster.Thrust.GetScaleModifiers(Ship); + thrustMod.Add(this,Context.Evaluate(_data.ThrustModifier,Item, Ship)); + _modifiers.Add(thrustMod); + } - var torqueMod = (Ship.GetEquipped(HardpointType.Thruster).ItemData as ThrusterData).Torque.GetScaleModifiers(Ship); - _modifiers.Add(torqueMod); - torqueMod.Add(this,Context.Evaluate(_data.TorqueModifier,Item, Ship)); + // var speedMod = (Ship.Hull.ItemData as HullData).TopSpeed.GetScaleModifiers(Ship); + // _modifiers.Add(speedMod); + // speedMod.Add(this,Context.Evaluate(_data.SpeedModifier,Item, Ship)); + // + // var torqueMod = (Ship.GetEquipped(HardpointType.Thruster).ItemData as ThrusterData).Torque.GetScaleModifiers(Ship); + // _modifiers.Add(torqueMod); + // torqueMod.Add(this,Context.Evaluate(_data.TorqueModifier,Item, Ship)); Ship.ForceThrust = true; } diff --git a/Assets/Scripts/ServerShared/ItemBehaviors/Behaviors.cs b/Assets/Scripts/ServerShared/ItemBehaviors/Behaviors.cs index 9d13f8f56..3ad7b7720 100644 --- a/Assets/Scripts/ServerShared/ItemBehaviors/Behaviors.cs +++ b/Assets/Scripts/ServerShared/ItemBehaviors/Behaviors.cs @@ -11,6 +11,7 @@ using static Unity.Mathematics.noise; public interface IItemBehavior { + void Initialize(); void Update(float delta); void FixedUpdate(float delta); Ship Ship { get; } @@ -25,15 +26,19 @@ public interface IActivatedItemBehavior : IItemBehavior void Deactivate(); } -[InspectableField] -[Union(0, typeof(CannonBehaviorData))] -[Union(1, typeof(LauncherBehaviorData))] -[Union(2, typeof(ReactorBehaviorData))] +public interface IAnalogItemBehavior : IItemBehavior +{ + void SetAxis(float value); +} + +[InspectableField, + Union(0, typeof(CannonBehaviorData)), + Union(1, typeof(LauncherBehaviorData)), + Union(2, typeof(ReactorBehaviorData)), + Union(4, typeof(AfterburnerBehaviorData)), + Union(5, typeof(SensorBehaviorData)), + JsonConverter(typeof(JsonKnownTypesConverter)), JsonObject(MemberSerialization.OptIn)] // [Union(3, typeof(PlusUltraBehaviorData))] -[Union(4, typeof(AfterburnerBehaviorData))] -[Union(5, typeof(SensorBehaviorData))] -[JsonConverter(typeof(JsonKnownTypesConverter))] -[JsonObject(MemberSerialization.OptIn)] public interface IItemBehaviorData { IItemBehavior CreateInstance(GameContext context, Ship ship, Gear item); diff --git a/Assets/Scripts/ServerShared/ItemBehaviors/Cannon.cs b/Assets/Scripts/ServerShared/ItemBehaviors/Cannon.cs index 75838417d..12ad73d3c 100644 --- a/Assets/Scripts/ServerShared/ItemBehaviors/Cannon.cs +++ b/Assets/Scripts/ServerShared/ItemBehaviors/Cannon.cs @@ -1,53 +1,20 @@ using MessagePack; using Newtonsoft.Json; -[RethinkTable("Items")] -[InspectableField] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] -public class CannonBehaviorData : IItemBehaviorData +[InspectableField, MessagePackObject, JsonObject(MemberSerialization.OptIn)] +public class CannonBehaviorData : WeaponBehaviorData, IItemBehaviorData { - [InspectablePrefab] [JsonProperty("bullet")] [Key(0)] + [InspectablePrefab, JsonProperty("bullet"), Key(9)] public string BulletPrefab; - - [InspectableField] [JsonProperty("damageType")] [Key(1)] - public DamageType DamageType; - [InspectableField] [JsonProperty("burstCount")] [Key(2)] - public int BurstCount; + [InspectableField, JsonProperty("spread"), Key(10)] + public PerformanceStat Spread = new PerformanceStat(); - [InspectableField] [JsonProperty("burstTime")] [Key(3)] - public PerformanceStat BurstTime; - - [InspectableField] [JsonProperty("bulletRange")] [Key(4)] - public PerformanceStat Range; - - [InspectableField] [JsonProperty("spread")] [Key(5)] - public PerformanceStat Spread; - - [InspectableField] [JsonProperty("bulletInherit")] [Key(6)] + [InspectableField, JsonProperty("bulletInherit"), Key(11)] public float Inherit; - [InspectableField] [JsonProperty("deflection")] [Key(7)] - public float Deflection; - - [InspectableField] [JsonProperty("visibility")] [Key(8)] - public PerformanceStat Visibility; - - [InspectableField] [JsonProperty("visibilityDecay")] [Key(9)] - public PerformanceStat VisibilityDecay; - - [InspectableField] [JsonProperty("bulletVelocity")] [Key(10)] - public PerformanceStat Velocity; - - [InspectableField] [JsonProperty("cooldown")] [Key(11)] - public PerformanceStat Cooldown; - - [InspectableField] [JsonProperty("damage")] [Key(12)] - public PerformanceStat Damage; - - [InspectableField] [JsonProperty("heat")] [Key(13)] - public PerformanceStat Heat; + [InspectableField, JsonProperty("bulletVelocity"), Key(12)] + public PerformanceStat Velocity = new PerformanceStat(); public IItemBehavior CreateInstance(GameContext context, Ship ship, Gear item) { @@ -114,6 +81,10 @@ public class CannonBehavior : IActivatedItemBehavior _firing = false; } + public void Initialize() + { + } + public void Update(float delta) { _cooldown -= delta / Context.Evaluate(_cannon.Cooldown, Item, Ship); diff --git a/Assets/Scripts/ServerShared/ItemBehaviors/Launcher.cs b/Assets/Scripts/ServerShared/ItemBehaviors/Launcher.cs index bdc1d9b06..9fab8cbc3 100644 --- a/Assets/Scripts/ServerShared/ItemBehaviors/Launcher.cs +++ b/Assets/Scripts/ServerShared/ItemBehaviors/Launcher.cs @@ -4,72 +4,38 @@ using MessagePack; using Newtonsoft.Json; using Unity.Mathematics; -[RethinkTable("Items")] -[InspectableField] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[InspectableField, MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class LauncherBehaviorData : IItemBehaviorData { - // [MessagePackFormatter(typeof(UnityGameObjectFormatter))] - // [Inspectable] [Key("missile")] public GameObject MissilePrefab; - // [MessagePackFormatter(typeof(ClipListFormatter))] - // [Inspectable] [Key("sounds")] public List Sounds; - // [MessagePackFormatter(typeof(UnityAudioClipFormatter))] - // [Inspectable] [Key("beepSound")] public AudioClip BeepSound; - // [Inspectable] [Key("beepCount")] public int Beeps; - [InspectableField] [JsonProperty("damageType")] [Key(0)] - public DamageType DamageType; + [InspectablePrefab, JsonProperty("missile"), Key(9)] + public string MissilePrefab; - [InspectableField] [JsonProperty("burstCount")] [Key(1)] - public int BurstCount; - - [InspectableField] [JsonProperty("burstTime")] [Key(2)] - public PerformanceStat BurstTime; - - [InspectableField] [JsonProperty("range")] [Key(3)] - public PerformanceStat Range; - - [InspectableAnimationCurve] [JsonProperty("guidance")] [Key(4)] + [InspectableAnimationCurve, JsonProperty("guidance"), Key(10)] public float4[] GuidanceCurve; - [InspectableAnimationCurve] [JsonProperty("thrustCurve")] [Key(5)] + [InspectableAnimationCurve, JsonProperty("thrustCurve"), Key(11)] public float4[] ThrustCurve; - [InspectableAnimationCurve] [JsonProperty("liftCurve")] [Key(6)] + [InspectableAnimationCurve, JsonProperty("liftCurve"), Key(12)] public float4[] LiftCurve; - [InspectableField] [JsonProperty("thrust")] [Key(7)] - public PerformanceStat Thrust; + [InspectableField, JsonProperty("thrust"), Key(13)] + public PerformanceStat Thrust = new PerformanceStat(); - [InspectableField] [JsonProperty("deflection")] [Key(8)] - public float Deflection; + [InspectableField, JsonProperty("lockAngle"), Key(14)] + public float LockAngle; - [InspectableField] [JsonProperty("lockOnBuffer")] [Key(9)] - public float LockOnDegrees; - - [InspectableField] [JsonProperty("frequency")] [Key(10)] + [InspectableField, JsonProperty("frequency"), Key(15)] public float DodgeFrequency; - [InspectableField] [JsonProperty("visibility")] [Key(11)] - public PerformanceStat Visibility; + [InspectableField, JsonProperty("launchSpeed"), Key(16)] + public PerformanceStat LaunchSpeed = new PerformanceStat(); - [InspectableField] [JsonProperty("launchSpeed")] [Key(12)] - public PerformanceStat LaunchSpeed; + [InspectableField, JsonProperty("missileSpeed"), Key(17)] + public PerformanceStat MissileSpeed = new PerformanceStat(); - [InspectableField] [JsonProperty("missileSpeed")] [Key(13)] - public PerformanceStat MissileSpeed; - - [InspectableField] [JsonProperty("cooldown")] [Key(14)] - public PerformanceStat Cooldown; - - [InspectableField] [JsonProperty("lockOnTime")] [Key(15)] - public PerformanceStat LockOnTime; - - [InspectableField] [JsonProperty("damage")] [Key(16)] - public PerformanceStat Damage; - - [InspectableField] [JsonProperty("heat")] [Key(17)] - public PerformanceStat Heat; + [InspectableField, JsonProperty("lockOnTime"), Key(18)] + public PerformanceStat LockOnTime = new PerformanceStat(); public IItemBehavior CreateInstance(GameContext context, Ship ship, Gear item) { @@ -154,6 +120,10 @@ public class LauncherBehavior : IActivatedItemBehavior // _lockingTimer = 1; } + public void Initialize() + { + } + public void Update(float delta) { // if (Ship.Target == null) diff --git a/Assets/Scripts/ServerShared/ItemBehaviors/Reactor.cs b/Assets/Scripts/ServerShared/ItemBehaviors/Reactor.cs index 63cc7530c..f18578c55 100644 --- a/Assets/Scripts/ServerShared/ItemBehaviors/Reactor.cs +++ b/Assets/Scripts/ServerShared/ItemBehaviors/Reactor.cs @@ -1,25 +1,23 @@ using MessagePack; using Newtonsoft.Json; -[RethinkTable("Items")] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class ReactorBehaviorData : IItemBehaviorData { - [InspectableField] [JsonProperty("charge")] [Key(0)] - public PerformanceStat Charge; + [InspectableField, JsonProperty("charge"), Key(0)] + public PerformanceStat Charge = new PerformanceStat(); - [InspectableField] [JsonProperty("capacitance")] [Key(1)] - public PerformanceStat Capacitance; + [InspectableField, JsonProperty("capacitance"), Key(1)] + public PerformanceStat Capacitance = new PerformanceStat(); - [InspectableField] [JsonProperty("efficiency")] [Key(2)] - public PerformanceStat Efficiency; + [InspectableField, JsonProperty("efficiency"), Key(2)] + public PerformanceStat Efficiency = new PerformanceStat(); - [InspectableField] [JsonProperty("overload")] [Key(3)] - public PerformanceStat OverloadEfficiency; + [InspectableField, JsonProperty("overload"), Key(3)] + public PerformanceStat OverloadEfficiency = new PerformanceStat(); - [InspectableField] [JsonProperty("underload")] [Key(4)] - public PerformanceStat UnderloadRecovery; + [InspectableField, JsonProperty("underload"), Key(4)] + public PerformanceStat UnderloadRecovery = new PerformanceStat(); public IItemBehavior CreateInstance(GameContext context, Ship ship, Gear item) { @@ -68,6 +66,10 @@ public class ReactorBehavior : IItemBehavior } + public void Initialize() + { + } + public void Update(float delta) { } diff --git a/Assets/Scripts/ServerShared/ItemBehaviors/Sensor.cs b/Assets/Scripts/ServerShared/ItemBehaviors/Sensor.cs index 989a76446..a1aa59d65 100644 --- a/Assets/Scripts/ServerShared/ItemBehaviors/Sensor.cs +++ b/Assets/Scripts/ServerShared/ItemBehaviors/Sensor.cs @@ -2,23 +2,20 @@ using MessagePack; using Newtonsoft.Json; -[RethinkTable("Items")] -[InspectableField] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[InspectableField, MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class SensorBehaviorData : IItemBehaviorData { - [InspectableField] [JsonProperty("radiance")] [Key(0)] - public PerformanceStat Radiance; + [InspectableField, JsonProperty("radiance"), Key(0)] + public PerformanceStat Radiance = new PerformanceStat(); - [InspectableField] [JsonProperty("masking")] [Key(1)] - public PerformanceStat RadianceMasking; + [InspectableField, JsonProperty("masking"), Key(1)] + public PerformanceStat RadianceMasking = new PerformanceStat(); - [InspectableField] [JsonProperty("sensitivity")] [Key(2)] - public PerformanceStat Sensitivity; + [InspectableField, JsonProperty("sensitivity"), Key(2)] + public PerformanceStat Sensitivity = new PerformanceStat(); - [InspectableField] [JsonProperty("range")] [Key(3)] - public PerformanceStat Range; + [InspectableField, JsonProperty("range"), Key(3)] + public PerformanceStat Range = new PerformanceStat(); public IItemBehavior CreateInstance(GameContext context, Ship ship, Gear item) { @@ -44,6 +41,10 @@ public class SensorBehavior : IItemBehavior Context = context; } + public void Initialize() + { + } + public void Update(float delta) { // var ship = Hardpoint.Ship.Ship.transform; diff --git a/Assets/Scripts/ServerShared/ItemBehaviors/Shield.cs b/Assets/Scripts/ServerShared/ItemBehaviors/Shield.cs new file mode 100644 index 000000000..9f6d47219 --- /dev/null +++ b/Assets/Scripts/ServerShared/ItemBehaviors/Shield.cs @@ -0,0 +1,52 @@ +using MessagePack; +using Newtonsoft.Json; +using Unity.Mathematics; +using static Unity.Mathematics.math; + +[MessagePackObject, JsonObject(MemberSerialization.OptIn)] +public class ShieldBehaviorData : IItemBehaviorData +{ + [InspectableField, JsonProperty("efficiency"), Key(0)] + public PerformanceStat Efficiency = new PerformanceStat(); + + [InspectableField, JsonProperty("shielding"), Key(1)] + public PerformanceStat Shielding = new PerformanceStat(); + + public IItemBehavior CreateInstance(GameContext context, Ship ship, Gear item) + { + return new ShieldBehavior(context, this, ship, item); + } +} + +public class ShieldBehavior : IItemBehavior +{ + public Ship Ship { get; } + public Gear Item { get; } + public GameContext Context { get; } + + public IItemBehaviorData Data => _data; + + private ShieldBehaviorData _data; + + public ShieldBehavior(GameContext context, ShieldBehaviorData data, Ship ship, Gear item) + { + Context = context; + _data = data; + Ship = ship; + Item = item; + + // TODO: Detect hits on Ship, keep a list of callbacks that modify the hit by reference + } + + public void FixedUpdate(float delta) + { + } + + public void Initialize() + { + } + + public void Update(float delta) + { + } +} \ No newline at end of file diff --git a/Assets/Scripts/ServerShared/ItemBehaviors/Shield.cs.meta b/Assets/Scripts/ServerShared/ItemBehaviors/Shield.cs.meta new file mode 100644 index 000000000..872817b1a --- /dev/null +++ b/Assets/Scripts/ServerShared/ItemBehaviors/Shield.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: dbb1419b4645402aad5a394b983a637f +timeCreated: 1586275939 \ No newline at end of file diff --git a/Assets/Scripts/ServerShared/ItemBehaviors/Thruster.cs b/Assets/Scripts/ServerShared/ItemBehaviors/Thruster.cs new file mode 100644 index 000000000..f30d1721e --- /dev/null +++ b/Assets/Scripts/ServerShared/ItemBehaviors/Thruster.cs @@ -0,0 +1,67 @@ +using MessagePack; +using Newtonsoft.Json; +using Unity.Mathematics; +using static Unity.Mathematics.math; + +[MessagePackObject, JsonObject(MemberSerialization.OptIn)] +public class ThrusterBehaviorData : IItemBehaviorData +{ + [InspectableField, JsonProperty("thrust"), Key(0)] + public PerformanceStat Thrust = new PerformanceStat(); + + [InspectableField, JsonProperty("torque"), Key(1)] + public PerformanceStat Torque = new PerformanceStat(); + + [InspectableField, JsonProperty("visibility"), Key(2)] + public PerformanceStat Visibility = new PerformanceStat(); + + [InspectableField, JsonProperty("heat"), Key(3)] + public PerformanceStat Heat = new PerformanceStat(); + + public IItemBehavior CreateInstance(GameContext context, Ship ship, Gear item) + { + return new ThrusterBehavior(context, this, ship, item); + } +} + +public class ThrusterBehavior : IAnalogItemBehavior +{ + public Ship Ship { get; } + public Gear Item { get; } + public GameContext Context { get; } + + public IItemBehaviorData Data => _data; + + private ThrusterBehaviorData _data; + + private float _thrust; + + public ThrusterBehavior(GameContext context, ThrusterBehaviorData data, Ship ship, Gear item) + { + Context = context; + _data = data; + Ship = ship; + Item = item; + } + + public void SetAxis(float value) + { + _thrust = saturate(value); + } + + public void FixedUpdate(float delta) + { + + } + + public void Initialize() + { + } + + public void Update(float delta) + { + Ship.Velocity += _thrust * Context.Evaluate(_data.Thrust, Item, Ship) * delta; + Ship.AddHeat(_thrust * Context.Evaluate(_data.Heat, Item, Ship) * delta); + Ship.VisibilitySources[this] = _thrust * Context.Evaluate(_data.Visibility, Item, Ship); + } +} \ No newline at end of file diff --git a/Assets/Scripts/ServerShared/ItemBehaviors/Thruster.cs.meta b/Assets/Scripts/ServerShared/ItemBehaviors/Thruster.cs.meta new file mode 100644 index 000000000..1ce6b1df0 --- /dev/null +++ b/Assets/Scripts/ServerShared/ItemBehaviors/Thruster.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f46e0da62f8c40f69bba0b7bcff8662f +timeCreated: 1586267627 \ No newline at end of file diff --git a/Assets/Scripts/ServerShared/ItemBehaviors/Turning.cs b/Assets/Scripts/ServerShared/ItemBehaviors/Turning.cs new file mode 100644 index 000000000..8dbc7ac9a --- /dev/null +++ b/Assets/Scripts/ServerShared/ItemBehaviors/Turning.cs @@ -0,0 +1,64 @@ +using MessagePack; +using Newtonsoft.Json; +using Unity.Mathematics; +using static Unity.Mathematics.math; + +[MessagePackObject, JsonObject(MemberSerialization.OptIn)] +public class TurningBehaviorData : IItemBehaviorData +{ + [InspectableField, JsonProperty("torque"), Key(0)] + public PerformanceStat Torque = new PerformanceStat(); + + [InspectableField, JsonProperty("visibility"), Key(1)] + public PerformanceStat Visibility = new PerformanceStat(); + + [InspectableField, JsonProperty("heat"), Key(2)] + public PerformanceStat Heat = new PerformanceStat(); + + public IItemBehavior CreateInstance(GameContext context, Ship ship, Gear item) + { + return new TurningBehavior(context, this, ship, item); + } +} + +public class TurningBehavior : IAnalogItemBehavior +{ + public Ship Ship { get; } + public Gear Item { get; } + public GameContext Context { get; } + + public IItemBehaviorData Data => _data; + + private TurningBehaviorData _data; + + private float _turning; + + public TurningBehavior(GameContext context, TurningBehaviorData data, Ship ship, Gear item) + { + Context = context; + _data = data; + Ship = ship; + Item = item; + } + + public void SetAxis(float value) + { + _turning = clamp(value, -1, 1); + } + + public void FixedUpdate(float delta) + { + + } + + public void Initialize() + { + } + + public void Update(float delta) + { + Ship.Direction = mul(Ship.Direction, Unity.Mathematics.float2x2.Rotate(_turning * Context.Evaluate(_data.Torque, Item, Ship) * delta)); + Ship.AddHeat(abs(_turning) * Context.Evaluate(_data.Heat, Item, Ship) * delta); + Ship.VisibilitySources[this] = abs(_turning) * Context.Evaluate(_data.Visibility, Item, Ship); + } +} \ No newline at end of file diff --git a/Assets/Scripts/ServerShared/ItemBehaviors/Turning.cs.meta b/Assets/Scripts/ServerShared/ItemBehaviors/Turning.cs.meta new file mode 100644 index 000000000..48dc539aa --- /dev/null +++ b/Assets/Scripts/ServerShared/ItemBehaviors/Turning.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 21343037bc4842669c20b0606b03a622 +timeCreated: 1586270198 \ No newline at end of file diff --git a/Assets/Scripts/ServerShared/ItemBehaviors/Weapon.cs b/Assets/Scripts/ServerShared/ItemBehaviors/Weapon.cs new file mode 100644 index 000000000..2390c294d --- /dev/null +++ b/Assets/Scripts/ServerShared/ItemBehaviors/Weapon.cs @@ -0,0 +1,34 @@ +using MessagePack; +using Newtonsoft.Json; + +[Union(0, typeof(CannonBehaviorData)), + Union(1, typeof(LauncherBehaviorData))] +public abstract class WeaponBehaviorData +{ + [InspectableField, JsonProperty("damageType"), Key(0)] + public DamageType DamageType; + + [InspectableField, JsonProperty("damage"), Key(1)] + public PerformanceStat Damage = new PerformanceStat(); + + [InspectableField, JsonProperty("range"), Key(2)] + public PerformanceStat Range = new PerformanceStat(); + + [InspectableField, JsonProperty("cooldown"), Key(3)] + public PerformanceStat Cooldown = new PerformanceStat(); + + [InspectableField, JsonProperty("heat"), Key(4)] + public PerformanceStat Heat = new PerformanceStat(); + + [InspectableField, JsonProperty("visibility"), Key(5)] + public PerformanceStat Visibility = new PerformanceStat(); + + [InspectableField, JsonProperty("visibilityDecay"), Key(6)] + public PerformanceStat VisibilityDecay = new PerformanceStat(); + + [InspectableField, JsonProperty("burstCount"), Key(7)] + public int BurstCount; + + [InspectableField, JsonProperty("burstTime"), Key(8)] + public PerformanceStat BurstTime = new PerformanceStat(); +} \ No newline at end of file diff --git a/Assets/Scripts/ServerShared/ItemBehaviors/Weapon.cs.meta b/Assets/Scripts/ServerShared/ItemBehaviors/Weapon.cs.meta new file mode 100644 index 000000000..7414ab456 --- /dev/null +++ b/Assets/Scripts/ServerShared/ItemBehaviors/Weapon.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d87bbbe67d6d48cb8f0cca9611985c00 +timeCreated: 1586295838 \ No newline at end of file diff --git a/Assets/Scripts/ServerShared/ItemData.cs b/Assets/Scripts/ServerShared/ItemData.cs index c59b7f1e9..c38c6a33c 100644 --- a/Assets/Scripts/ServerShared/ItemData.cs +++ b/Assets/Scripts/ServerShared/ItemData.cs @@ -6,27 +6,25 @@ using MessagePack; using Newtonsoft.Json; using Unity.Mathematics; -[MessagePackObject] -[Union(0, typeof(SimpleCommodityData))] -[Union(1, typeof(CompoundCommodityData))] -[Union(2, typeof(GearData))] -[Union(3, typeof(HullData))] -[Union(4, typeof(ShieldData))] -[Union(5, typeof(ThrusterData))] -[JsonObject(MemberSerialization.OptIn)] -[JsonConverter(typeof(JsonKnownTypesConverter))] +[MessagePackObject, + Union(0, typeof(SimpleCommodityData)), + Union(1, typeof(CompoundCommodityData)), + Union(2, typeof(GearData)), + Union(3, typeof(HullData)), + JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter))] public abstract class ItemData : DatabaseEntry, INamedEntry { - [InspectableField] [JsonProperty("name")] [Key(1)] + [InspectableField, JsonProperty("name"), Key(1)] public string Name; - [InspectableField] [JsonProperty("mass")] [Key(2)] + [InspectableField, JsonProperty("mass"), Key(2)] public float Mass; - [InspectableField] [JsonProperty("size")] [Key(3)] + [InspectableField, JsonProperty("size"), Key(3)] public float Size; - [InspectableField] [JsonProperty("specificHeat")] [Key(4)] + // Heat needed to change temperature of 1 gram by 1 degree + [InspectableField, JsonProperty("specificHeat"), Key(4)] public float SpecificHeat; [IgnoreMember] public string EntryName @@ -36,61 +34,66 @@ public abstract class ItemData : DatabaseEntry, INamedEntry } } -[RethinkTable("Items")] -[Inspectable] -[MessagePackObject] -public class SimpleCommodityData : ItemData {} - -[MessagePackObject] -[Union(0, typeof(CompoundCommodityData))] -[Union(1, typeof(GearData))] -[Union(2, typeof(HullData))] -[Union(3, typeof(ShieldData))] -[Union(4, typeof(ThrusterData))] -[JsonObject(MemberSerialization.OptIn)] -[JsonConverter(typeof(JsonKnownTypesConverter))] -public abstract class CraftedItemData : ItemData +[RethinkTable("Items"), Inspectable, MessagePackObject] +public class SimpleCommodityData : ItemData { - [InspectableField] [JsonProperty("ingredients")] [Key(5)] - public Dictionary Ingredients = new Dictionary(); + // Types of body where this resource can be found + [InspectableField, JsonProperty("resourceBodyType"), Key(5)] + public BodyType ResourceBodyType; + + // Link to map(s) controlling density of resource, multiplied together when more than one + [InspectableDatabaseLink(typeof(GalaxyMapLayerData)), JsonProperty("resourceDensity"), Key(6)] + public List ResourceDensity = new List(); + + // Controls the bias power variable during resource placement + [InspectableField, JsonProperty("resourceDensityBiasPower"), Key(7)] + public float ResourceDensityBiasPower = 5; + + // Minimum amount of resources needed for presence to register + [InspectableField, JsonProperty("resourceFloor"), Key(8)] + public float ResourceFloor = 10f; } -[RethinkTable("Items")] -[Inspectable] -[MessagePackObject] +[MessagePackObject, + Union(0, typeof(CompoundCommodityData)), + Union(1, typeof(GearData)), + Union(2, typeof(HullData)), + JsonObject(MemberSerialization.OptIn), + JsonConverter(typeof(JsonKnownTypesConverter))] +public abstract class CraftedItemData : ItemData +{ +} + +[RethinkTable("Items"), Inspectable, MessagePackObject] public class CompoundCommodityData : CraftedItemData {} -[Union(0, typeof(GearData))] -[Union(1, typeof(HullData))] -[Union(2, typeof(ShieldData))] -[Union(3, typeof(ThrusterData))] -[JsonObject(MemberSerialization.OptIn)] -[JsonConverter(typeof(JsonKnownTypesConverter))] +[Union(0, typeof(GearData)), + Union(1, typeof(HullData)), + JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter))] public abstract class EquippableItemData : CraftedItemData { + [InspectableField, JsonProperty("draw"), Key(6)] + public PerformanceStat EnergyDraw = new PerformanceStat(); - [InspectableField] [JsonProperty("draw")] [Key(6)] - public PerformanceStat EnergyDraw; - - [InspectableAnimationCurve] [JsonProperty("performanceCurve")] [Key(7)] + [InspectableAnimationCurve, JsonProperty("performanceCurve"), Key(7)] public float4[] HeatPerformanceCurve; - - [TemperatureInspectable] [JsonProperty("minTemp")] [Key(8)] + + [TemperatureInspectable, JsonProperty("minTemp"), Key(8)] public float MinimumTemperature; - - [TemperatureInspectable] [JsonProperty("maxTemp")] [Key(9)] + + [TemperatureInspectable, JsonProperty("maxTemp"), Key(9)] public float MaximumTemperature; - - [InspectableField] [JsonProperty("durability")] [Key(10)] + + [InspectableField, JsonProperty("durability"), Key(10)] public float Durability; - [InspectableField] [JsonProperty("durabilityExponent")] [Key(11)] - public PerformanceStat DurabilityExponent; + [InspectableField, JsonProperty("durabilityExponent"), Key(11)] + public PerformanceStat DurabilityExponent = new PerformanceStat(); - [InspectableField] [JsonProperty("heatExponent")] [Key(12)] - public PerformanceStat HeatExponent; - - [InspectableField] [JsonProperty("behaviors")] [Key(13)] + [InspectableField, JsonProperty("heatExponent"), Key(12)] + public PerformanceStat HeatExponent = new PerformanceStat(); + + [InspectableField, JsonProperty("behaviors"), Key(13)] public List Behaviors = new List(); [IgnoreMember] @@ -125,117 +128,70 @@ public abstract class EquippableItemData : CraftedItemData } } -[RethinkTable("Items")] -[Inspectable] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[RethinkTable("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class GearData : EquippableItemData { - [InspectableField] [JsonProperty("hardpointType")] [Key(14)] public HardpointType Hardpoint; + [InspectableField, JsonProperty("hardpointType"), Key(14)] + public HardpointType Hardpoint; [IgnoreMember] public override HardpointType HardpointType => Hardpoint; } -[RethinkTable("Items")] -[Inspectable] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[RethinkTable("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class HullData : EquippableItemData { - [InspectableField] [JsonProperty("hullCapacity")] [Key(14)] - public PerformanceStat Capacity; + [InspectableField, JsonProperty("hullCapacity"), Key(14)] + public PerformanceStat Capacity = new PerformanceStat(); - [InspectableField] [JsonProperty("traction")] [Key(15)] - public PerformanceStat Traction; + [InspectableField, JsonProperty("traction"), Key(15)] + public PerformanceStat Traction = new PerformanceStat(); - [InspectableField] [JsonProperty("topSpeed")] [Key(16)] - public PerformanceStat TopSpeed; + [InspectableField, JsonProperty("topSpeed"), Key(16)] + public PerformanceStat TopSpeed = new PerformanceStat(); - [InspectableField] [JsonProperty("emissivity")] [Key(17)] - public PerformanceStat Emissivity; + [InspectableField, JsonProperty("emissivity"), Key(17)] + public PerformanceStat Emissivity = new PerformanceStat(); - [InspectableField] [JsonProperty("crossSection")] [Key(18)] - public PerformanceStat CrossSection; + [InspectableField, JsonProperty("crossSection"), Key(18)] + public PerformanceStat CrossSection = new PerformanceStat(); - [InspectableField] [JsonProperty("hardpoints")] [Key(19)] + [InspectableField, JsonProperty("hardpoints"), Key(19)] public List Hardpoints = new List(); - [InspectableAnimationCurve] [JsonProperty("visibility")] [Key(20)] + [InspectableAnimationCurve, JsonProperty("visibility"), Key(20)] public float4[] VisibilityCurve; - [InspectablePrefab] [JsonProperty("prefab")] [Key(21)] + [InspectablePrefab, JsonProperty("prefab"), Key(21)] public string Prefab; [IgnoreMember] public override HardpointType HardpointType => HardpointType.Hull; } -[RethinkTable("Items")] -[InspectableField] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[RethinkTable("Items"), InspectableField, MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class HardpointData { - [JsonProperty("type")] [Key(0)] - public HardpointType Type; + [JsonProperty("type"), Key(0)] public HardpointType Type; } -[RethinkTable("Items")] -[Inspectable] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] -public class ShieldData : EquippableItemData +[MessagePackObject, JsonObject(MemberSerialization.OptIn)] +public class PerformanceStat { - [InspectableField] [JsonProperty("efficiency")] [Key(14)] - public PerformanceStat Efficiency; + [JsonProperty("min"), Key(0)] public float Min; - [InspectableField] [JsonProperty("shielding")] [Key(15)] - public PerformanceStat Shielding; + [JsonProperty("max"), Key(1)] public float Max; - [IgnoreMember] public override HardpointType HardpointType => HardpointType.Shield; -} - -[RethinkTable("Items")] -[Inspectable] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] -public class ThrusterData : EquippableItemData -{ - [InspectableField] [JsonProperty("thrust")] [Key(14)] - public PerformanceStat Thrust; - - [InspectableField] [JsonProperty("torque")] [Key(15)] - public PerformanceStat Torque; - - [InspectableField] [JsonProperty("visibility")] [Key(16)] - public PerformanceStat Visibility; - - [InspectableField] [JsonProperty("thrusterHeat")] [Key(17)] - public PerformanceStat Heat; - - [IgnoreMember] public override HardpointType HardpointType => HardpointType.Thruster; -} - -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] -public struct PerformanceStat -{ - [JsonProperty("min")] [Key(0)] - public float Min; - - [JsonProperty("max")] [Key(1)] - public float Max; - - [JsonProperty("durabilityDependent")] [Key(2)] + [JsonProperty("durabilityDependent"), Key(2)] public bool DurabilityDependent; - - [JsonProperty("heatDependent")] [Key(3)] + + [JsonProperty("heatDependent"), Key(3)] public bool HeatDependent; - - [JsonProperty("qualityExponent")] [Key(4)] + + [JsonProperty("qualityExponent"), Key(4)] public float QualityExponent; - [JsonProperty("ingredient")] [Key(5)] - public Guid? Ingredient; + //[JsonProperty("id"), Key(5)] public Guid ID = Guid.NewGuid(); + + // [JsonProperty("ingredient"), Key(5)] public Guid? Ingredient; [IgnoreMember] private Dictionary> _scaleModifiers; [IgnoreMember] private Dictionary> _constantModifiers; diff --git a/Assets/Scripts/ServerShared/ItemInstance.cs b/Assets/Scripts/ServerShared/ItemInstance.cs index 42a6ef63b..9c17c9cc1 100644 --- a/Assets/Scripts/ServerShared/ItemInstance.cs +++ b/Assets/Scripts/ServerShared/ItemInstance.cs @@ -12,63 +12,50 @@ using Unity.Mathematics; // TODO: USE THIS EVERYWHERE using static Unity.Mathematics.math; -[Union(0, typeof(SimpleCommodity))] -[Union(1, typeof(CompoundCommodity))] -[Union(2, typeof(Gear))] -[JsonObject(MemberSerialization.OptIn)] -[JsonConverter(typeof(JsonKnownTypesConverter))] +[Union(0, typeof(SimpleCommodity)), Union(1, typeof(CompoundCommodity)), Union(2, typeof(Gear)), + JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter))] public abstract class ItemInstance : DatabaseEntry { - [JsonProperty("data")] [Key(1)] - public Guid Data; + [JsonProperty("data"), Key(1)] public Guid Data; public float Mass => Context.GetMass(this); public float HeatCapacity => Context.GetHeatCapacity(this); } -[Union(0, typeof(CompoundCommodity))] -[Union(1, typeof(Gear))] -[JsonObject(MemberSerialization.OptIn)] -[JsonConverter(typeof(JsonKnownTypesConverter))] +[Union(0, typeof(CompoundCommodity)), Union(1, typeof(Gear)), JsonObject(MemberSerialization.OptIn), + JsonConverter(typeof(JsonKnownTypesConverter))] public abstract class CraftedItemInstance : ItemInstance { - [JsonProperty("quality")] [Key(2)] - public float Quality; + [JsonProperty("quality"), Key(2)] public float Quality; - [JsonProperty("ingredients")] [Key(3)] - public List Ingredients = new List(); + [JsonProperty("ingredients"), Key(3)] public List Ingredients = new List(); + + [JsonProperty("blueprint"), Key(4)] public BlueprintData Blueprint; } -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class CompoundCommodity : CraftedItemInstance {} -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class SimpleCommodity : ItemInstance { - [JsonProperty("quantity")] [Key(2)] - public int Quantity; + [JsonProperty("quantity"), Key(2)] public int Quantity; public SimpleCommodityData ItemData => Context.GetData(this); } -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class Gear : CraftedItemInstance { - [JsonProperty("durability")] [Key(4)] - public float Durability; + [JsonProperty("durability"), Key(5)] public float Durability; public EquippableItemData ItemData => Context.GetData(this); } -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class Hardpoint { - [JsonProperty("item")] [Key(0)] - public Gear Item; + [JsonProperty("item"), Key(0)] public Gear Item; [IgnoreMember] public HardpointData HardpointData; } \ No newline at end of file diff --git a/Assets/Scripts/ServerShared/Messages.cs b/Assets/Scripts/ServerShared/Messages.cs index 3a6a214c3..5afff719c 100644 --- a/Assets/Scripts/ServerShared/Messages.cs +++ b/Assets/Scripts/ServerShared/Messages.cs @@ -5,20 +5,11 @@ using LiteNetLib; using MessagePack; using Unity.Mathematics; -[Union(0,typeof(PingMessage))] -[Union(1,typeof(LoginMessage))] -[Union(2,typeof(RegisterMessage))] -[Union(3,typeof(VerifyMessage))] -[Union(4,typeof(ErrorMessage))] -[Union(5,typeof(LoginSuccessMessage))] -[Union(6,typeof(ChatMessage))] -[Union(7,typeof(ChatBroadcastMessage))] -[Union(8,typeof(ChangeNameMessage))] -[Union(9,typeof(GalaxyRequestMessage))] -[Union(10,typeof(GalaxyResponseMessage))] -[Union(11,typeof(ZoneRequestMessage))] -[Union(12,typeof(ZoneResponseMessage))] -[MessagePackObject] +[Union(0, typeof(PingMessage)), Union(1, typeof(LoginMessage)), Union(2, typeof(RegisterMessage)), + Union(3, typeof(VerifyMessage)), Union(4, typeof(ErrorMessage)), Union(5, typeof(LoginSuccessMessage)), + Union(6, typeof(ChatMessage)), Union(7, typeof(ChatBroadcastMessage)), Union(8, typeof(ChangeNameMessage)), + Union(9, typeof(GalaxyRequestMessage)), Union(10, typeof(GalaxyResponseMessage)), + Union(11, typeof(ZoneRequestMessage)), Union(12, typeof(ZoneResponseMessage)), MessagePackObject] public abstract class Message { [IgnoreMember] public NetPeer Peer; diff --git a/Assets/Scripts/ServerShared/Ship.cs b/Assets/Scripts/ServerShared/Ship.cs index ba9e38674..44f960d84 100644 --- a/Assets/Scripts/ServerShared/Ship.cs +++ b/Assets/Scripts/ServerShared/Ship.cs @@ -27,7 +27,9 @@ public class Ship : DatabaseEntry [IgnoreMember] public float Temperature; [IgnoreMember] public float Charge; // [IgnoreMember] public Targetable Target; + [IgnoreMember] public float2 Position; [IgnoreMember] public float2 Direction; + [IgnoreMember] public float2 Velocity; [IgnoreMember] public Dictionary VisibilitySources = new Dictionary(); private HullData _hullData; @@ -51,6 +53,20 @@ public class Ship : DatabaseEntry return null; } + public IEnumerable GetBehaviors() where T : class, IItemBehavior + { + foreach (var behavior in ItemBehaviors) + if (behavior is T b) + yield return b; + } + + public IEnumerable GetBehaviorData() where T : class, IItemBehaviorData + { + foreach (var behavior in ItemBehaviors) + if (behavior.Data is T b) + yield return b; + } + public void AddHeat(float heat) { Temperature += heat / SpecificHeat; @@ -192,4 +208,5 @@ public class Ship : DatabaseEntry // } // // } -} \ No newline at end of file +} + diff --git a/Assets/Scripts/ServerShared/ZoneData.cs b/Assets/Scripts/ServerShared/ZoneData.cs index 672505f56..1968d7152 100644 --- a/Assets/Scripts/ServerShared/ZoneData.cs +++ b/Assets/Scripts/ServerShared/ZoneData.cs @@ -6,33 +6,31 @@ using Newtonsoft.Json; using Unity.Mathematics; using static Unity.Mathematics.math; -[RethinkTable("Galaxy")] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[RethinkTable("Galaxy"), MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class ZoneData : DatabaseEntry, INamedEntry { - [JsonProperty("name")] [Key(1)] + [JsonProperty("name"), Key(1)] public string Name; - - [JsonProperty("position")] [Key(2)] + + [JsonProperty("position"), Key(2)] public float2 Position = 500; - [JsonProperty("wormholes")] [Key(3)] + [JsonProperty("wormholes"), Key(3)] public List Wormholes = new List(); - - [JsonProperty("stations")] [Key(4)] + + [JsonProperty("stations"), Key(4)] public List Stations = new List(); - - [JsonProperty("planets")] [Key(5)] + + [JsonProperty("planets"), Key(5)] public List Planets = new List(); - - [JsonProperty("orbits")] [Key(6)] + + [JsonProperty("orbits"), Key(6)] public List Orbits = new List(); - - [JsonProperty("radius")] [Key(7)] + + [JsonProperty("radius"), Key(7)] public float Radius = 2000; - [JsonProperty("visited")] [Key(8)] + [JsonProperty("visited"), Key(8)] public bool Visited; [IgnoreMember] public string EntryName @@ -42,31 +40,29 @@ public class ZoneData : DatabaseEntry, INamedEntry } } -[RethinkTable("Galaxy")] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[RethinkTable("Galaxy"), MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class Station : DatabaseEntry, INamedEntry { - [JsonProperty("name")] [Key(1)] + [JsonProperty("name"), Key(1)] public string Name; // Can be Planet or Orbit - [JsonProperty("parent")] [Key(2)] + [JsonProperty("parent"), Key(2)] public Guid Parent; - [JsonProperty("owner")] [Key(3)] + [JsonProperty("owner"), Key(3)] public Guid Owner; - [JsonProperty("inventory")] [Key(4)] + [JsonProperty("inventory"), Key(4)] public List Inventory = new List(); - [JsonProperty("buying")] [Key(5)] + [JsonProperty("buying"), Key(5)] public Dictionary BuyPrices = new Dictionary(); - [JsonProperty("selling")] [Key(6)] + [JsonProperty("selling"), Key(6)] public Dictionary SellPrices = new Dictionary(); - - [JsonProperty("zone")] [Key(7)] + + [JsonProperty("zone"), Key(7)] public Guid Zone; [IgnoreMember] public string EntryName @@ -76,25 +72,26 @@ public class Station : DatabaseEntry, INamedEntry } } -[RethinkTable("Galaxy")] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[RethinkTable("Galaxy"), MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class PlanetData : DatabaseEntry, INamedEntry { - [JsonProperty("name")] [Key(1)] + [JsonProperty("name"), Key(1)] public string Name; - - [JsonProperty("orbit")] [Key(2)] + + [JsonProperty("orbit"), Key(2)] public Guid Orbit; - - [JsonProperty("mass")] [Key(3)] + + [JsonProperty("mass"), Key(3)] public float Mass; - - [JsonProperty("zone")] [Key(4)] + + [JsonProperty("zone"), Key(4)] public Guid Zone; - - [JsonProperty("belt")] [Key(5)] + + [JsonProperty("belt"), Key(5)] public bool Belt; + + [JsonProperty("resources"), Key(5)] + public Dictionary Resources = new Dictionary(); // [JsonProperty("radius")] [Key(5)] // public float GravityRadius; @@ -106,24 +103,22 @@ public class PlanetData : DatabaseEntry, INamedEntry } } -[RethinkTable("Galaxy")] -[MessagePackObject] -[JsonObject(MemberSerialization.OptIn)] +[RethinkTable("Galaxy"), MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class OrbitData : DatabaseEntry { - [JsonProperty("parent")] [Key(1)] + [JsonProperty("parent"), Key(1)] public Guid Parent; - - [JsonProperty("distance")] [Key(2)] + + [JsonProperty("distance"), Key(2)] public float Distance; - - [JsonProperty("phase")] [Key(3)] + + [JsonProperty("phase"), Key(3)] public float Phase; - - [JsonProperty("period")] [Key(4)] + + [JsonProperty("period"), Key(4)] public float Period; - - [JsonProperty("zone")] [Key(5)] + + [JsonProperty("zone"), Key(5)] public Guid Zone; public static float2 Evaluate(float phase) diff --git a/Assets/Scripts/ServerShared/ZoneGenerator.cs b/Assets/Scripts/ServerShared/ZoneGenerator.cs index 8584511cd..620c0650d 100644 --- a/Assets/Scripts/ServerShared/ZoneGenerator.cs +++ b/Assets/Scripts/ServerShared/ZoneGenerator.cs @@ -12,25 +12,27 @@ using Random = Unity.Mathematics.Random; public class ZoneGenerator { -// public float BinaryFloor = 100; -// public float BinaryProbability = .1f; -// public float MassPowerMinimum = 1.35f; -// public float MassPowerMaximum = 1.75f; -// public float DistancePowerMinimum = 1.35f; -// public float DistancePowerMaximum = 1.75f; -// public float Radius = 500; -// public float Mass = 100000; -// public float MassFloor = 1; -// public float SunMass = 10000; -// public float GasGiantMass = 2000; -// public float RadiusPower = 1.75f; - public static void GenerateZone(GlobalData global, ZoneData zone, GalaxyMapLayerData mass, GalaxyMapLayerData radius, out OrbitData[] orbitData, out PlanetData[] planetData) + public static void GenerateZone( + GlobalData global, + ZoneData zone, + IEnumerable mapLayers, + IEnumerable resources, + out OrbitData[] orbitData, + out PlanetData[] planetsData) { - var zoneRadius = lerp(global.MinimumZoneRadius, global.MaximumZoneRadius, radius.Evaluate(zone.Position, global)); + var zoneRadius = lerp(global.MinimumZoneRadius, + global.MaximumZoneRadius, + mapLayers.First(m => m.Name == "Radius") + .Evaluate(zone.Position, + global)); zone.Radius = zoneRadius; - var zoneMass = lerp(global.MinimumZoneMass, global.MaximumZoneMass, mass.Evaluate(zone.Position, global)); + var zoneMass = lerp(global.MinimumZoneMass, + global.MaximumZoneMass, + mapLayers.First(m => m.Name == "Mass") + .Evaluate(zone.Position, + global)); //Debug.Log($"Generating zone at position {zone.Position} with radius {zoneRadius} and mass {zoneMass}"); @@ -62,21 +64,45 @@ public class ZoneGenerator ? orbitMap[orbitInverseMap[data].Parent].ID : Guid.Empty; - planetData = planets.Where(p=>!p.Empty).Select(planet => + // Cache resource densities + var resourceMaps = mapLayers.ToDictionary(m => m.ID, m => m.Evaluate(zone.Position, global)); + + var random = new Random(); + + planetsData = planets.Where(p=>!p.Empty).Select(planet => { - var planetDatum = new PlanetData + var planetData = new PlanetData { Mass = planet.Mass, ID = Guid.NewGuid(), Orbit = orbitMap[planet].ID, Zone = zone.ID, - Belt = planet.Belt + Belt = planet.Belt, + Resources = resources + // Filter resources where the body type matches the current planet + .Where(r => + ((planet.Belt ? BodyType.Asteroid : + planet.Mass > global.SunMass ? BodyType.Sun : + planet.Mass > global.GasGiantMass ? BodyType.GasGiant : + planet.Mass > global.PlanetMass ? BodyType.Planet : BodyType.Planetoid) & r.ResourceBodyType) != 0) + // NextUnbounded is our extension function containing resource placement formula + // Obtain bias variable by multiplying all resource maps together + .Select(r => new + { + resource = r, + quantity = random.NextUnbounded( + r.ResourceDensity.Aggregate(1f, (m, rdm) => m * resourceMaps[rdm]), + r.ResourceDensityBiasPower) + }) + // Only include resources above a minimum quantity + .Where(r => r.resource.ResourceFloor < r.quantity) + .ToDictionary(r => r.resource.ID, r => r.quantity) }; - planetDatum.Name = planetDatum.ID.ToString().Substring(0, 8); - return planetDatum; + planetData.Name = planetData.ID.ToString().Substring(0, 8); + return planetData; }).ToArray(); - zone.Planets = planetData.Select(pd => pd.ID).ToList(); + zone.Planets = planetsData.Select(pd => pd.ID).ToList(); zone.Orbits = orbitData.Select(od => od.ID).ToList(); } @@ -105,7 +131,7 @@ public class ZoneGenerator // Create a small number of less massive "captured" planets orbiting past the rosette root.ExpandSolar( - count: random.NextInt(1,5), + count: (int)(random.NextFloat(1, 3) * random.NextFloat(1, 2)), massMulMin: .6f, massMulMax: .8f, distMulMin: 1.25f, @@ -119,7 +145,7 @@ public class ZoneGenerator var m = p.Mass / averageChildMass; // Give each child in the rosette its own mini solar system p.ExpandSolar( - count: (int) (m * 5), + count: (int) (random.NextFloat() * random.NextFloat() * m * 5 + 1), massMulMin: 0.75f, massMulMax: 2.5f, distMulMin: 1 + m * .25f, diff --git a/Assets/Scripts/StrategyGameManager.cs b/Assets/Scripts/StrategyGameManager.cs index 7a7880efb..a3b8740aa 100644 --- a/Assets/Scripts/StrategyGameManager.cs +++ b/Assets/Scripts/StrategyGameManager.cs @@ -67,7 +67,7 @@ public class StrategyGameManager : MonoBehaviour _galaxy = galaxy; _galaxyResponseZones = _galaxy.Zones.ToDictionary(z => z.ZoneID); _cache.Add(_galaxy.GlobalData, true); - _context = new GameContext(_cache); + _context = new GameContext(_cache, Debug.Log); if (_currentTab == GalaxyTabButton && !_galaxyPopulated) PopulateGalaxy(); }); @@ -142,7 +142,7 @@ public class StrategyGameManager : MonoBehaviour { var orbitData = _cache.Get(orbit); _orbitPositions[orbit] = GetOrbitPosition(orbitData.Parent) + (orbitData.Period < .01f ? float2.zero : - OrbitData.Evaluate(Time.time / orbitData.Period + orbitData.Phase) * + OrbitData.Evaluate(Time.time / -orbitData.Period + orbitData.Phase) * orbitData.Distance); } diff --git a/Assets/Scripts/Targetable.cs b/Assets/Scripts/Targetable.cs deleted file mode 100644 index f787f4c3f..000000000 --- a/Assets/Scripts/Targetable.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using static Unity.Mathematics.math; - -public class Targetable : MonoBehaviour -{ - public float Points = 100; - public float Visibility; - public Transform ReplaceWithPrefab; - public Ship Ship; - - public IsFriendlyFoeStatus DefaultIsFriendlyFoeStatus = IsFriendlyFoeStatus.None; - - public readonly Dictionary IFF = new Dictionary(); - private Vector3 _lastPosition; - - public IsFriendlyFoeStatus IsFriendlyFoe(Targetable target) - { - if (!IFF.ContainsKey(target)) - IFF[target] = DefaultIsFriendlyFoeStatus; - - return IFF[target]; - } - - void Start() - { - } - - void Health(float health) - { - Points = health; - } - - public void Damage(float points) - { - if (Ship != null) - { - var shield = Ship.GetEquipped(HardpointType.Shield); - if (shield != null) - { - var shieldData = shield.ItemData as ShieldData; - var shieldedDamage = points * saturate(Ship.Context.Evaluate(shieldData.Shielding, shield, Ship)); - Ship.AddHeat(shieldedDamage / Ship.Context.Evaluate(shieldData.Efficiency, shield, Ship)); - Ship.Hull.Durability -= points - shieldedDamage; - } - else Ship.Hull.Durability -= points; - } - else - { - Points -= points; - - if (Points > 0) return; - - KillLocal(); - } - /* - var ent = GameManager.Instance.Entities.FirstOrDefault(kv => kv.Value == transform).Key; - if(ent>0) - GameManager.Instance.Send("Destroy", ent);*/ - - } - - public void KillLocal() - { - //GameManager.Instance.Kill(this); -// if (GetComponent()) -// { -// GameManager.Instance.KillPlayer(); -// } - - Destroy(gameObject); - - if (ReplaceWithPrefab != null) - Instantiate(ReplaceWithPrefab, transform.position, transform.rotation); - } - - private void LateUpdate() - { - _lastPosition = transform.position; - } - - void kill(string[] args) - { - if(args[0]==gameObject.name) - KillLocal(); - } -} - - -public enum IsFriendlyFoeStatus -{ - None, - Friendly, - Hostile, - Mayday, - Body, - Wormhole -} \ No newline at end of file diff --git a/Assets/Scripts/ZoneGeneratorTest.cs b/Assets/Scripts/ZoneGeneratorTest.cs index 8800c3915..c58bd8ffa 100644 --- a/Assets/Scripts/ZoneGeneratorTest.cs +++ b/Assets/Scripts/ZoneGeneratorTest.cs @@ -57,7 +57,7 @@ public class ZoneGeneratorTest : MonoBehaviour void Start() { _cache = new DatabaseCache(); - _context = new GameContext(_cache); + _context = new GameContext(_cache, Debug.Log); _boundaryMaterial = ZoneBoundary.material; } @@ -105,10 +105,10 @@ public class ZoneGeneratorTest : MonoBehaviour ZoneGenerator.GenerateZone( global: Galaxy.MapData.GlobalData, zone: zone, - mass: Galaxy.MapData.ResourceDensities.First(m=>m.Name=="Mass"), - radius: Galaxy.MapData.ResourceDensities.First(m=>m.Name=="Radius"), + mapLayers: Galaxy.MapData.ResourceDensities, + resources: Array.Empty(), orbitData: out orbits, - planetData: out planets); + planetsData: out planets); _cache.AddAll(orbits); _cache.AddAll(planets); _cache.Add(zone); diff --git a/Economy.Server/Program.cs b/Economy.Server/Program.cs index 7688aaab0..5363ce89c 100644 --- a/Economy.Server/Program.cs +++ b/Economy.Server/Program.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; +using System.Reactive.Concurrency; +using System.Reactive.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; @@ -11,6 +13,7 @@ using MessagePack.Resolvers; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using RethinkDb.Driver; +using RethinkDb.Driver.Ast; using RethinkDb.Driver.Net; using Serilog; using ILogger = Microsoft.Extensions.Logging.ILogger; @@ -118,7 +121,9 @@ namespace ChatApp.Server }; server.Start(); - var context = new GameContext(cache); + var context = new GameContext(cache, s=>_logger.Log(LogLevel.Information, s)); + + var mapLayers = cache.GetAll().ToDictionary(m => m.Name); server.AddMessageListener(galaxyRequest => galaxyRequest.Peer.Send( new GalaxyResponseMessage @@ -132,7 +137,7 @@ namespace ChatApp.Server Links = zd.Wormholes?.ToArray() ?? Array.Empty() }).ToArray(), GlobalData = context.GlobalData, - StarDensity = cache.Get(context.GlobalData.MapLayers["StarDensity"]) + StarDensity = mapLayers["StarDensity"] })); server.AddMessageListener(zoneRequest => @@ -148,10 +153,10 @@ namespace ChatApp.Server ZoneGenerator.GenerateZone( global: context.GlobalData, zone: zone, - mass: cache.Get(context.GlobalData.MapLayers["Mass"]), - radius: cache.Get(context.GlobalData.MapLayers["Radius"]), + mapLayers: mapLayers.Values, + resources: cache.GetAll(), orbitData: out orbits, - planetData: out planets); + planetsData: out planets); cache.AddAll(orbits); cache.AddAll(planets); cache.Add(zone); @@ -166,6 +171,11 @@ namespace ChatApp.Server }); }); + Observable.Timer(DateTimeOffset.Now, TimeSpan.FromSeconds(60)).SubscribeOn(NewThreadScheduler.Default).Subscribe(_ => + { + _logger.Log(LogLevel.Information, R.Now().Run(connection).ToString() as string); + }); + while (true) { Thread.Sleep(100); diff --git a/Economy.Server/bin/Debug/netcoreapp3.1/Economy.Server.dll b/Economy.Server/bin/Debug/netcoreapp3.1/Economy.Server.dll index 250f89358..d3658a10a 100644 --- a/Economy.Server/bin/Debug/netcoreapp3.1/Economy.Server.dll +++ b/Economy.Server/bin/Debug/netcoreapp3.1/Economy.Server.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:55362430e15cdc89c54b9cd50fbfa54e286a1cedc5f81dbd05a8d309c1c83f48 -size 28672 +oid sha256:cb4987c613ea604ad611ab5fb4859f86abd88ca3d9c9686057f197e030f88724 +size 30208 diff --git a/Economy.Server/bin/Debug/netcoreapp3.1/Economy.Shared.dll b/Economy.Server/bin/Debug/netcoreapp3.1/Economy.Shared.dll index 037b6e0de..9206cb340 100644 --- a/Economy.Server/bin/Debug/netcoreapp3.1/Economy.Shared.dll +++ b/Economy.Server/bin/Debug/netcoreapp3.1/Economy.Shared.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85174ebd9f2cf8d1d598bf287911aa15b1cdaca148a0a107a336a2118847ea63 +oid sha256:12df2dbc0f0a418429b9f6f6810e583ece9a361c508e3ba60cb70b7c8d04c2fe size 1397248 diff --git a/Economy.Server/obj/Debug/netcoreapp3.1/Economy.Server.csprojAssemblyReference.cache b/Economy.Server/obj/Debug/netcoreapp3.1/Economy.Server.csprojAssemblyReference.cache index 32b2ddc17bcb535371ed57af14ce02224855c6fe..80168d2674d28c44ca951f7491fff32a00a9b3b6 100644 GIT binary patch literal 107728 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 literal 108033 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 + @@ -74,6 +75,10 @@ + + + + @@ -673,9 +678,18 @@ C:/Program Files/Unity/Hub/Editor/2018.4.17f1/Editor/Data/PlaybackEngines/windowsstandalonesupport/UnityEditor.WindowsStandalone.Extensions.dll + + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Microsoft.Extensions.Logging.Abstractions.dll + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Microsoft.SqlServer.Types.dll + + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Newtonsoft.Json.dll + + + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Remotion.Linq.dll + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/System.Buffers.dll @@ -700,15 +714,6 @@ C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.dll - - C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Newtonsoft.Json.dll - - - C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Microsoft.Extensions.Logging.Abstractions.dll - - - C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Remotion.Linq.dll - C:/Program Files/Unity/Hub/Editor/2018.4.17f1/Editor/Data/MonoBleedingEdge/lib/mono/4.7.1-api/mscorlib.dll diff --git a/Economy.Shared/bin/Debug/netstandard2.0/Economy.Shared.dll b/Economy.Shared/bin/Debug/netstandard2.0/Economy.Shared.dll index 037b6e0de..9206cb340 100644 --- a/Economy.Shared/bin/Debug/netstandard2.0/Economy.Shared.dll +++ b/Economy.Shared/bin/Debug/netstandard2.0/Economy.Shared.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85174ebd9f2cf8d1d598bf287911aa15b1cdaca148a0a107a336a2118847ea63 +oid sha256:12df2dbc0f0a418429b9f6f6810e583ece9a361c508e3ba60cb70b7c8d04c2fe size 1397248 diff --git a/Economy.Shared/obj/Debug/netstandard2.0/Economy.Shared.dll b/Economy.Shared/obj/Debug/netstandard2.0/Economy.Shared.dll index 037b6e0de..9206cb340 100644 --- a/Economy.Shared/obj/Debug/netstandard2.0/Economy.Shared.dll +++ b/Economy.Shared/obj/Debug/netstandard2.0/Economy.Shared.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85174ebd9f2cf8d1d598bf287911aa15b1cdaca148a0a107a336a2118847ea63 +oid sha256:12df2dbc0f0a418429b9f6f6810e583ece9a361c508e3ba60cb70b7c8d04c2fe size 1397248 diff --git a/MessagePack.csproj b/MessagePack.csproj index aba5e2994..4c4ba2dcd 100644 --- a/MessagePack.csproj +++ b/MessagePack.csproj @@ -387,9 +387,18 @@ C:/Program Files/Unity/Hub/Editor/2018.4.17f1/Editor/Data/PlaybackEngines/windowsstandalonesupport/UnityEditor.WindowsStandalone.Extensions.dll + + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Microsoft.Extensions.Logging.Abstractions.dll + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Microsoft.SqlServer.Types.dll + + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Newtonsoft.Json.dll + + + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Remotion.Linq.dll + C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/System.Buffers.dll @@ -414,15 +423,6 @@ C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.dll - - C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Newtonsoft.Json.dll - - - C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Microsoft.Extensions.Logging.Abstractions.dll - - - C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Remotion.Linq.dll - C:/Program Files/Unity/Hub/Editor/2018.4.17f1/Editor/Data/MonoBleedingEdge/lib/mono/4.7.1-api/mscorlib.dll