instead of Entity[]. Use the command line tool `MigrationAssistant.exe` to automatically migrate.
+
+```
+$ mono MigrationAssistant.exe
+usage:
+[-l] - print all available versions
+[version] [path] - apply migration of version [version] to source files located at [path]
+
+$ mono MigrationAssistant.exe -l
+0.18.0 - Migrates IReactiveSystem API
+0.19.0 - Migrates IReactiveSystem.Execute
+
+// Example from Math-One example project, where all the systems are located in the Features folder
+$ mono MigrationAssistant.exe 0.19.0 /Path/To/Project/Assets/Sources/Features
+```
+
+---
+
+Entitas 0.18.0 upgrade guide
+============================
+
+Entitas 0.18.0 changes IReactiveSystem. To upgrade your source files, follow these steps
+- Install Entitas 0.18.0 (which will result in compiler errors)
+- Use the command line tool `MigrationAssistant.exe` to automatically migrate
+
+```
+$ mono MigrationAssistant.exe
+usage:
+[-l] - print all available versions
+[version] [path] - apply migration of version [version] to source files located at [path]
+
+$ mono MigrationAssistant.exe -l
+0.18.0 - Migrates IReactiveSystem API
+
+// Example from Math-One example project, where all the systems are located in the Features folder
+$ mono MigrationAssistant.exe 0.18.0 /Path/To/Project/Assets/Sources/Features
+```
+
+---
+
+Entitas 0.12.0 upgrade guide
+============================
+
+Entitas 0.12.0 generates prefixed matchers based on the PoolAttribute and introduces some
+API changes. In your existing project with a Entitas version < 0.12.0 manually rename the
+following classes and methods.
+
+## Before installing Entitas 0.12.0
+
+#### Rename
+
+ pool.CreateSystem() -> pool.CreateExecuteSystem()
+
+Now that you're prepared for integrating the latest version, delete your existing version
+of Entitas, EntitasCodeGenerator and EntitasUnity.
+
+#### Delete
+
+ Entitas
+ EntitasCodeGenerator
+ EntitasUnity
+
+## Install Entitas 0.12.0
+
+#### Setup Entitas Preferences
+
+ Open the Unity preference panel and select Entitas. Check and update the path to the folder where
+ the code generator will save all generated files. If you are using the PoolAttribute in your components,
+ add all custom pool names used in your application. Make sure that all existing custom PoolAttributes call
+ the base constructor with the same name as the class (without 'Attribute').
+ If you are not using the PoolAttribute in your components, you can skip this process.
+
+```cs
+using Entitas.CodeGenerator;
+
+public class CoreGameAttribute : PoolAttribute {
+ public CoreGameAttribute() : base("CoreGame") {
+ }
+}
+```
+
+#### Code Generator
+
+ Use the code generator and generate
+
+#### Update API
+
+ Click the MenuItem "Entitas/Update API". All occurrences of the old Matcher will be updated
+ to the new version, which is prefixed based on the PoolAttribute.
+
+#### Delete
+
+ Delete all custom PoolAttributes
+
+---
+
+Entitas 0.10.0 upgrade guide
+============================
+
+Beside features, Entitas 0.10.0 includes lots of renaming. If your current Entitas
+version is < 0.10.0, you might want to follow the next few simple renaming steps,
+to speed up the integration of the latest version of Entitas.
+In your existing project with a Entitas version < 0.10.0 manually rename the following
+classes and methods.
+
+## Before installing Entitas 0.10.0
+
+#### Rename
+
+ EntityRepository -> Pool
+ EntityRepository.GetCollection() -> Pool.GetGroup()
+
+ EntityCollection -> Group
+ EntityCollection.EntityCollectionChange -> Group.GroupChanged
+
+ EntityRepositoryObserver -> GroupObserver
+ EntityRepositoryObserver.EntityCollectionEventType -> GroupObserver.GroupEventType
+
+ IEntityMatcher -> IMatcher
+ IEntitySystem -> IExecuteSystem
+ AllOfEntityMatcher -> AllOfMatcher
+ EntityRepositoryAttribute -> PoolAttribute
+ IReactiveSubEntitySystem -> IReactiveSystem
+ ReactiveEntitySystem -> ReactiveSystem
+
+#### Delete
+
+ EntityWillBeRemovedEntityRepositoryObserver -> DELETE
+ IReactiveSubEntityWillBeRemovedSystem -> DELETE
+ ReactiveEntityWillBeRemovedSystem -> DELETE
+
+Now that you're prepared for integrating the latest version, delete your existing version
+of Entitas, EntitasCodeGenerator and ToolKit.
+
+#### Delete
+
+ Entitas
+ EntitasCodeGenerator
+ ToolKit (unless you use classes from ToolKit. The new version of Entitas doesn't depend on ToolKit anymore)
+
+
+## Install Entitas 0.10.0
+
+#### Fix remaining issues
+
+ IReactiveSubEntityWillBeRemovedSystem
+ - Consider implementing ISystem & ISetPool and use group.OnEntityWillBeRemoved += foobar;
+
+#### Code Generator
+
+ Use the code generator and generate
diff --git a/Assets/Plugins/Entitas/EntitasUpgradeGuide.md.meta b/Assets/Plugins/Entitas/EntitasUpgradeGuide.md.meta
new file mode 100644
index 0000000..4936369
--- /dev/null
+++ b/Assets/Plugins/Entitas/EntitasUpgradeGuide.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 215bbb6ffba38d64ea0e2821628dd20d
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/Entitas/LICENSE.txt b/Assets/Plugins/Entitas/LICENSE.txt
new file mode 100644
index 0000000..97175fb
--- /dev/null
+++ b/Assets/Plugins/Entitas/LICENSE.txt
@@ -0,0 +1,22 @@
+The MIT License
+
+Copyright (c) 2014 - 2018 Simon Schmid
+
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/Assets/Plugins/Entitas/LICENSE.txt.meta b/Assets/Plugins/Entitas/LICENSE.txt.meta
new file mode 100644
index 0000000..bda16dd
--- /dev/null
+++ b/Assets/Plugins/Entitas/LICENSE.txt.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 4dbed025e0f8f3d40ac1843618048915
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/Entitas/README.md b/Assets/Plugins/Entitas/README.md
new file mode 100644
index 0000000..f61bad5
--- /dev/null
+++ b/Assets/Plugins/Entitas/README.md
@@ -0,0 +1,202 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Entitas is free, but powered by
+
+ your donations
+
+
+
+Entitas - The Entity Component System Framework for C# and Unity
+================================================================
+
+Entitas is a super fast Entity Component System Framework (ECS) specifically made for C# and Unity. Internal caching and blazing fast component access makes it second to none. Several design decisions have been made to work optimal in a garbage collected environment and to go easy on the garbage collector. Entitas comes with an optional code generator which radically reduces the amount of code you have to write and [makes your code read like well written prose.][clean-coders]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+### **[» Download](#download-entitas)**
+### **[» Documentation][documentation]**
+### **[» Ask a question][issues-new]**
+### **[» Wiki and example projects][wiki]**
+### **[» #madeWithEntitas][wiki-games-and-examples]**
+
+---
+
+Video Tutorials & Unity Unite Talks
+=================
+
+| Entitas ECS Unity Tutorial | Entitas ECS Unity Tutorial | Entity system architecture with Unity | ECS architecture with Unity by example |
+|:---------------------------------:|:---------------------------------:|:--------------------------------------------------------------------:|:--------------------------------------------------------------------:|
+| [![Shmup1][shmup1-thumb]][shmup1] | [![Shmup2][shmup2-thumb]][shmup2] | [![Unite 15][unite15-thumb]][unite15] | [![Unite 16][unite16-thumb]][unite16] |
+| Setup & Basics | Git & Unit Tests | [» Open the slides on SlideShare: Unite Europe 2015][unite15-slides] | [» Open the slides on SlideShare: Unite Europe 2016][unite16-slides] |
+
+
+First glimpse
+=============
+
+The optional [code generator][wiki-code-generator] lets you write code that is super fast, safe and literally screams its intent.
+
+```csharp
+public static GameEntity CreateRedGem(this GameContext context, Vector3 position) {
+ var entity = context.CreateEntity();
+ entity.isGameBoardElement = true;
+ entity.isMovable = true;
+ entity.AddPosition(position);
+ entity.AddAsset("RedGem");
+ entity.isInteractive = true;
+ return entity;
+}
+```
+
+```csharp
+var entities = context.GetEntities(Matcher.AllOf(GameMatcher.Position, GameMatcher.Velocity));
+foreach(var e in entities) {
+ var pos = e.position;
+ var vel = e.velocity;
+ e.ReplacePosition(pos.value + vel.value);
+}
+```
+
+
+Overview
+========
+
+Entitas is fast, light and gets rid of unnecessary complexity. There are less than a handful classes you have to know to rocket start your game or application:
+
+- Entity
+- Context
+- Group
+- Entity Collector
+
+[Read more...][wiki-overview]
+
+
+Code Generator
+==============
+
+The Code Generator generates classes and methods for you, so you can focus on getting the job done. It radically reduces the amount of code you have to write and improves readability by a huge magnitude. It makes your code less error-prone while ensuring best performance. I strongly recommend using it!
+
+[Read more...][wiki-code-generator]
+
+
+Unity integration
+=================
+
+The optional Unity module integrates Entitas nicely into Unity and provides powerful editor extensions to inspect and debug contexts, groups, entities, components and systems.
+
+[Read more...][wiki-unity-integration]
+
+
+
+
+
+
+
+
+Entitas deep dive
+=================
+
+[Read the wiki][wiki] or checkout the [example projects][wiki-example-projects] to see Entitas in action. These example projects illustrate how systems, groups, collectors and entities all play together seamlessly.
+
+
+Download Entitas
+================
+
+Each release is published with zip files containing all source files you need.
+
+[Show releases][releases]
+
+
+Thanks to
+=========
+
+Big shout out to [@mzaks][github-mzaks], [@cloudjubei][github-cloudjubei] and [@devboy][github-devboy] for endless hours of discussion and helping making Entitas awesome!
+
+
+Maintainer(s)
+=============
+
+- [@sschmid][github-sschmid] | [@s_schmid][twitter-sschmid] | [@entitas_csharp][twitter-entitas_csharp]
+
+
+Different language?
+===================
+
+Entitas is available in
+- [C#](https://github.com/sschmid/Entitas-CSharp)
+- [Swift](https://github.com/mzaks/Entitas-Swift)
+- [C++](https://github.com/JuDelCo/Entitas-Cpp)
+- [Objective-C](https://github.com/wooga/entitas)
+- [Java](https://github.com/Rubentxu/entitas-java)
+- [Python](https://github.com/Aenyhm/entitas-python)
+- [Scala](https://github.com/darkoverlordofdata/entitas-scala)
+- [Go](https://github.com/wooga/go-entitas)
+- [F#](https://github.com/darkoverlordofdata/entitas-fsharp)
+- [TypeScript](https://github.com/darkoverlordofdata/entitas-ts)
+- [Kotlin](https://github.com/darkoverlordofdata/entitas-kotlin)
+- [Haskell](https://github.com/mhaemmerle/entitas-haskell)
+- [Erlang](https://github.com/mhaemmerle/entitas_erl)
+- [Clojure](https://github.com/mhaemmerle/entitas-clj)
+
+
+[clean-coders]: https://cleancoders.com "Clean Coders"
+
+[documentation]: http://sschmid.github.io/Entitas-CSharp/ "Entitas Documentation"
+[wiki]: https://github.com/sschmid/Entitas-CSharp/wiki "Entitas Wiki"
+[wiki-code-generator]: https://github.com/sschmid/Entitas-CSharp/wiki/Code-Generator "Wiki - Code Generator"
+[wiki-overview]: https://github.com/sschmid/Entitas-CSharp/wiki/Overview "Wiki - Overview"
+[wiki-unity-integration]: https://github.com/sschmid/Entitas-CSharp/wiki/Unity-integration "Wiki - Unity Integration"
+[wiki-example-projects]: https://github.com/sschmid/Entitas-CSharp/wiki/Example-projects "Wiki - Example Projects"
+[wiki-games-and-examples]: https://github.com/sschmid/Entitas-CSharp/wiki/Made-With-Entitas "Wiki - #madeWithEntitas"
+
+[shmup1-thumb]: https://raw.githubusercontent.com/sschmid/Entitas-CSharp/master/Readme/Images/Entitas-Shmup-Part-1.jpg "Video: Entitas - Shmup - Part 1"
+[shmup1]: https://www.youtube.com/watch?v=L-18XRTarOM "Video: Entitas - Shmup - Part 1"
+[shmup2-thumb]: https://raw.githubusercontent.com/sschmid/Entitas-CSharp/master/Readme/Images/Entitas-Shmup-Part-2.jpg "Video: Entitas - Shmup - Part 2"
+[shmup2]: https://www.youtube.com/watch?v=DZpvUnj2dGI "Video: Entitas - Shmup - Part 2"
+[unite15-thumb]: https://raw.githubusercontent.com/sschmid/Entitas-CSharp/master/Readme/Images/UniteEurope2015-Video.png "Video: Watch the Entitas Talk at Unite Europe 2015"
+[unite15]: https://www.youtube.com/watch?v=Re5kGtxTW6E "Video: Watch the Entitas Talk at Unite Europe 2015"
+[unite15-slides]: http://www.slideshare.net/sschmid/uniteeurope-2015 "SlideShare: Unite Europe 2015"
+[unite16-thumb]: https://raw.githubusercontent.com/sschmid/Entitas-CSharp/master/Readme/Images/UniteEurope2016-Video.png "Video: Watch the Entitas Talk at Unite Europe 2016"
+[unite16]: https://www.youtube.com/watch?v=Phx7IJ3XUzg "Video: Watch the Entitas Talk at Unite Europe 2016"
+[unite16-slides]: http://www.slideshare.net/sschmid/uniteeurope-2016 "SlideShare: Unite Europe 2016"
+
+[releases]: https://github.com/sschmid/Entitas-CSharp/releases "Releases"
+[issues-new]: https://github.com/sschmid/Entitas-CSharp/issues/new "New issue"
+
+[twitter-sschmid]: https://twitter.com/s_schmid "s_schmid on Twitter"
+[twitter-entitas_csharp]: https://twitter.com/entitas_csharp "entitas_csharp on Twitter"
+
+[github-sschmid]: https://github.com/sschmid "@sschmid"
+[github-mzaks]: https://github.com/mzaks "@mzaks"
+[github-cloudjubei]: https://github.com/cloudjubei "@cloudjubei"
+[github-devboy]: https://github.com/devboy "@devboy"
diff --git a/Assets/Plugins/Entitas/README.md.meta b/Assets/Plugins/Entitas/README.md.meta
new file mode 100644
index 0000000..38940fa
--- /dev/null
+++ b/Assets/Plugins/Entitas/README.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 59e907356184a344d9e1402d1c2a33a1
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/Generators.dll b/Assets/Plugins/Generators.dll
new file mode 100644
index 0000000..71c89de
Binary files /dev/null and b/Assets/Plugins/Generators.dll differ
diff --git a/Assets/Plugins/Generators.dll.meta b/Assets/Plugins/Generators.dll.meta
new file mode 100644
index 0000000..c5b10b0
--- /dev/null
+++ b/Assets/Plugins/Generators.dll.meta
@@ -0,0 +1,33 @@
+fileFormatVersion: 2
+guid: 7b096a7023b1a654fbde83161695f15d
+PluginImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ iconMap: {}
+ executionOrder: {}
+ defineConstraints: []
+ isPreloaded: 0
+ isOverridable: 0
+ isExplicitlyReferenced: 0
+ validateReferences: 1
+ platformData:
+ - first:
+ Any:
+ second:
+ enabled: 1
+ settings: {}
+ - first:
+ Editor: Editor
+ second:
+ enabled: 0
+ settings:
+ DefaultValueInitialized: true
+ - first:
+ Windows Store Apps: WindowsStoreApps
+ second:
+ enabled: 0
+ settings:
+ CPU: AnyCPU
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/NetStack.meta b/Assets/Plugins/NetStack.meta
new file mode 100644
index 0000000..becd6e2
--- /dev/null
+++ b/Assets/Plugins/NetStack.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 6aecf72e86861334386d9c8b5673bd02
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/NetStack/NetStack.Compression.meta b/Assets/Plugins/NetStack/NetStack.Compression.meta
new file mode 100644
index 0000000..bbb005a
--- /dev/null
+++ b/Assets/Plugins/NetStack/NetStack.Compression.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: e37f991919e66724ca83bbbe8dae2588
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/NetStack/NetStack.Compression/BoundedRange.cs b/Assets/Plugins/NetStack/NetStack.Compression/BoundedRange.cs
new file mode 100644
index 0000000..44d98bc
--- /dev/null
+++ b/Assets/Plugins/NetStack/NetStack.Compression/BoundedRange.cs
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2018 Stanislav Denisov
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+using System;
+using System.Runtime.CompilerServices;
+
+#if !(ENABLE_MONO || ENABLE_IL2CPP)
+ using System.Numerics;
+#else
+ using UnityEngine;
+#endif
+
+namespace NetStack.Compression {
+ public struct CompressedVector2 {
+ public uint x;
+ public uint y;
+
+ public CompressedVector2(uint x, uint y) {
+ this.x = x;
+ this.y = y;
+ }
+ }
+
+ public struct CompressedVector3 {
+ public uint x;
+ public uint y;
+ public uint z;
+
+ public CompressedVector3(uint x, uint y, uint z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+ }
+
+ public struct CompressedVector4 {
+ public uint x;
+ public uint y;
+ public uint z;
+ public uint w;
+
+ public CompressedVector4(uint x, uint y, uint z, uint w) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+ }
+
+ public static class DeBruijn {
+ public static readonly int[] Lookup = new int[32] {
+ 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
+ 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
+ };
+ }
+
+ public class BoundedRange {
+ private readonly float minValue;
+ private readonly float maxValue;
+ private readonly float precision;
+ private readonly int requiredBits;
+ private readonly uint mask;
+
+ public BoundedRange(float minValue, float maxValue, float precision) {
+ this.minValue = minValue;
+ this.maxValue = maxValue;
+ this.precision = precision;
+
+ requiredBits = Log2((uint)((maxValue - minValue) * (1.0f / precision) + 0.5f)) + 1;
+ mask = (uint)((1L << requiredBits) - 1);
+ }
+
+ private int Log2(uint value) {
+ value |= value >> 1;
+ value |= value >> 2;
+ value |= value >> 4;
+ value |= value >> 8;
+ value |= value >> 16;
+
+ return DeBruijn.Lookup[(value * 0x07C4ACDDU) >> 27];
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public uint Compress(float value) {
+ if (value < minValue)
+ value = minValue;
+ else if (value > maxValue)
+ value = maxValue;
+
+ return (uint)((float)((value - minValue) * (1f / precision)) + 0.5f) & mask;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public float Decompress(uint data) {
+ float adjusted = ((float)data * precision) + minValue;
+
+ if (adjusted < minValue)
+ adjusted = minValue;
+ else if (adjusted > maxValue)
+ adjusted = maxValue;
+
+ return adjusted;
+ }
+
+ public static CompressedVector2 Compress(Vector2 vector2, BoundedRange[] boundedRange) {
+ CompressedVector2 data = default(CompressedVector2);
+
+ #if ENABLE_MONO || ENABLE_IL2CPP
+ data.x = boundedRange[0].Compress(vector2.x);
+ data.y = boundedRange[1].Compress(vector2.y);
+ #else
+ data.x = boundedRange[0].Compress(vector2.X);
+ data.y = boundedRange[1].Compress(vector2.Y);
+ #endif
+
+ return data;
+ }
+
+ public static CompressedVector3 Compress(Vector3 vector3, BoundedRange[] boundedRange) {
+ CompressedVector3 data = default(CompressedVector3);
+
+ #if ENABLE_MONO || ENABLE_IL2CPP
+ data.x = boundedRange[0].Compress(vector3.x);
+ data.y = boundedRange[1].Compress(vector3.y);
+ data.z = boundedRange[2].Compress(vector3.z);
+ #else
+ data.x = boundedRange[0].Compress(vector3.X);
+ data.y = boundedRange[1].Compress(vector3.Y);
+ data.z = boundedRange[2].Compress(vector3.Z);
+ #endif
+
+ return data;
+ }
+
+ public static CompressedVector4 Compress(Vector4 vector4, BoundedRange[] boundedRange) {
+ CompressedVector4 data = default(CompressedVector4);
+
+ #if ENABLE_MONO || ENABLE_IL2CPP
+ data.x = boundedRange[0].Compress(vector4.x);
+ data.y = boundedRange[1].Compress(vector4.y);
+ data.z = boundedRange[2].Compress(vector4.z);
+ data.w = boundedRange[3].Compress(vector4.w);
+ #else
+ data.x = boundedRange[0].Compress(vector4.X);
+ data.y = boundedRange[1].Compress(vector4.Y);
+ data.z = boundedRange[2].Compress(vector4.Z);
+ data.w = boundedRange[3].Compress(vector4.W);
+ #endif
+
+ return data;
+ }
+
+ public static Vector2 Decompress(CompressedVector2 data, BoundedRange[] boundedRange) {
+ return new Vector2(boundedRange[0].Decompress(data.x), boundedRange[1].Decompress(data.y));
+ }
+
+ public static Vector3 Decompress(CompressedVector3 data, BoundedRange[] boundedRange) {
+ return new Vector3(boundedRange[0].Decompress(data.x), boundedRange[1].Decompress(data.y), boundedRange[2].Decompress(data.z));
+ }
+
+ public static Vector4 Decompress(CompressedVector4 data, BoundedRange[] boundedRange) {
+ return new Vector4(boundedRange[0].Decompress(data.x), boundedRange[1].Decompress(data.y), boundedRange[2].Decompress(data.z), boundedRange[3].Decompress(data.w));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Plugins/NetStack/NetStack.Compression/BoundedRange.cs.meta b/Assets/Plugins/NetStack/NetStack.Compression/BoundedRange.cs.meta
new file mode 100644
index 0000000..1e5a170
--- /dev/null
+++ b/Assets/Plugins/NetStack/NetStack.Compression/BoundedRange.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d395432689331dd4f883b3afe69c6e2b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/NetStack/NetStack.Compression/HalfPrecision.cs b/Assets/Plugins/NetStack/NetStack.Compression/HalfPrecision.cs
new file mode 100644
index 0000000..8344d60
--- /dev/null
+++ b/Assets/Plugins/NetStack/NetStack.Compression/HalfPrecision.cs
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2018 Stanislav Denisov
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace NetStack.Compression {
+ public static class HalfPrecision {
+ [StructLayout(LayoutKind.Explicit)]
+ private struct Values {
+ [FieldOffset(0)]
+ public float f;
+ [FieldOffset(0)]
+ public int i;
+ [FieldOffset(0)]
+ public uint u;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public static ushort Compress(float value) {
+ var values = new Values {
+ f = value
+ };
+
+ return Compress(values.i);
+ }
+
+ public static ushort Compress(int value) {
+ int s = (value >> 16) & 0x00008000;
+ int e = ((value >> 23) & 0X000000FF) - (127 - 15);
+ int m = value & 0X007FFFFF;
+
+ if (e <= 0) {
+ if (e < -10)
+ return (ushort)s;
+
+ m = m | 0x00800000;
+
+ int t = 14 - e;
+ int a = (1 << (t - 1)) - 1;
+ int b = (m >> t) & 1;
+
+ m = (m + a + b) >> t;
+
+ return (ushort)(s | m);
+ }
+
+ if (e == 0XFF - (127 - 15)) {
+ if (m == 0)
+ return (ushort)(s | 0X7C00);
+
+ m >>= 13;
+
+ return (ushort)(s | 0X7C00 | m | ((m == 0) ? 1 : 0));
+ }
+
+ m = m + 0X00000FFF + ((m >> 13) & 1);
+
+ if ((m & 0x00800000) != 0) {
+ m = 0;
+ e++;
+ }
+
+ if (e > 30)
+ return (ushort)(s | 0X7C00);
+
+ return (ushort)(s | (e << 10) | (m >> 13));
+ }
+
+ public static float Decompress(ushort value) {
+ uint result;
+ uint mantissa = (uint)(value & 1023);
+ uint exponent = 0XFFFFFFF2;
+
+ if ((value & -33792) == 0) {
+ if (mantissa != 0) {
+ while ((mantissa & 1024) == 0) {
+ exponent--;
+ mantissa = mantissa << 1;
+ }
+
+ mantissa &= 0XFFFFFBFF;
+ result = ((uint)((((uint)value & 0x8000) << 16) | ((exponent + 127) << 23))) | (mantissa << 13);
+ } else {
+ result = (uint)((value & 0x8000) << 16);
+ }
+ } else {
+ result = ((((uint)value & 0x8000) << 16) | ((((((uint)value >> 10) & 0X1F) - 15) + 127) << 23)) | (mantissa << 13);
+ }
+
+ var values = new Values {
+ u = result
+ };
+
+ return values.f;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Plugins/NetStack/NetStack.Compression/HalfPrecision.cs.meta b/Assets/Plugins/NetStack/NetStack.Compression/HalfPrecision.cs.meta
new file mode 100644
index 0000000..4a4d825
--- /dev/null
+++ b/Assets/Plugins/NetStack/NetStack.Compression/HalfPrecision.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2b93a7b07069f334e9a659a3443fde6b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/NetStack/NetStack.Compression/SmallestThree.cs b/Assets/Plugins/NetStack/NetStack.Compression/SmallestThree.cs
new file mode 100644
index 0000000..84d9cb5
--- /dev/null
+++ b/Assets/Plugins/NetStack/NetStack.Compression/SmallestThree.cs
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2018 Stanislav Denisov
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+using System;
+
+#if !(ENABLE_MONO || ENABLE_IL2CPP)
+ using System.Numerics;
+#else
+ using UnityEngine;
+#endif
+
+namespace NetStack.Compression {
+ public struct CompressedQuaternion {
+ public byte m;
+ public short a;
+ public short b;
+ public short c;
+
+ public CompressedQuaternion(byte m, short a, short b, short c) {
+ this.m = m;
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ }
+ }
+
+ public static class SmallestThree {
+ private const float floatPrecision = 10000f;
+
+ public static CompressedQuaternion Compress(Quaternion quaternion) {
+ CompressedQuaternion data = default(CompressedQuaternion);
+ byte m = 0;
+ float maxValue = float.MinValue;
+ float sign = 1f;
+
+ for (int i = 0; i <= 3; i++) {
+ float element = 0f;
+ float abs = 0f;
+
+ switch (i) {
+ #if ENABLE_MONO || ENABLE_IL2CPP
+ case 0:
+ element = quaternion.x;
+
+ break;
+
+ case 1:
+ element = quaternion.y;
+
+ break;
+
+ case 2:
+ element = quaternion.z;
+
+ break;
+
+ case 3:
+ element = quaternion.w;
+
+ break;
+ #else
+ case 0:
+ element = quaternion.X;
+
+ break;
+
+ case 1:
+ element = quaternion.Y;
+
+ break;
+
+ case 2:
+ element = quaternion.Z;
+
+ break;
+
+ case 3:
+ element = quaternion.W;
+
+ break;
+ #endif
+ }
+
+ abs = Math.Abs(element);
+
+ if (abs > maxValue) {
+ sign = (element < 0) ? -1 : 1;
+ m = (byte)i;
+ maxValue = abs;
+ }
+ }
+
+ if (Math.Abs(1f - maxValue) < Math.Max(0.000001f * Math.Max(Math.Abs(maxValue), Math.Abs(1f)), Single.Epsilon * 8)) {
+ data.m = (byte)(m + 4);
+
+ return data;
+ }
+
+ short a = 0;
+ short b = 0;
+ short c = 0;
+
+ #if ENABLE_MONO || ENABLE_IL2CPP
+ if (m == 0) {
+ a = (short)(quaternion.y * sign * floatPrecision);
+ b = (short)(quaternion.z * sign * floatPrecision);
+ c = (short)(quaternion.w * sign * floatPrecision);
+ } else if (m == 1) {
+ a = (short)(quaternion.x * sign * floatPrecision);
+ b = (short)(quaternion.z * sign * floatPrecision);
+ c = (short)(quaternion.w * sign * floatPrecision);
+ } else if (m == 2) {
+ a = (short)(quaternion.x * sign * floatPrecision);
+ b = (short)(quaternion.y * sign * floatPrecision);
+ c = (short)(quaternion.w * sign * floatPrecision);
+ } else {
+ a = (short)(quaternion.x * sign * floatPrecision);
+ b = (short)(quaternion.y * sign * floatPrecision);
+ c = (short)(quaternion.z * sign * floatPrecision);
+ }
+ #else
+ if (m == 0) {
+ a = (short)(quaternion.Y * sign * floatPrecision);
+ b = (short)(quaternion.Z * sign * floatPrecision);
+ c = (short)(quaternion.W * sign * floatPrecision);
+ } else if (m == 1) {
+ a = (short)(quaternion.X * sign * floatPrecision);
+ b = (short)(quaternion.Z * sign * floatPrecision);
+ c = (short)(quaternion.W * sign * floatPrecision);
+ } else if (m == 2) {
+ a = (short)(quaternion.X * sign * floatPrecision);
+ b = (short)(quaternion.Y * sign * floatPrecision);
+ c = (short)(quaternion.W * sign * floatPrecision);
+ } else {
+ a = (short)(quaternion.X * sign * floatPrecision);
+ b = (short)(quaternion.Y * sign * floatPrecision);
+ c = (short)(quaternion.Z * sign * floatPrecision);
+ }
+ #endif
+
+ data.m = m;
+ data.a = a;
+ data.b = b;
+ data.c = c;
+
+ return data;
+ }
+
+ public static Quaternion Decompress(CompressedQuaternion data) {
+ byte m = data.m;
+
+ if (m >= 4 && m <= 7) {
+ float x = (m == 4) ? 1f : 0f;
+ float y = (m == 5) ? 1f : 0f;
+ float z = (m == 6) ? 1f : 0f;
+ float w = (m == 7) ? 1f : 0f;
+
+ return new Quaternion(x, y, z, w);
+ }
+
+ float a = (float)data.a / floatPrecision;
+ float b = (float)data.b / floatPrecision;
+ float c = (float)data.c / floatPrecision;
+ float d = (float)Math.Sqrt(1f - ((a * a) + (b * b) + (c * c)));
+
+ if (m == 0)
+ return new Quaternion(d, a, b, c);
+ else if (m == 1)
+ return new Quaternion(a, d, b, c);
+ else if (m == 2)
+ return new Quaternion(a, b, d, c);
+
+ return new Quaternion(a, b, c, d);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Plugins/NetStack/NetStack.Compression/SmallestThree.cs.meta b/Assets/Plugins/NetStack/NetStack.Compression/SmallestThree.cs.meta
new file mode 100644
index 0000000..7a0a769
--- /dev/null
+++ b/Assets/Plugins/NetStack/NetStack.Compression/SmallestThree.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: aedeaaa9b9d42254a934cce0a3f5e8c2
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/NetStack/NetStack.Serialization.meta b/Assets/Plugins/NetStack/NetStack.Serialization.meta
new file mode 100644
index 0000000..bb2232c
--- /dev/null
+++ b/Assets/Plugins/NetStack/NetStack.Serialization.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: bd461e76132dc874385ba95301de58eb
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/NetStack/NetStack.Serialization/BitBuffer.cs b/Assets/Plugins/NetStack/NetStack.Serialization/BitBuffer.cs
new file mode 100644
index 0000000..72a928a
--- /dev/null
+++ b/Assets/Plugins/NetStack/NetStack.Serialization/BitBuffer.cs
@@ -0,0 +1,591 @@
+/*
+ * Copyright (c) 2018 Stanislav Denisov
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 2018 Alexander Shoulson
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace NetStack.Serialization {
+ public class BitBuffer {
+ private const int defaultCapacity = 8;
+ private const int stringLengthMax = 512;
+ private const int stringLengthBits = 9;
+ private const int bitsASCII = 7;
+ private const int growFactor = 2;
+ private const int minGrow = 1;
+ private int readPosition;
+ private int nextPosition;
+ private uint[] chunks;
+
+ public BitBuffer(int capacity = defaultCapacity) {
+ readPosition = 0;
+ nextPosition = 0;
+ chunks = new uint[capacity];
+ }
+
+ public int Length {
+ get {
+ return ((nextPosition - 1) >> 3) + 1;
+ }
+ }
+
+ public bool IsFinished {
+ get {
+ return nextPosition == readPosition;
+ }
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public void Clear() {
+ readPosition = 0;
+ nextPosition = 0;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public void Add(int numBits, uint value) {
+ if (numBits < 0)
+ throw new ArgumentOutOfRangeException("Pushing negative bits");
+
+ if (numBits > 32)
+ throw new ArgumentOutOfRangeException("Pushing too many bits");
+
+ int index = nextPosition >> 5;
+ int used = nextPosition & 0x0000001F;
+
+ if ((index + 1) >= chunks.Length)
+ ExpandArray();
+
+ ulong chunkMask = ((1UL << used) - 1);
+ ulong scratch = chunks[index] & chunkMask;
+ ulong result = scratch | ((ulong)value << used);
+
+ chunks[index] = (uint)result;
+ chunks[index + 1] = (uint)(result >> 32);
+ nextPosition += numBits;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public uint Read(int numBits) {
+ uint result = Peek(numBits);
+
+ readPosition += numBits;
+
+ return result;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public uint Peek(int numBits) {
+ if (numBits < 0)
+ throw new ArgumentOutOfRangeException("Pushing negative bits");
+
+ if (numBits > 32)
+ throw new ArgumentOutOfRangeException("Pushing too many bits");
+
+ int index = readPosition >> 5;
+ int used = readPosition & 0x0000001F;
+
+ ulong chunkMask = ((1UL << numBits) - 1) << used;
+ ulong scratch = (ulong)chunks[index];
+
+ if ((index + 1) < chunks.Length)
+ scratch |= (ulong)chunks[index + 1] << 32;
+
+ ulong result = (scratch & chunkMask) >> used;
+
+ return (uint)result;
+ }
+
+ public int ToArray(byte[] data, int offset) {
+ Add(1, 1);
+
+ int numChunks = (nextPosition >> 5) + 1;
+ int length = data.Length;
+
+ for (int i = 0; i < numChunks; i++) {
+ int dataIdx = i * 4 + offset;
+ uint chunk = chunks[i];
+
+ if (dataIdx < length)
+ data[dataIdx] = (byte)(chunk);
+
+ if (dataIdx + 1 < length)
+ data[dataIdx + 1] = (byte)(chunk >> 8);
+
+ if (dataIdx + 2 < length)
+ data[dataIdx + 2] = (byte)(chunk >> 16);
+
+ if (dataIdx + 3 < length)
+ data[dataIdx + 3] = (byte)(chunk >> 24);
+ }
+
+ return Length;
+ }
+
+ public void FromArray(byte[] data, int offset, int length) {
+ int numChunks = (length / 4) + 1;
+
+ if (chunks.Length < numChunks)
+ chunks = new uint[numChunks];
+
+ for (int i = 0; i < numChunks; i++) {
+ int dataIdx = i * 4 + offset;
+ uint chunk = 0;
+
+ if (dataIdx < length)
+ chunk = (uint)data[dataIdx];
+
+ if (dataIdx + 1 < length)
+ chunk = chunk | (uint)data[dataIdx + 1] << 8;
+
+ if (dataIdx + 2 < length)
+ chunk = chunk | (uint)data[dataIdx + 2] << 16;
+
+ if (dataIdx + 3 < length)
+ chunk = chunk | (uint)data[dataIdx + 3] << 24;
+
+ chunks[i] = chunk;
+ }
+
+ int positionInByte = FindHighestBitPosition(data[length - 1]);
+
+ nextPosition = ((length - 1) * 8) + (positionInByte - 1);
+ readPosition = 0;
+ }
+
+ #if NETSTACK_SPAN
+ public int ToSpan(ref Span data) {
+ Add(1, 1);
+
+ int numChunks = (nextPosition >> 5) + 1;
+ int length = data.Length;
+
+ for (int i = 0; i < numChunks; i++) {
+ int dataIdx = i * 4;
+ uint chunk = chunks[i];
+
+ if (dataIdx < length)
+ data[dataIdx] = (byte)(chunk);
+
+ if (dataIdx + 1 < length)
+ data[dataIdx + 1] = (byte)(chunk >> 8);
+
+ if (dataIdx + 2 < length)
+ data[dataIdx + 2] = (byte)(chunk >> 16);
+
+ if (dataIdx + 3 < length)
+ data[dataIdx + 3] = (byte)(chunk >> 24);
+ }
+
+ return Length;
+ }
+
+ public void FromSpan(ref ReadOnlySpan data, int length) {
+ int numChunks = (length / 4) + 1;
+
+ if (chunks.Length < numChunks)
+ chunks = new uint[numChunks];
+
+ for (int i = 0; i < numChunks; i++) {
+ int dataIdx = i * 4;
+ uint chunk = 0;
+
+ if (dataIdx < length)
+ chunk = (uint)data[dataIdx];
+
+ if (dataIdx + 1 < length)
+ chunk = chunk | (uint)data[dataIdx + 1] << 8;
+
+ if (dataIdx + 2 < length)
+ chunk = chunk | (uint)data[dataIdx + 2] << 16;
+
+ if (dataIdx + 3 < length)
+ chunk = chunk | (uint)data[dataIdx + 3] << 24;
+
+ chunks[i] = chunk;
+ }
+
+ int positionInByte = FindHighestBitPosition(data[length - 1]);
+
+ nextPosition = ((length - 1) * 8) + (positionInByte - 1);
+ readPosition = 0;
+ }
+ #endif
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public BitBuffer AddBool(bool value) {
+ Add(1, value ? 1U : 0U);
+
+ return this;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public bool ReadBool() {
+ return Read(1) > 0;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public bool PeekBool() {
+ return Peek(1) > 0;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public BitBuffer AddByte(byte value) {
+ Add(8, value);
+
+ return this;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public byte ReadByte() {
+ return (byte)Read(8);
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public byte PeekByte() {
+ return (byte)Peek(8);
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public BitBuffer AddShort(short value) {
+ AddInt(value);
+
+ return this;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public short ReadShort() {
+ return (short)ReadInt();
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public short PeekShort() {
+ return (short)PeekInt();
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public BitBuffer AddUShort(ushort value) {
+ AddUInt(value);
+
+ return this;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public ushort ReadUShort() {
+ return (ushort)ReadUInt();
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public ushort PeekUShort() {
+ return (ushort)PeekUInt();
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public BitBuffer AddInt(int value) {
+ uint zigzag = (uint)((value << 1) ^ (value >> 31));
+
+ AddUInt(zigzag);
+
+ return this;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public int ReadInt() {
+ uint value = ReadUInt();
+ int zagzig = (int)((value >> 1) ^ (-(int)(value & 1)));
+
+ return zagzig;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public int PeekInt() {
+ uint value = PeekUInt();
+ int zagzig = (int)((value >> 1) ^ (-(int)(value & 1)));
+
+ return zagzig;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public BitBuffer AddUInt(uint value) {
+ uint buffer = 0x0u;
+
+ do {
+ buffer = value & 0x7Fu;
+ value >>= 7;
+
+ if (value > 0)
+ buffer |= 0x80u;
+
+ Add(8, buffer);
+ }
+
+ while (value > 0);
+
+ return this;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public uint ReadUInt() {
+ uint buffer = 0x0u;
+ uint value = 0x0u;
+ int shift = 0;
+
+ do {
+ buffer = Read(8);
+
+ value |= (buffer & 0x7Fu) << shift;
+ shift += 7;
+ }
+
+ while ((buffer & 0x80u) > 0);
+
+ return value;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public uint PeekUInt() {
+ int tempPosition = readPosition;
+ uint value = ReadUInt();
+
+ readPosition = tempPosition;
+
+ return value;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public BitBuffer AddLong(long value) {
+ AddInt((int)(value & uint.MaxValue));
+ AddInt((int)(value >> 32));
+
+ return this;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public long ReadLong() {
+ int low = ReadInt();
+ int high = ReadInt();
+ long value = high;
+
+ return value << 32 | (uint)low;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public long PeekLong() {
+ int tempPosition = readPosition;
+ long value = ReadLong();
+
+ readPosition = tempPosition;
+
+ return value;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public BitBuffer AddULong(ulong value) {
+ AddUInt((uint)(value & uint.MaxValue));
+ AddUInt((uint)(value >> 32));
+
+ return this;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public ulong ReadULong() {
+ uint low = ReadUInt();
+ uint high = ReadUInt();
+
+ return (ulong)high << 32 | low;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public ulong PeekULong() {
+ int tempPosition = readPosition;
+ ulong value = ReadULong();
+
+ readPosition = tempPosition;
+
+ return value;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public BitBuffer AddString(string value) {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ uint length = (uint)value.Length;
+
+ if (length > stringLengthMax)
+ length = (uint)stringLengthMax;
+
+ Add(stringLengthBits, length);
+
+ for (int i = 0; i < length; i++) {
+ Add(bitsASCII, ToASCII(value[i]));
+ }
+
+ return this;
+ }
+
+ #if NETSTACK_INLINING
+ [MethodImpl(256)]
+ #endif
+ public string ReadString() {
+ StringBuilder builder = new StringBuilder();
+ uint length = Read(stringLengthBits);
+
+ for (int i = 0; i < length; i++) {
+ builder.Append((char)Read(bitsASCII));
+ }
+
+ return builder.ToString();
+ }
+
+ public override string ToString() {
+ StringBuilder builder = new StringBuilder();
+
+ for (int i = chunks.Length - 1; i >= 0; i--) {
+ builder.Append(Convert.ToString(chunks[i], 2).PadLeft(32, '0'));
+ }
+
+ StringBuilder spaced = new StringBuilder();
+
+ for (int i = 0; i < builder.Length; i++) {
+ spaced.Append(builder[i]);
+
+ if (((i + 1) % 8) == 0)
+ spaced.Append(" ");
+ }
+
+ return spaced.ToString();
+ }
+
+ private void ExpandArray() {
+ int newCapacity = (chunks.Length * growFactor) + minGrow;
+ uint[] newChunks = new uint[newCapacity];
+
+ Array.Copy(chunks, newChunks, chunks.Length);
+ chunks = newChunks;
+ }
+
+ private static int FindHighestBitPosition(byte data) {
+ int shiftCount = 0;
+
+ while (data > 0) {
+ data >>= 1;
+ shiftCount++;
+ }
+
+ return shiftCount;
+ }
+
+ private static byte ToASCII(char character) {
+ byte value = 0;
+
+ try {
+ value = Convert.ToByte(character);
+ }
+
+ catch (OverflowException) {
+ throw new Exception("Cannot convert to ASCII: " + character);
+ }
+
+ if (value > 127)
+ throw new Exception("Cannot convert to ASCII: " + character);
+
+ return value;
+ }
+ }
+}
diff --git a/Assets/Plugins/NetStack/NetStack.Serialization/BitBuffer.cs.meta b/Assets/Plugins/NetStack/NetStack.Serialization/BitBuffer.cs.meta
new file mode 100644
index 0000000..6df7271
--- /dev/null
+++ b/Assets/Plugins/NetStack/NetStack.Serialization/BitBuffer.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0820c909f73d7334f8f93857a07b357b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/SpanSupport.meta b/Assets/Plugins/SpanSupport.meta
new file mode 100644
index 0000000..66b11a3
--- /dev/null
+++ b/Assets/Plugins/SpanSupport.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ece87778abb51134587ac5b15c84aac3
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/SpanSupport/System.Buffers.dll b/Assets/Plugins/SpanSupport/System.Buffers.dll
new file mode 100644
index 0000000..c517a3b
Binary files /dev/null and b/Assets/Plugins/SpanSupport/System.Buffers.dll differ
diff --git a/Assets/Plugins/SpanSupport/System.Buffers.dll.meta b/Assets/Plugins/SpanSupport/System.Buffers.dll.meta
new file mode 100644
index 0000000..27585bf
--- /dev/null
+++ b/Assets/Plugins/SpanSupport/System.Buffers.dll.meta
@@ -0,0 +1,33 @@
+fileFormatVersion: 2
+guid: c8e1e0ada971a584dbb2038c2b5514be
+PluginImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ iconMap: {}
+ executionOrder: {}
+ defineConstraints: []
+ isPreloaded: 0
+ isOverridable: 0
+ isExplicitlyReferenced: 0
+ validateReferences: 1
+ platformData:
+ - first:
+ Any:
+ second:
+ enabled: 1
+ settings: {}
+ - first:
+ Editor: Editor
+ second:
+ enabled: 0
+ settings:
+ DefaultValueInitialized: true
+ - first:
+ Windows Store Apps: WindowsStoreApps
+ second:
+ enabled: 0
+ settings:
+ CPU: AnyCPU
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/SpanSupport/System.Memory.dll b/Assets/Plugins/SpanSupport/System.Memory.dll
new file mode 100644
index 0000000..3ba645b
Binary files /dev/null and b/Assets/Plugins/SpanSupport/System.Memory.dll differ
diff --git a/Assets/Plugins/SpanSupport/System.Memory.dll.meta b/Assets/Plugins/SpanSupport/System.Memory.dll.meta
new file mode 100644
index 0000000..140e6bf
--- /dev/null
+++ b/Assets/Plugins/SpanSupport/System.Memory.dll.meta
@@ -0,0 +1,33 @@
+fileFormatVersion: 2
+guid: 4bfaf94ce3054c64492e06128a28e5cf
+PluginImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ iconMap: {}
+ executionOrder: {}
+ defineConstraints: []
+ isPreloaded: 0
+ isOverridable: 0
+ isExplicitlyReferenced: 0
+ validateReferences: 1
+ platformData:
+ - first:
+ Any:
+ second:
+ enabled: 1
+ settings: {}
+ - first:
+ Editor: Editor
+ second:
+ enabled: 0
+ settings:
+ DefaultValueInitialized: true
+ - first:
+ Windows Store Apps: WindowsStoreApps
+ second:
+ enabled: 0
+ settings:
+ CPU: AnyCPU
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/SpanSupport/System.Runtime.CompilerServices.Unsafe.dll b/Assets/Plugins/SpanSupport/System.Runtime.CompilerServices.Unsafe.dll
new file mode 100644
index 0000000..3156239
Binary files /dev/null and b/Assets/Plugins/SpanSupport/System.Runtime.CompilerServices.Unsafe.dll differ
diff --git a/Assets/Plugins/SpanSupport/System.Runtime.CompilerServices.Unsafe.dll.meta b/Assets/Plugins/SpanSupport/System.Runtime.CompilerServices.Unsafe.dll.meta
new file mode 100644
index 0000000..d0c90b0
--- /dev/null
+++ b/Assets/Plugins/SpanSupport/System.Runtime.CompilerServices.Unsafe.dll.meta
@@ -0,0 +1,33 @@
+fileFormatVersion: 2
+guid: 09a7d47f51b5cc84685c35938efe0d94
+PluginImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ iconMap: {}
+ executionOrder: {}
+ defineConstraints: []
+ isPreloaded: 0
+ isOverridable: 0
+ isExplicitlyReferenced: 0
+ validateReferences: 1
+ platformData:
+ - first:
+ Any:
+ second:
+ enabled: 1
+ settings: {}
+ - first:
+ Editor: Editor
+ second:
+ enabled: 0
+ settings:
+ DefaultValueInitialized: true
+ - first:
+ Windows Store Apps: WindowsStoreApps
+ second:
+ enabled: 0
+ settings:
+ CPU: AnyCPU
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scenes.meta b/Assets/Scenes.meta
new file mode 100644
index 0000000..afe9d07
--- /dev/null
+++ b/Assets/Scenes.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 564f3be33d670384cb22785aa1931e73
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity
new file mode 100644
index 0000000..5f2ecc7
--- /dev/null
+++ b/Assets/Scenes/SampleScene.unity
@@ -0,0 +1,387 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!29 &1
+OcclusionCullingSettings:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_OcclusionBakeSettings:
+ smallestOccluder: 5
+ smallestHole: 0.25
+ backfaceThreshold: 100
+ m_SceneGUID: 00000000000000000000000000000000
+ m_OcclusionCullingData: {fileID: 0}
+--- !u!104 &2
+RenderSettings:
+ m_ObjectHideFlags: 0
+ serializedVersion: 9
+ m_Fog: 0
+ m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
+ m_FogMode: 3
+ m_FogDensity: 0.01
+ m_LinearFogStart: 0
+ m_LinearFogEnd: 300
+ m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
+ m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
+ m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
+ m_AmbientIntensity: 1
+ m_AmbientMode: 0
+ m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
+ m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
+ m_HaloStrength: 0.5
+ m_FlareStrength: 1
+ m_FlareFadeSpeed: 3
+ m_HaloTexture: {fileID: 0}
+ m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
+ m_DefaultReflectionMode: 0
+ m_DefaultReflectionResolution: 128
+ m_ReflectionBounces: 1
+ m_ReflectionIntensity: 1
+ m_CustomReflection: {fileID: 0}
+ m_Sun: {fileID: 705507994}
+ m_IndirectSpecularColor: {r: 0.44657844, g: 0.49641222, b: 0.57481694, a: 1}
+ m_UseRadianceAmbientProbe: 0
+--- !u!157 &3
+LightmapSettings:
+ m_ObjectHideFlags: 0
+ serializedVersion: 11
+ m_GIWorkflowMode: 0
+ m_GISettings:
+ serializedVersion: 2
+ m_BounceScale: 1
+ m_IndirectOutputScale: 1
+ m_AlbedoBoost: 1
+ m_EnvironmentLightingMode: 0
+ m_EnableBakedLightmaps: 1
+ m_EnableRealtimeLightmaps: 1
+ m_LightmapEditorSettings:
+ serializedVersion: 12
+ m_Resolution: 2
+ m_BakeResolution: 40
+ m_AtlasSize: 1024
+ m_AO: 0
+ m_AOMaxDistance: 1
+ m_CompAOExponent: 1
+ m_CompAOExponentDirect: 0
+ m_ExtractAmbientOcclusion: 0
+ m_Padding: 2
+ m_LightmapParameters: {fileID: 0}
+ m_LightmapsBakeMode: 1
+ m_TextureCompression: 1
+ m_FinalGather: 0
+ m_FinalGatherFiltering: 1
+ m_FinalGatherRayCount: 256
+ m_ReflectionCompression: 2
+ m_MixedBakeMode: 2
+ m_BakeBackend: 1
+ m_PVRSampling: 1
+ m_PVRDirectSampleCount: 32
+ m_PVRSampleCount: 500
+ m_PVRBounces: 2
+ m_PVREnvironmentSampleCount: 500
+ m_PVREnvironmentReferencePointCount: 2048
+ m_PVRFilteringMode: 2
+ m_PVRDenoiserTypeDirect: 0
+ m_PVRDenoiserTypeIndirect: 0
+ m_PVRDenoiserTypeAO: 0
+ m_PVRFilterTypeDirect: 0
+ m_PVRFilterTypeIndirect: 0
+ m_PVRFilterTypeAO: 0
+ m_PVREnvironmentMIS: 0
+ m_PVRCulling: 1
+ m_PVRFilteringGaussRadiusDirect: 1
+ m_PVRFilteringGaussRadiusIndirect: 5
+ m_PVRFilteringGaussRadiusAO: 2
+ m_PVRFilteringAtrousPositionSigmaDirect: 0.5
+ m_PVRFilteringAtrousPositionSigmaIndirect: 2
+ m_PVRFilteringAtrousPositionSigmaAO: 1
+ m_ShowResolutionOverlay: 1
+ m_ExportTrainingData: 0
+ m_LightingDataAsset: {fileID: 0}
+ m_UseShadowmask: 1
+--- !u!196 &4
+NavMeshSettings:
+ serializedVersion: 2
+ m_ObjectHideFlags: 0
+ m_BuildSettings:
+ serializedVersion: 2
+ agentTypeID: 0
+ agentRadius: 0.5
+ agentHeight: 2
+ agentSlope: 45
+ agentClimb: 0.4
+ ledgeDropHeight: 0
+ maxJumpAcrossDistance: 0
+ minRegionArea: 2
+ manualCellSize: 0
+ cellSize: 0.16666667
+ manualTileSize: 0
+ tileSize: 256
+ accuratePlacement: 0
+ debug:
+ m_Flags: 0
+ m_NavMeshData: {fileID: 0}
+--- !u!1 &705507993
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 705507995}
+ - component: {fileID: 705507994}
+ m_Layer: 0
+ m_Name: Directional Light
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!108 &705507994
+Light:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 705507993}
+ m_Enabled: 1
+ serializedVersion: 9
+ m_Type: 1
+ m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
+ m_Intensity: 1
+ m_Range: 10
+ m_SpotAngle: 30
+ m_InnerSpotAngle: 21.80208
+ m_CookieSize: 10
+ m_Shadows:
+ m_Type: 2
+ m_Resolution: -1
+ m_CustomResolution: -1
+ m_Strength: 1
+ m_Bias: 0.05
+ m_NormalBias: 0.4
+ m_NearPlane: 0.2
+ m_CullingMatrixOverride:
+ e00: 1
+ e01: 0
+ e02: 0
+ e03: 0
+ e10: 0
+ e11: 1
+ e12: 0
+ e13: 0
+ e20: 0
+ e21: 0
+ e22: 1
+ e23: 0
+ e30: 0
+ e31: 0
+ e32: 0
+ e33: 1
+ m_UseCullingMatrixOverride: 0
+ m_Cookie: {fileID: 0}
+ m_DrawHalo: 0
+ m_Flare: {fileID: 0}
+ m_RenderMode: 0
+ m_CullingMask:
+ serializedVersion: 2
+ m_Bits: 4294967295
+ m_RenderingLayerMask: 1
+ m_Lightmapping: 1
+ m_LightShadowCasterMode: 0
+ m_AreaSize: {x: 1, y: 1}
+ m_BounceIntensity: 1
+ m_ColorTemperature: 6570
+ m_UseColorTemperature: 0
+ m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
+ m_UseBoundingSphereOverride: 0
+ m_ShadowRadius: 0
+ m_ShadowAngle: 0
+--- !u!4 &705507995
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 705507993}
+ m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
+ m_LocalPosition: {x: 0, y: 3, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_RootOrder: 3
+ m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
+--- !u!1 &963194225
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 963194228}
+ - component: {fileID: 963194227}
+ - component: {fileID: 963194226}
+ m_Layer: 0
+ m_Name: Main Camera
+ m_TagString: MainCamera
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!81 &963194226
+AudioListener:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 963194225}
+ m_Enabled: 1
+--- !u!20 &963194227
+Camera:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 963194225}
+ m_Enabled: 1
+ serializedVersion: 2
+ m_ClearFlags: 1
+ m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
+ m_projectionMatrixMode: 1
+ m_GateFitMode: 2
+ m_FOVAxisMode: 0
+ m_SensorSize: {x: 36, y: 24}
+ m_LensShift: {x: 0, y: 0}
+ m_FocalLength: 50
+ m_NormalizedViewPortRect:
+ serializedVersion: 2
+ x: 0
+ y: 0
+ width: 1
+ height: 1
+ near clip plane: 0.3
+ far clip plane: 1000
+ field of view: 60
+ orthographic: 0
+ orthographic size: 5
+ m_Depth: -1
+ m_CullingMask:
+ serializedVersion: 2
+ m_Bits: 4294967295
+ m_RenderingPath: -1
+ m_TargetTexture: {fileID: 0}
+ m_TargetDisplay: 0
+ m_TargetEye: 3
+ m_HDR: 1
+ m_AllowMSAA: 1
+ m_AllowDynamicResolution: 0
+ m_ForceIntoRT: 0
+ m_OcclusionCulling: 1
+ m_StereoConvergence: 10
+ m_StereoSeparation: 0.022
+--- !u!4 &963194228
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 963194225}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: -5.61, y: 2.86, z: -10}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_RootOrder: 2
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1016431233
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1016431235}
+ - component: {fileID: 1016431234}
+ m_Layer: 0
+ m_Name: Logger
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!114 &1016431234
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1016431233}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 9ab84c5d2ea6467a8a733e98051580b1, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ DrawCount: 15
+ Messages: []
+--- !u!4 &1016431235
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1016431233}
+ m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_RootOrder: 1
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &2079191269
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 2079191271}
+ - component: {fileID: 2079191270}
+ m_Layer: 0
+ m_Name: GameController
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!114 &2079191270
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 2079191269}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: dbbbddda32854a78aa149317fbcf6c63, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ TargetTickPerSecond: 10
+ PanicStateCount: 6
+ PanicCleanupTarget: 3
+--- !u!4 &2079191271
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 2079191269}
+ m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+ m_LocalPosition: {x: -8.186773, y: 4.664304, z: -5.166054}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_RootOrder: 0
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
diff --git a/Assets/Scenes/SampleScene.unity.meta b/Assets/Scenes/SampleScene.unity.meta
new file mode 100644
index 0000000..952bd1e
--- /dev/null
+++ b/Assets/Scenes/SampleScene.unity.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 9fc0d4010bbf28b4594072e72b8655ab
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources.meta b/Assets/Sources.meta
new file mode 100644
index 0000000..20d29d6
--- /dev/null
+++ b/Assets/Sources.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 647a2fff7110ed1459f0868cba0c4ea4
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/ClientFeature.cs b/Assets/Sources/ClientFeature.cs
new file mode 100644
index 0000000..697d3cd
--- /dev/null
+++ b/Assets/Sources/ClientFeature.cs
@@ -0,0 +1,13 @@
+using Sources.Networking.Client;
+
+public class ClientFeature : Feature
+{
+ public ClientFeature(Contexts contexts, Services services)
+ {
+ Add(new CommonGameplayFeature(contexts, services));
+ Add(new ClientGameplayFeature(contexts, services));
+
+ Add(new ClientNetworkFeature(contexts, services));
+ Add(new CommonGeneratedFeature(contexts));
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/ClientFeature.cs.meta b/Assets/Sources/ClientFeature.cs.meta
new file mode 100644
index 0000000..0a3fa51
--- /dev/null
+++ b/Assets/Sources/ClientFeature.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: e581e3880d1746f482aa388309b1a28c
+timeCreated: 1557775317
\ No newline at end of file
diff --git a/Assets/Sources/Codegen.meta b/Assets/Sources/Codegen.meta
new file mode 100644
index 0000000..93bda53
--- /dev/null
+++ b/Assets/Sources/Codegen.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 474e63f3db484004999f1db68f8192b1
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Codegen/CodegenAttributes.meta b/Assets/Sources/Codegen/CodegenAttributes.meta
new file mode 100644
index 0000000..4904059
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenAttributes.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 95b2ade0f06483246af4becf2bb48ce2
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Codegen/CodegenAttributes/Bounds.meta b/Assets/Sources/Codegen/CodegenAttributes/Bounds.meta
new file mode 100644
index 0000000..bb9db2b
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenAttributes/Bounds.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 13d612487ae74737b0066067951208cd
+timeCreated: 1558178077
\ No newline at end of file
diff --git a/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedFloatAttribute.cs b/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedFloatAttribute.cs
new file mode 100644
index 0000000..89aefc2
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedFloatAttribute.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace Codegen.CodegenAttributes.Bounds
+{
+ [AttributeUsage(AttributeTargets.Field)]
+ public class BoundedFloatAttribute : Attribute
+ {
+ public BoundedFloatAttribute(float min, float max, float precision)
+ {
+ Min = min;
+ Max = max;
+ Precision = precision;
+ }
+
+ public float Min { get; }
+ public float Max { get; }
+ public float Precision { get; }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedFloatAttribute.cs.meta b/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedFloatAttribute.cs.meta
new file mode 100644
index 0000000..4988eed
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedFloatAttribute.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 37e9601c26c4449787af36e8b4917941
+timeCreated: 1558177946
\ No newline at end of file
diff --git a/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedVector2Attribute.cs b/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedVector2Attribute.cs
new file mode 100644
index 0000000..7fa627e
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedVector2Attribute.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace Codegen.CodegenAttributes.Bounds
+{
+ [AttributeUsage(AttributeTargets.Field)]
+ public class BoundedVector2Attribute : Attribute
+ {
+ public BoundedVector2Attribute(float xMin, float xMax, float xPrecision, float yMin, float yMax,
+ float yPrecision)
+ {
+ XMin = xMin;
+ XMax = xMax;
+ XPrecision = xPrecision;
+ YMin = yMin;
+ YMax = yMax;
+ YPrecision = yPrecision;
+ }
+
+ public float XMin { get; }
+ public float XMax { get; }
+ public float XPrecision { get; }
+ public float YMin { get; }
+ public float YMax { get; }
+ public float YPrecision { get; }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedVector2Attribute.cs.meta b/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedVector2Attribute.cs.meta
new file mode 100644
index 0000000..815d4ba
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedVector2Attribute.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: a35cc5e5d1fc43d7a7139c4091540522
+timeCreated: 1558178099
\ No newline at end of file
diff --git a/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedVector3Attribute.cs b/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedVector3Attribute.cs
new file mode 100644
index 0000000..9363208
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedVector3Attribute.cs
@@ -0,0 +1,32 @@
+using System;
+
+namespace Codegen.CodegenAttributes.Bounds
+{
+ [AttributeUsage(AttributeTargets.Field)]
+ public class BoundedVector3Attribute : Attribute
+ {
+ public BoundedVector3Attribute(float xMin, float xMax, float xPrecision, float yMin, float yMax,
+ float yPrecision, float zMin, float zMax, float zPrecision)
+ {
+ XMin = xMin;
+ XMax = xMax;
+ XPrecision = xPrecision;
+ YMin = yMin;
+ YMax = yMax;
+ YPrecision = yPrecision;
+ ZMin = zMin;
+ ZMax = zMax;
+ ZPrecision = zPrecision;
+ }
+
+ public float XMin { get; }
+ public float XMax { get; }
+ public float XPrecision { get; }
+ public float YMin { get; }
+ public float YMax { get; }
+ public float YPrecision { get; }
+ public float ZMin { get; }
+ public float ZMax { get; }
+ public float ZPrecision { get; }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedVector3Attribute.cs.meta b/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedVector3Attribute.cs.meta
new file mode 100644
index 0000000..f324c00
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenAttributes/Bounds/BoundedVector3Attribute.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 5ceca79bc9a446b88f5f6b99607cac79
+timeCreated: 1558178226
\ No newline at end of file
diff --git a/Assets/Sources/Codegen/CodegenAttributes/CommandToClientAttribute.cs b/Assets/Sources/Codegen/CodegenAttributes/CommandToClientAttribute.cs
new file mode 100644
index 0000000..b4d4442
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenAttributes/CommandToClientAttribute.cs
@@ -0,0 +1,8 @@
+using System;
+
+namespace Codegen.CodegenAttributes
+{
+ public class CommandToClientAttribute : Attribute
+ {
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Codegen/CodegenAttributes/CommandToClientAttribute.cs.meta b/Assets/Sources/Codegen/CodegenAttributes/CommandToClientAttribute.cs.meta
new file mode 100644
index 0000000..d42d113
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenAttributes/CommandToClientAttribute.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 01eb0db9e5ae4287af78ac1151c7626b
+timeCreated: 1557597660
\ No newline at end of file
diff --git a/Assets/Sources/Codegen/CodegenAttributes/CommandToServerAttribute.cs b/Assets/Sources/Codegen/CodegenAttributes/CommandToServerAttribute.cs
new file mode 100644
index 0000000..7b2b391
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenAttributes/CommandToServerAttribute.cs
@@ -0,0 +1,8 @@
+using System;
+
+namespace Codegen.CodegenAttributes
+{
+ public class CommandToServerAttribute : Attribute
+ {
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Codegen/CodegenAttributes/CommandToServerAttribute.cs.meta b/Assets/Sources/Codegen/CodegenAttributes/CommandToServerAttribute.cs.meta
new file mode 100644
index 0000000..7c89365
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenAttributes/CommandToServerAttribute.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 763a971e32544f068a03a13537dd6593
+timeCreated: 1557594551
\ No newline at end of file
diff --git a/Assets/Sources/Codegen/CodegenAttributes/SerializeAttribute.cs b/Assets/Sources/Codegen/CodegenAttributes/SerializeAttribute.cs
new file mode 100644
index 0000000..cf1110d
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenAttributes/SerializeAttribute.cs
@@ -0,0 +1,8 @@
+using System;
+
+namespace Codegen.CodegenAttributes
+{
+ public class SerializeAttribute : Attribute
+ {
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Codegen/CodegenAttributes/SerializeAttribute.cs.meta b/Assets/Sources/Codegen/CodegenAttributes/SerializeAttribute.cs.meta
new file mode 100644
index 0000000..ef0fe61
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenAttributes/SerializeAttribute.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 1760a04a9aba47dfb7e0e5679e2cac1d
+timeCreated: 1557592225
\ No newline at end of file
diff --git a/Assets/Sources/Codegen/CodegenAttributes/SyncAttribute.cs b/Assets/Sources/Codegen/CodegenAttributes/SyncAttribute.cs
new file mode 100644
index 0000000..d135da3
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenAttributes/SyncAttribute.cs
@@ -0,0 +1,8 @@
+using System;
+
+namespace Codegen.CodegenAttributes
+{
+ public class SyncAttribute : Attribute
+ {
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Codegen/CodegenAttributes/SyncAttribute.cs.meta b/Assets/Sources/Codegen/CodegenAttributes/SyncAttribute.cs.meta
new file mode 100644
index 0000000..8272856
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenAttributes/SyncAttribute.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 710db9c21b538894094e13ec6c549128
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Codegen/CodegenExecutor.meta b/Assets/Sources/Codegen/CodegenExecutor.meta
new file mode 100644
index 0000000..2dabc97
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenExecutor.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3fc09f8ca15792b4ea300e27cf9f36c6
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Codegen/CodegenExecutor/CodegenExecutor.cs b/Assets/Sources/Codegen/CodegenExecutor/CodegenExecutor.cs
new file mode 100644
index 0000000..2d877e2
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenExecutor/CodegenExecutor.cs
@@ -0,0 +1,682 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using Codegen.CodegenAttributes;
+using Codegen.CodegenAttributes.Bounds;
+using Generators.Compressors;
+using Generators.Scheme.Command;
+using Generators.Scheme.Command.Executor;
+using Generators.Scheme.Command.Executor.Interface;
+using Generators.Sync.Component;
+using Generators.Sync.Feature;
+using Generators.Sync.Systems;
+using Generators.Sync.Utility;
+using UnityEngine;
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+
+public class CodegenExecutor : ScriptableObject
+{
+#if UNITY_EDITOR
+ public string OutputPath = "Generated";
+
+ [ContextMenu("Generate Sync Code")]
+ private void GenerateSyncCode()
+ {
+ #region collect
+
+ var clearPath = Path.Combine(Application.dataPath, OutputPath, "Sync");
+ if (Directory.Exists(clearPath))
+ Directory.Delete(clearPath, true);
+
+ ushort counter = 0;
+ var compressors = new List>();
+ var components = new List>();
+ foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
+ foreach (var type in assembly.GetTypes())
+ {
+ var syncAttributes = type.GetCustomAttributes(typeof(SyncAttribute), false);
+
+ if (syncAttributes != null && syncAttributes.Length > 0)
+ {
+ var componentName = type.Name;
+
+ var fields = type.GetFields();
+ var fieldTypes = new List();
+ var fieldNames = new List();
+ var isEnums = new List();
+ var isCompressed = new List();
+
+ foreach (var field in fields)
+ {
+ var compressed = false;
+ switch (field.FieldType.ToString())
+ {
+ case "System.Single":
+ {
+ var compressor = field.GetCustomAttribute();
+ if (compressor != null)
+ {
+ compressors.Add(new Tuple(
+ $"{componentName.Replace("Component", "")}{field.Name}", compressor.Min,
+ compressor.Max, compressor.Precision));
+ compressed = true;
+ }
+ }
+ break;
+ case "UnityEngine.Vector2":
+ {
+ var compressor = field.GetCustomAttribute();
+ if (compressor != null)
+ {
+ compressors.Add(new Tuple(
+ $"{componentName.Replace("Component", "")}{field.Name}X", compressor.XMin,
+ compressor.XMax, compressor.XPrecision));
+ compressors.Add(new Tuple(
+ $"{componentName.Replace("Component", "")}{field.Name}Y", compressor.YMin,
+ compressor.YMax, compressor.YPrecision));
+ compressed = true;
+ }
+ }
+ break;
+ case "UnityEngine.Vector3":
+ {
+ var compressor = field.GetCustomAttribute();
+ if (compressor != null)
+ {
+ compressors.Add(new Tuple(
+ $"{componentName.Replace("Component", "")}{field.Name}X", compressor.XMin,
+ compressor.XMax, compressor.XPrecision));
+ compressors.Add(new Tuple(
+ $"{componentName.Replace("Component", "")}{field.Name}Y", compressor.YMin,
+ compressor.YMax, compressor.YPrecision));
+ compressors.Add(new Tuple(
+ $"{componentName.Replace("Component", "")}{field.Name}Z", compressor.ZMin,
+ compressor.ZMax, compressor.ZPrecision));
+ compressed = true;
+ }
+ }
+ break;
+ }
+
+ isEnums.Add(field.FieldType.IsEnum);
+ fieldTypes.Add(field.FieldType.ToString());
+ fieldNames.Add(field.Name);
+ isCompressed.Add(compressed);
+ }
+
+ components.Add(new Tuple(componentName, counter,
+ fieldTypes.ToArray(), fieldNames.ToArray(), isEnums.ToArray(), isCompressed.ToArray()));
+ counter++;
+ }
+ else
+ {
+ var serializeAttributes = type.GetCustomAttributes(typeof(SerializeAttribute), false);
+
+ if (serializeAttributes != null && serializeAttributes.Length > 0)
+ {
+ var componentName = type.Name;
+
+ var fields = type.GetFields();
+ var fieldTypes = new List();
+ var fieldNames = new List();
+ var isEnums = new List();
+ var isCompressed = new List();
+
+ foreach (var field in fields)
+ {
+ var compressed = false;
+ switch (field.FieldType.ToString())
+ {
+ case "System.Single":
+ {
+ var compressor = field.GetCustomAttribute();
+ if (compressor != null)
+ {
+ compressors.Add(new Tuple(
+ $"{componentName.Replace("Component", "")}{field.Name}", compressor.Min,
+ compressor.Max, compressor.Precision));
+ compressed = true;
+ }
+ }
+ break;
+ case "UnityEngine.Vector2":
+ {
+ var compressor = field.GetCustomAttribute();
+ if (compressor != null)
+ {
+ compressors.Add(new Tuple(
+ $"{componentName.Replace("Component", "")}{field.Name}X", compressor.XMin,
+ compressor.XMax, compressor.XPrecision));
+ compressors.Add(new Tuple(
+ $"{componentName.Replace("Component", "")}{field.Name}Y", compressor.YMin,
+ compressor.YMax, compressor.YPrecision));
+ compressed = true;
+ }
+ }
+ break;
+ case "UnityEngine.Vector3":
+ {
+ var compressor = field.GetCustomAttribute();
+ if (compressor != null)
+ {
+ compressors.Add(new Tuple(
+ $"{componentName.Replace("Component", "")}{field.Name}X", compressor.XMin,
+ compressor.XMax, compressor.XPrecision));
+ compressors.Add(new Tuple(
+ $"{componentName.Replace("Component", "")}{field.Name}Y", compressor.YMin,
+ compressor.YMax, compressor.YPrecision));
+ compressors.Add(new Tuple(
+ $"{componentName.Replace("Component", "")}{field.Name}Z", compressor.ZMin,
+ compressor.ZMax, compressor.ZPrecision));
+ compressed = true;
+ }
+ }
+ break;
+ }
+
+ isEnums.Add(field.FieldType.IsEnum);
+ fieldTypes.Add(field.FieldType.ToString());
+ fieldNames.Add(field.Name);
+ isCompressed.Add(compressed);
+ }
+
+ var componentTemplate = new SyncComponentGenerator();
+ var d = new Dictionary
+ {
+ {"ComponentName", componentName},
+ {"ComponentId", counter},
+ {"FieldTypes", fieldTypes.ToArray()},
+ {"FieldNames", fieldNames.ToArray()},
+ {"IsEnums", isEnums.ToArray()},
+ {"IsCompressed", isCompressed.ToArray()}
+ };
+
+ componentTemplate.Session = d;
+ componentTemplate.Initialize();
+ var output = componentTemplate.TransformText();
+
+ SaveFile("Sync/Components/", $"{componentName}.cs", output);
+ counter++;
+ }
+ }
+ }
+
+ #endregion
+
+ #region components
+
+ foreach (var tuple in components)
+ {
+ var componentTemplate = new SyncComponentGenerator();
+ var d = new Dictionary
+ {
+ {"ComponentName", tuple.Item1},
+ {"ComponentId", tuple.Item2},
+ {"FieldTypes", tuple.Item3},
+ {"FieldNames", tuple.Item4},
+ {"IsEnums", tuple.Item5},
+ {"IsCompressed", tuple.Item6}
+ };
+
+ componentTemplate.Session = d;
+ componentTemplate.Initialize();
+ var output = componentTemplate.TransformText();
+
+ SaveFile("Sync/Components/", $"{tuple.Item1}.cs", output);
+ }
+
+ #endregion
+
+ #region capture removed components
+
+ foreach (var tuple in components)
+ {
+ var componentTemplate = new SyncRemovedComponentSystemGenerator();
+ var d = new Dictionary
+ {
+ {"ComponentName", tuple.Item1.Replace("Component", "")},
+ {"ComponentId", tuple.Item2},
+ {"IsTag", tuple.Item3.Length == 0}
+ };
+
+ componentTemplate.Session = d;
+ componentTemplate.Initialize();
+ var output = componentTemplate.TransformText();
+
+ SaveFile("Sync/Capture/", $"ServerCaptureRemoved{tuple.Item1.Replace("Component", "")}System.cs", output);
+ }
+
+ #endregion
+
+ #region capture changed/added components
+
+ foreach (var tuple in components)
+ {
+ var componentTemplate = new SyncChangedComponentSystemGenerator();
+ var d = new Dictionary
+ {
+ {"ComponentName", tuple.Item1.Replace("Component", "")},
+ {"ComponentId", tuple.Item2},
+ {"IsTag", tuple.Item3.Length == 0}
+ };
+
+ componentTemplate.Session = d;
+ componentTemplate.Initialize();
+ var output = componentTemplate.TransformText();
+
+ SaveFile("Sync/Capture/", $"ServerCaptureChanged{tuple.Item1.Replace("Component", "")}System.cs", output);
+ }
+
+ #endregion
+
+ #region pack entity utility
+
+ {
+ var packUtilityTemplate = new PackEntityUtilityGenerator();
+ var d = new Dictionary
+ {
+ {"ComponentNames", components.Select(x => x.Item1).ToArray()},
+ {"ComponentIds", components.Select(x => x.Item2).ToArray()},
+ {"IsTags", components.Select(x => x.Item3.Length == 0).ToArray()}
+ };
+
+ packUtilityTemplate.Session = d;
+ packUtilityTemplate.Initialize();
+ var output = packUtilityTemplate.TransformText();
+
+ SaveFile("Sync/Utility/", "PackEntityUtility.cs", output);
+ }
+
+ #endregion
+
+ #region unpack entity utility
+
+ {
+ var template = new UnpackEntityUtilityGenerator();
+ var d = new Dictionary
+ {
+ {"ComponentNames", components.Select(x => x.Item1).ToArray()},
+ {"ComponentIds", components.Select(x => x.Item2).ToArray()},
+ {"IsTags", components.Select(x => x.Item3.Length == 0).ToArray()}
+ };
+
+ template.Session = d;
+ template.Initialize();
+ var output = template.TransformText();
+
+ SaveFile("Sync/Utility/", "UnpackEntityUtility.cs", output);
+ }
+
+ #endregion
+
+ #region feature
+
+ {
+ var template = new SyncFeatureGenerator();
+ var d = new Dictionary
+ {
+ {"ComponentNames", components.Select(x => x.Item1.Replace("Component", "")).ToArray()}
+ };
+
+ template.Session = d;
+ template.Initialize();
+ var output = template.TransformText();
+
+ SaveFile("Sync/Feature/", "ServerStateCaptureFeature.cs", output);
+ }
+
+ #endregion
+
+ #region compressors
+
+ {
+ var template = new CompressorsGenerator();
+ var d = new Dictionary
+ {
+ {"Prefix", "Sync"},
+ {"CompressorNames", compressors.Select(x => x.Item1).ToArray()},
+ {"Mins", compressors.Select(x => x.Item2).ToArray()},
+ {"Maxs", compressors.Select(x => x.Item3).ToArray()},
+ {"Precisions", compressors.Select(x => x.Item4).ToArray()}
+ };
+
+ template.Session = d;
+ template.Initialize();
+ var output = template.TransformText();
+
+ SaveFile("Sync/Compressors/", "SyncCompressors.cs", output);
+ }
+
+ #endregion
+
+ AssetDatabase.Refresh();
+ }
+
+ [ContextMenu("Generate Command Code")]
+ private void GenerateCommandCode()
+ {
+ #region collect
+
+ var clearPath = Path.Combine(Application.dataPath, OutputPath, "Command");
+ if (Directory.Exists(clearPath))
+ Directory.Delete(clearPath, true);
+
+ ushort serverCounter = 0;
+ ushort clientCounter = 0;
+ var compressors = new List>();
+ var serverCommands = new List>();
+ var clientCommands = new List>();
+ foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
+ foreach (var type in assembly.GetTypes())
+ {
+ var serverAttribute = type.GetCustomAttributes(typeof(CommandToServerAttribute), false);
+
+ if (serverAttribute != null && serverAttribute.Length > 0)
+ {
+ var name = type.Name.Replace("Scheme", "");
+
+ var fields = type.GetFields();
+ var fieldTypes = new List();
+ var fieldNames = new List();
+ var isEnums = new List();
+ var isCompressed = new List();
+
+ foreach (var field in fields)
+ {
+ var compressed = false;
+ switch (field.FieldType.ToString())
+ {
+ case "System.Single":
+ {
+ var compressor = field.GetCustomAttribute();
+ if (compressor != null)
+ {
+ compressors.Add(new Tuple(
+ $"Client{name.Replace("Component", "")}{field.Name}", compressor.Min,
+ compressor.Max, compressor.Precision));
+ compressed = true;
+ }
+ }
+ break;
+ case "UnityEngine.Vector2":
+ {
+ var compressor = field.GetCustomAttribute();
+ if (compressor != null)
+ {
+ compressors.Add(new Tuple(
+ $"Client{name.Replace("Component", "")}{field.Name}X", compressor.XMin,
+ compressor.XMax, compressor.XPrecision));
+ compressors.Add(new Tuple(
+ $"Client{name.Replace("Component", "")}{field.Name}Y", compressor.YMin,
+ compressor.YMax, compressor.YPrecision));
+ compressed = true;
+ }
+ }
+ break;
+ case "UnityEngine.Vector3":
+ {
+ var compressor = field.GetCustomAttribute();
+ if (compressor != null)
+ {
+ compressors.Add(new Tuple(
+ $"Client{name.Replace("Component", "")}{field.Name}X", compressor.XMin,
+ compressor.XMax, compressor.XPrecision));
+ compressors.Add(new Tuple(
+ $"Client{name.Replace("Component", "")}{field.Name}Y", compressor.YMin,
+ compressor.YMax, compressor.YPrecision));
+ compressors.Add(new Tuple(
+ $"Client{name.Replace("Component", "")}{field.Name}Z", compressor.ZMin,
+ compressor.ZMax, compressor.ZPrecision));
+ compressed = true;
+ }
+ }
+ break;
+ }
+
+ isEnums.Add(field.FieldType.IsEnum);
+ fieldTypes.Add(field.FieldType.ToString());
+ fieldNames.Add(field.Name);
+ isCompressed.Add(compressed);
+ }
+
+ clientCommands.Add(new Tuple(name, clientCounter,
+ fieldTypes.ToArray(), fieldNames.ToArray(), isEnums.ToArray(), isCompressed.ToArray()));
+ clientCounter++;
+ }
+
+ var clientAttribute = type.GetCustomAttributes(typeof(CommandToClientAttribute), false);
+
+ if (clientAttribute != null && clientAttribute.Length > 0)
+ {
+ var name = type.Name.Replace("Scheme", "");
+
+ var fields = type.GetFields();
+ var fieldTypes = new List();
+ var fieldNames = new List();
+ var isEnums = new List();
+ var isCompressed = new List();
+
+ foreach (var field in fields)
+ {
+ var compressed = false;
+ switch (field.FieldType.ToString())
+ {
+ case "System.Single":
+ {
+ var compressor = field.GetCustomAttribute();
+ if (compressor != null)
+ {
+ compressors.Add(new Tuple(
+ $"Server{name}{field.Name}", compressor.Min,
+ compressor.Max, compressor.Precision));
+ compressed = true;
+ }
+ }
+ break;
+ case "UnityEngine.Vector2":
+ {
+ var compressor = field.GetCustomAttribute();
+ if (compressor != null)
+ {
+ compressors.Add(new Tuple(
+ $"Server{name}{field.Name}X", compressor.XMin,
+ compressor.XMax, compressor.XPrecision));
+ compressors.Add(new Tuple(
+ $"Server{name}{field.Name}Y", compressor.YMin,
+ compressor.YMax, compressor.YPrecision));
+ compressed = true;
+ }
+ }
+ break;
+ case "UnityEngine.Vector3":
+ {
+ var compressor = field.GetCustomAttribute();
+ if (compressor != null)
+ {
+ compressors.Add(new Tuple(
+ $"Server{name}{field.Name}X", compressor.XMin,
+ compressor.XMax, compressor.XPrecision));
+ compressors.Add(new Tuple(
+ $"Server{name}{field.Name}Y", compressor.YMin,
+ compressor.YMax, compressor.YPrecision));
+ compressors.Add(new Tuple(
+ $"Server{name}{field.Name}Z", compressor.ZMin,
+ compressor.ZMax, compressor.ZPrecision));
+ compressed = true;
+ }
+ }
+ break;
+ }
+
+ isEnums.Add(field.FieldType.IsEnum);
+ fieldTypes.Add(field.FieldType.ToString());
+ fieldNames.Add(field.Name);
+ isCompressed.Add(compressed);
+ }
+
+ serverCommands.Add(new Tuple(name, serverCounter,
+ fieldTypes.ToArray(), fieldNames.ToArray(), isEnums.ToArray(), isCompressed.ToArray()));
+ serverCounter++;
+ }
+ }
+
+ #endregion
+
+ #region execution interfaces
+
+ var serverSystem = new SchemeCommandExecutorInterfaceGenerator();
+ var d = new Dictionary
+ {
+ {"Using", "Client"},
+ {"Type", "Server"},
+ {"SchemeNames", clientCommands.Select(x => x.Item1).ToArray()}
+ };
+
+ serverSystem.Session = d;
+ serverSystem.Initialize();
+ var output = serverSystem.TransformText();
+
+ SaveFile("Command/Execution/", "IServerHandler.cs", output);
+
+ var clientSystem = new SchemeCommandExecutorInterfaceGenerator();
+ d = new Dictionary
+ {
+ {"Using", "Server"},
+ {"Type", "Client"},
+ {"SchemeNames", serverCommands.Select(x => x.Item1).ToArray()}
+ };
+
+ clientSystem.Session = d;
+ clientSystem.Initialize();
+ output = clientSystem.TransformText();
+
+ SaveFile("Command/Execution/", "IClientHandler.cs", output);
+
+ #endregion
+
+ #region executors
+
+ var serverExecutor = new SchemeCommandExecutorGenerator();
+ d = new Dictionary
+ {
+ {"Using", "Client"},
+ {"Type", "Server"},
+ {"SchemeNames", clientCommands.Select(x => x.Item1).ToArray()},
+ {"SchemeIds", clientCommands.Select(x => x.Item2).ToArray()}
+ };
+
+ serverExecutor.Session = d;
+ serverExecutor.Initialize();
+ output = serverExecutor.TransformText();
+
+ SaveFile("Command/Execution/", "ServerCommandExecutor.cs", output);
+
+ var clientExecutor = new SchemeCommandExecutorGenerator();
+ d = new Dictionary
+ {
+ {"Using", "Server"},
+ {"Type", "Client"},
+ {"SchemeNames", serverCommands.Select(x => x.Item1).ToArray()},
+ {"SchemeIds", serverCommands.Select(x => x.Item2).ToArray()}
+ };
+
+ clientExecutor.Session = d;
+ clientExecutor.Initialize();
+ output = clientExecutor.TransformText();
+
+ SaveFile("Command/Execution/", "ClientCommandExecutor.cs", output);
+
+ #endregion
+
+ #region commands
+
+ foreach (var tuple in serverCommands)
+ {
+ var componentTemplate = new SchemeCommandGenerator();
+ d = new Dictionary
+ {
+ {"Namespace", "Server"},
+ {"CommandName", tuple.Item1},
+ {"CommandId", tuple.Item2},
+ {"FieldTypes", tuple.Item3},
+ {"FieldNames", tuple.Item4},
+ {"IsEnums", tuple.Item5},
+ {"IsCompressed", tuple.Item6}
+ };
+
+ componentTemplate.Session = d;
+ componentTemplate.Initialize();
+ output = componentTemplate.TransformText();
+
+ SaveFile("Command/Server/", $"{tuple.Item1}Command.cs", output);
+ }
+
+ foreach (var tuple in clientCommands)
+ {
+ var componentTemplate = new SchemeCommandGenerator();
+ d = new Dictionary
+ {
+ {"Namespace", "Client"},
+ {"CommandName", tuple.Item1},
+ {"CommandId", tuple.Item2},
+ {"FieldTypes", tuple.Item3},
+ {"FieldNames", tuple.Item4},
+ {"IsEnums", tuple.Item5},
+ {"IsCompressed", tuple.Item6}
+ };
+
+ componentTemplate.Session = d;
+ componentTemplate.Initialize();
+ output = componentTemplate.TransformText();
+
+ SaveFile("Command/Client/", $"{tuple.Item1}Command.cs", output);
+ }
+
+ #endregion
+
+ #region compressors
+
+ {
+ var template = new CompressorsGenerator();
+ d = new Dictionary
+ {
+ {"Prefix", "Command"},
+ {"CompressorNames", compressors.Select(x => x.Item1).ToArray()},
+ {"Mins", compressors.Select(x => x.Item2).ToArray()},
+ {"Maxs", compressors.Select(x => x.Item3).ToArray()},
+ {"Precisions", compressors.Select(x => x.Item4).ToArray()}
+ };
+
+ template.Session = d;
+ template.Initialize();
+ output = template.TransformText();
+
+ SaveFile("Command/Compressors/", "SyncCompressors.cs", output);
+ }
+
+ #endregion
+
+ AssetDatabase.Refresh();
+ }
+
+ private void SaveFile(string directory, string fileName, string text)
+ {
+ try
+ {
+ var path = Path.Combine(Application.dataPath, OutputPath, directory);
+ Directory.CreateDirectory(path);
+ path = Path.Combine(path, fileName);
+ File.WriteAllText(path, text);
+ }
+ catch (Exception e)
+ {
+ Debug.LogError($"Error while saving file {name}:" + e.Message);
+ throw;
+ }
+ }
+#endif
+}
\ No newline at end of file
diff --git a/Assets/Sources/Codegen/CodegenExecutor/CodegenExecutor.cs.meta b/Assets/Sources/Codegen/CodegenExecutor/CodegenExecutor.cs.meta
new file mode 100644
index 0000000..f6abc76
--- /dev/null
+++ b/Assets/Sources/Codegen/CodegenExecutor/CodegenExecutor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 16d40f4c171d6f647a7e84fcaaf26327
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/CommandSchemes.meta b/Assets/Sources/CommandSchemes.meta
new file mode 100644
index 0000000..5fe8b56
--- /dev/null
+++ b/Assets/Sources/CommandSchemes.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 35583590a39948738fb0e9ca84c2fae8
+timeCreated: 1557594366
\ No newline at end of file
diff --git a/Assets/Sources/CommandSchemes/ICommand.cs b/Assets/Sources/CommandSchemes/ICommand.cs
new file mode 100644
index 0000000..7253355
--- /dev/null
+++ b/Assets/Sources/CommandSchemes/ICommand.cs
@@ -0,0 +1,7 @@
+using NetStack.Serialization;
+
+public interface ICommand
+{
+ void Serialize(BitBuffer bitBuffer);
+ void Deserialize(BitBuffer bitBuffer);
+}
\ No newline at end of file
diff --git a/Assets/Sources/CommandSchemes/ICommand.cs.meta b/Assets/Sources/CommandSchemes/ICommand.cs.meta
new file mode 100644
index 0000000..71dc59f
--- /dev/null
+++ b/Assets/Sources/CommandSchemes/ICommand.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: f1be1272dfa84381b835c4f0a59a1870
+timeCreated: 1557598638
\ No newline at end of file
diff --git a/Assets/Sources/CommandSchemes/ToClient.meta b/Assets/Sources/CommandSchemes/ToClient.meta
new file mode 100644
index 0000000..a155dbc
--- /dev/null
+++ b/Assets/Sources/CommandSchemes/ToClient.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 4011258077df4954be2668a6e1c8c16d
+timeCreated: 1557594392
\ No newline at end of file
diff --git a/Assets/Sources/CommandSchemes/ToClient/ChatMessageScheme.cs b/Assets/Sources/CommandSchemes/ToClient/ChatMessageScheme.cs
new file mode 100644
index 0000000..aabc328
--- /dev/null
+++ b/Assets/Sources/CommandSchemes/ToClient/ChatMessageScheme.cs
@@ -0,0 +1,11 @@
+using Codegen.CodegenAttributes;
+
+namespace Sources.CommandSchemes.ToClient
+{
+ [CommandToClient]
+ public class ChatMessageScheme
+ {
+ public string Message;
+ public ushort Sender;
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/CommandSchemes/ToClient/ChatMessageScheme.cs.meta b/Assets/Sources/CommandSchemes/ToClient/ChatMessageScheme.cs.meta
new file mode 100644
index 0000000..1318962
--- /dev/null
+++ b/Assets/Sources/CommandSchemes/ToClient/ChatMessageScheme.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 94a4bc6ac9d941e288b522bcb53d88ac
+timeCreated: 1557599093
\ No newline at end of file
diff --git a/Assets/Sources/CommandSchemes/ToClient/GrantedIdScheme.cs b/Assets/Sources/CommandSchemes/ToClient/GrantedIdScheme.cs
new file mode 100644
index 0000000..5af1d77
--- /dev/null
+++ b/Assets/Sources/CommandSchemes/ToClient/GrantedIdScheme.cs
@@ -0,0 +1,10 @@
+using Codegen.CodegenAttributes;
+
+namespace Sources.CommandSchemes.ToClient
+{
+ [CommandToClient]
+ public class GrantedIdScheme
+ {
+ public ushort Id;
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/CommandSchemes/ToClient/GrantedIdScheme.cs.meta b/Assets/Sources/CommandSchemes/ToClient/GrantedIdScheme.cs.meta
new file mode 100644
index 0000000..2d67f2e
--- /dev/null
+++ b/Assets/Sources/CommandSchemes/ToClient/GrantedIdScheme.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: e852bd7e236142e2a28151e90a9e1eb7
+timeCreated: 1557671269
\ No newline at end of file
diff --git a/Assets/Sources/CommandSchemes/ToClient/SetTickrateScheme.cs b/Assets/Sources/CommandSchemes/ToClient/SetTickrateScheme.cs
new file mode 100644
index 0000000..2ea6674
--- /dev/null
+++ b/Assets/Sources/CommandSchemes/ToClient/SetTickrateScheme.cs
@@ -0,0 +1,10 @@
+using Codegen.CodegenAttributes;
+
+namespace Sources.CommandSchemes.ToClient
+{
+ [CommandToClient]
+ public class SetTickrateScheme
+ {
+ public ushort Tickrate;
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/CommandSchemes/ToClient/SetTickrateScheme.cs.meta b/Assets/Sources/CommandSchemes/ToClient/SetTickrateScheme.cs.meta
new file mode 100644
index 0000000..1d49ae0
--- /dev/null
+++ b/Assets/Sources/CommandSchemes/ToClient/SetTickrateScheme.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 2e8a4564270d4f57bc1ce346ee660205
+timeCreated: 1557922705
\ No newline at end of file
diff --git a/Assets/Sources/CommandSchemes/ToServer.meta b/Assets/Sources/CommandSchemes/ToServer.meta
new file mode 100644
index 0000000..710ff98
--- /dev/null
+++ b/Assets/Sources/CommandSchemes/ToServer.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 56193667f4da4fffbda78a639b2cd32f
+timeCreated: 1557594385
\ No newline at end of file
diff --git a/Assets/Sources/CommandSchemes/ToServer/ChatMessageScheme.cs b/Assets/Sources/CommandSchemes/ToServer/ChatMessageScheme.cs
new file mode 100644
index 0000000..ea4a399
--- /dev/null
+++ b/Assets/Sources/CommandSchemes/ToServer/ChatMessageScheme.cs
@@ -0,0 +1,10 @@
+using Codegen.CodegenAttributes;
+
+namespace Sources.CommandSchemes.ToServer
+{
+ [CommandToServer]
+ public class ChatMessageScheme
+ {
+ public string Message;
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/CommandSchemes/ToServer/ChatMessageScheme.cs.meta b/Assets/Sources/CommandSchemes/ToServer/ChatMessageScheme.cs.meta
new file mode 100644
index 0000000..5fdd87e
--- /dev/null
+++ b/Assets/Sources/CommandSchemes/ToServer/ChatMessageScheme.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 5d578a4f6ef041108d864c7af5458ecd
+timeCreated: 1557676027
\ No newline at end of file
diff --git a/Assets/Sources/CommandSchemes/ToServer/RequestCharacterScheme.cs b/Assets/Sources/CommandSchemes/ToServer/RequestCharacterScheme.cs
new file mode 100644
index 0000000..1091544
--- /dev/null
+++ b/Assets/Sources/CommandSchemes/ToServer/RequestCharacterScheme.cs
@@ -0,0 +1,9 @@
+using Codegen.CodegenAttributes;
+
+namespace Sources.CommandSchemes.ToServer
+{
+ [CommandToServer]
+ public class RequestCharacterScheme
+ {
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/CommandSchemes/ToServer/RequestCharacterScheme.cs.meta b/Assets/Sources/CommandSchemes/ToServer/RequestCharacterScheme.cs.meta
new file mode 100644
index 0000000..9892b53
--- /dev/null
+++ b/Assets/Sources/CommandSchemes/ToServer/RequestCharacterScheme.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: f4e812ce938b43578290aeb186598d0e
+timeCreated: 1558201839
\ No newline at end of file
diff --git a/Assets/Sources/CommandSchemes/ToServer/SetTickrateScheme.cs b/Assets/Sources/CommandSchemes/ToServer/SetTickrateScheme.cs
new file mode 100644
index 0000000..0b3f2f5
--- /dev/null
+++ b/Assets/Sources/CommandSchemes/ToServer/SetTickrateScheme.cs
@@ -0,0 +1,10 @@
+using Codegen.CodegenAttributes;
+
+namespace Sources.CommandSchemes.ToServer
+{
+ [CommandToServer]
+ public class SetTickrateScheme
+ {
+ public ushort Tickrate;
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/CommandSchemes/ToServer/SetTickrateScheme.cs.meta b/Assets/Sources/CommandSchemes/ToServer/SetTickrateScheme.cs.meta
new file mode 100644
index 0000000..13f67d7
--- /dev/null
+++ b/Assets/Sources/CommandSchemes/ToServer/SetTickrateScheme.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 6fdcc79fbd1b42c9bee92a0700a36d69
+timeCreated: 1558385134
\ No newline at end of file
diff --git a/Assets/Sources/Common.meta b/Assets/Sources/Common.meta
new file mode 100644
index 0000000..b72e776
--- /dev/null
+++ b/Assets/Sources/Common.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: eacb205581764de39af914df9ad5dd2d
+timeCreated: 1556833308
\ No newline at end of file
diff --git a/Assets/Sources/Common/DestroyedComponent.cs b/Assets/Sources/Common/DestroyedComponent.cs
new file mode 100644
index 0000000..c3f7030
--- /dev/null
+++ b/Assets/Sources/Common/DestroyedComponent.cs
@@ -0,0 +1,9 @@
+using Entitas;
+using Entitas.CodeGeneration.Attributes;
+
+[Game]
+[Event(EventTarget.Self)]
+[Cleanup(CleanupMode.DestroyEntity)]
+public class DestroyedComponent : IComponent
+{
+}
\ No newline at end of file
diff --git a/Assets/Sources/Common/DestroyedComponent.cs.meta b/Assets/Sources/Common/DestroyedComponent.cs.meta
new file mode 100644
index 0000000..2748d13
--- /dev/null
+++ b/Assets/Sources/Common/DestroyedComponent.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 68cda93113f94ddb8d32b78c141bf027
+timeCreated: 1556833325
\ No newline at end of file
diff --git a/Assets/Sources/Common/IdComponent.cs b/Assets/Sources/Common/IdComponent.cs
new file mode 100644
index 0000000..5683407
--- /dev/null
+++ b/Assets/Sources/Common/IdComponent.cs
@@ -0,0 +1,15 @@
+using Codegen.CodegenAttributes;
+using Entitas;
+using Entitas.CodeGeneration.Attributes;
+
+[Game]
+[Sync]
+public partial class IdComponent : IComponent
+{
+ [PrimaryEntityIndex] public ushort Value;
+
+ public IdComponent()
+ {
+ Value = ushort.MaxValue;
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Common/IdComponent.cs.meta b/Assets/Sources/Common/IdComponent.cs.meta
new file mode 100644
index 0000000..ace3520
--- /dev/null
+++ b/Assets/Sources/Common/IdComponent.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 929e1b29b0c54929af5b04cfe641591b
+timeCreated: 1556835251
\ No newline at end of file
diff --git a/Assets/Sources/CommonGeneratedFeature.cs b/Assets/Sources/CommonGeneratedFeature.cs
new file mode 100644
index 0000000..cebb84b
--- /dev/null
+++ b/Assets/Sources/CommonGeneratedFeature.cs
@@ -0,0 +1,8 @@
+public class CommonGeneratedFeature : Feature
+{
+ public CommonGeneratedFeature(Contexts contexts)
+ {
+ Add(new GameEventSystems(contexts));
+ Add(new GameCleanupSystems(contexts));
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/CommonGeneratedFeature.cs.meta b/Assets/Sources/CommonGeneratedFeature.cs.meta
new file mode 100644
index 0000000..cb8f062
--- /dev/null
+++ b/Assets/Sources/CommonGeneratedFeature.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 410fcdef53cd4afca6a7005f26e7f0a2
+timeCreated: 1557759807
\ No newline at end of file
diff --git a/Assets/Sources/GameController.cs b/Assets/Sources/GameController.cs
new file mode 100644
index 0000000..8bf2e7e
--- /dev/null
+++ b/Assets/Sources/GameController.cs
@@ -0,0 +1,270 @@
+using System;
+using System.Collections.Generic;
+using ENet;
+using Entitas;
+using Sources.Networking.Client;
+using Sources.Networking.Server;
+using UnityEngine;
+using Random = UnityEngine.Random;
+
+public class GameController : MonoBehaviour
+{
+ public static GameController I;
+ [NonSerialized] public Mode Mode = Mode.Inactive;
+
+ [Header("Server")] public int TargetTickPerSecond = 20;
+
+ [Header("Client")] public int PanicStateCount = 10;
+ public int PanicCleanupTarget = 6;
+
+ private IGroup _connectionsGroup;
+ private readonly List _connectionsBuffer = new List(ServerNetworkSystem.MaxPlayers);
+
+ private Contexts _contexts;
+
+ private ClientNetworkSystem _client;
+ private ClientFeature _clientFeature;
+
+ private ServerNetworkSystem _server;
+ private ServerFeature _serverFeature;
+
+ private int _tickCount;
+ private ushort _tickrate = 10;
+ private float _timer = 1f;
+ private int _totalTicksThisSecond;
+
+ private string _ip = "192.168.1.1";
+ private float _lastUpdate;
+ private string _message = "";
+ private ushort _port = 9500;
+
+ private int _lastId;
+
+ private void Awake()
+ {
+ I = this;
+ Library.Initialize();
+
+ _contexts = Contexts.sharedInstance;
+ _connectionsGroup = _contexts.game.GetGroup(GameMatcher.Connection);
+ _lastUpdate = Time.realtimeSinceStartup;
+ }
+
+ public void StartServer()
+ {
+ if (Mode != Mode.Inactive)
+ throw new ApplicationException("Can't start server if already active.");
+
+ SetupHooks(_contexts);
+
+ _server = new ServerNetworkSystem(_contexts);
+ _server.TickRate = (ushort) TargetTickPerSecond;
+
+ var services = new Services
+ {
+ ServerSystem = _server
+ };
+
+ _serverFeature = new ServerFeature(_contexts, services);
+ Mode = Mode.Server;
+ }
+
+ public void StartClient()
+ {
+ if (Mode != Mode.Inactive)
+ throw new ApplicationException("Can't start client if already active.");
+
+ _client = new ClientNetworkSystem(_contexts);
+ _client.TickRate = (ushort) TargetTickPerSecond;
+ _client.PanicStateCount = PanicStateCount;
+ _client.PanicCleanupTarget = PanicCleanupTarget;
+
+ var services = new Services
+ {
+ ClientSystem = _client
+ };
+
+ _clientFeature = new ClientFeature(_contexts, services);
+ Mode = Mode.Client;
+ }
+
+ private void Update()
+ {
+ switch (Mode)
+ {
+ case Mode.Server:
+ TargetTickPerSecond = _server.TickRate;
+ break;
+ case Mode.Client:
+ TargetTickPerSecond = _client.TickRate;
+ break;
+ }
+
+ while (_lastUpdate < Time.realtimeSinceStartup)
+ {
+ _lastUpdate += 1f / TargetTickPerSecond;
+ _tickCount++;
+ switch (Mode)
+ {
+ case Mode.Server:
+ _server.Execute();
+ _serverFeature.Execute();
+ _serverFeature.Cleanup();
+ break;
+ case Mode.Client:
+ _client.UpdateNetwork();
+ _client.Execute();
+ _clientFeature.Execute();
+ _clientFeature.Cleanup();
+ break;
+ }
+ }
+
+ _timer -= Time.deltaTime;
+ if (_timer < 0f)
+ {
+ _totalTicksThisSecond = _tickCount;
+ _tickCount = 0;
+ _timer += 1;
+ }
+ }
+
+ private void OnGUI()
+ {
+ GUILayout.Label($"TPS {_totalTicksThisSecond}");
+ switch (Mode)
+ {
+ case Mode.Inactive:
+ if (GUILayout.Button("Setup Server")) StartServer();
+ if (GUILayout.Button("Setup Client")) StartClient();
+ break;
+ case Mode.Server:
+ switch (_server.State)
+ {
+ case ServerState.Stopped:
+ GUILayout.Label("Server stopped");
+ GUILayout.BeginHorizontal();
+ _ip = GUILayout.TextField(_ip, GUILayout.Width(120));
+ var tmp =
+ GUILayout.TextField(_port.ToString(), GUILayout.Width(60));
+ if (ushort.TryParse(tmp, out var result)) _port = result;
+ if (GUILayout.Button("Start!"))
+ {
+ var address = new Address();
+ address.Port = _port;
+ address.SetHost(_ip);
+ _server.StartServer(address);
+ }
+
+ GUILayout.EndHorizontal();
+ if (GUILayout.Button("localhost")) _ip = "localhost";
+ break;
+ case ServerState.Starting:
+ GUILayout.Label("Server starting");
+ break;
+ case ServerState.Working:
+ GUILayout.Label("Server working");
+ if (GUILayout.Button("Stop!")) _server.StopServer();
+ break;
+ case ServerState.Stopping:
+ GUILayout.Label("Server stopping");
+ break;
+ }
+
+ break;
+ case Mode.Client:
+ switch (_client.State)
+ {
+ case ClientState.Disconnected:
+ GUILayout.Label("Disconnected");
+ GUILayout.BeginHorizontal();
+ _ip = GUILayout.TextField(_ip, GUILayout.Width(120));
+ var tmp =
+ GUILayout.TextField(_port.ToString(), GUILayout.Width(60));
+ if (ushort.TryParse(tmp, out var result)) _port = result;
+ if (GUILayout.Button("Connect!"))
+ {
+ var address = new Address();
+ address.Port = _port;
+ address.SetHost(_ip);
+ _client.Connect(address);
+ }
+
+ GUILayout.EndHorizontal();
+ if (GUILayout.Button("localhost")) _ip = "localhost";
+ break;
+ case ClientState.Connecting:
+ GUILayout.Label("Connecting");
+ if (GUILayout.Button("Cancel")) _client.EnqueueRequest(NetworkThreadRequest.CancelConnect);
+ break;
+ case ClientState.WaitingForId:
+ GUILayout.Label("WaitingForId");
+ break;
+ case ClientState.Connected:
+ GUILayout.BeginHorizontal();
+ GUILayout.Label("Connected");
+ tmp = GUILayout.TextField(_tickrate.ToString(), GUILayout.Width(60));
+ if (ushort.TryParse(tmp, out result))
+ if (result > 0)
+ _tickrate = result;
+
+ if (GUILayout.Button("Set tickRate"))
+ _client.EnqueueCommand(new ClientSetTickrateCommand {Tickrate = _tickrate});
+
+ var str = "States :";
+ for (var i = 0; i < _client.StatesCount; i++) str += "#";
+ GUILayout.Label(str);
+ GUILayout.EndHorizontal();
+
+ GUILayout.BeginHorizontal();
+ _message = GUILayout.TextField(_message, GUILayout.Width(120));
+ if (GUILayout.Button("Send message"))
+ _client.EnqueueCommand(new ClientChatMessageCommand {Message = _message});
+ if (GUILayout.Button("Request character"))
+ _client.EnqueueCommand(new ClientRequestCharacterCommand());
+ GUILayout.EndHorizontal();
+ if (GUILayout.Button("Disconnect")) _client.Disconnect();
+ break;
+ case ClientState.Disconnecting:
+ GUILayout.Label("Disconnecting");
+ break;
+ }
+
+ break;
+ }
+ }
+
+ private void OnDestroy()
+ {
+ switch (Mode)
+ {
+ case Mode.Server:
+ _server.TearDown();
+ _serverFeature.TearDown();
+ break;
+ case Mode.Client:
+ _client.TearDown();
+ _clientFeature.TearDown();
+ break;
+ }
+
+ Library.Deinitialize();
+ }
+
+ private void SetupHooks(Contexts contexts)
+ {
+ contexts.Reset();
+ contexts.game.OnEntityCreated += (context, entity) =>
+ {
+ ((GameEntity) entity).AddId((ushort) _lastId);
+ _lastId++;
+ };
+ }
+}
+
+public enum Mode
+{
+ Inactive,
+ Server,
+ Client
+}
\ No newline at end of file
diff --git a/Assets/Sources/GameController.cs.meta b/Assets/Sources/GameController.cs.meta
new file mode 100644
index 0000000..3400457
--- /dev/null
+++ b/Assets/Sources/GameController.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: dbbbddda32854a78aa149317fbcf6c63
+timeCreated: 1556835320
\ No newline at end of file
diff --git a/Assets/Sources/Gameplay.meta b/Assets/Sources/Gameplay.meta
new file mode 100644
index 0000000..240f751
--- /dev/null
+++ b/Assets/Sources/Gameplay.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a459d548064819d4faeac7e9959bea15
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Gameplay/Cleanup.meta b/Assets/Sources/Gameplay/Cleanup.meta
new file mode 100644
index 0000000..c7156d3
--- /dev/null
+++ b/Assets/Sources/Gameplay/Cleanup.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 4a3819cbfe421ef4591ed8beade42d2f
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Gameplay/Cleanup/DestroyDestroyedGameSystem.cs b/Assets/Sources/Gameplay/Cleanup/DestroyDestroyedGameSystem.cs
new file mode 100644
index 0000000..76933f3
--- /dev/null
+++ b/Assets/Sources/Gameplay/Cleanup/DestroyDestroyedGameSystem.cs
@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+using Entitas;
+
+public sealed class DestroyDestroyedGameSystem : ICleanupSystem {
+
+ readonly IGroup _group;
+ readonly List _buffer = new List();
+
+ public DestroyDestroyedGameSystem(Contexts contexts) {
+ _group = contexts.game.GetGroup(GameMatcher.Destroyed);
+ }
+
+ public void Cleanup() {
+ foreach (var e in _group.GetEntities(_buffer)) {
+ e.Destroy();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Gameplay/Cleanup/DestroyDestroyedGameSystem.cs.meta b/Assets/Sources/Gameplay/Cleanup/DestroyDestroyedGameSystem.cs.meta
new file mode 100644
index 0000000..3b3b453
--- /dev/null
+++ b/Assets/Sources/Gameplay/Cleanup/DestroyDestroyedGameSystem.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 1031de9a0e542604aa6c82fd62743636
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Gameplay/Cleanup/GameCleanupSystems.cs b/Assets/Sources/Gameplay/Cleanup/GameCleanupSystems.cs
new file mode 100644
index 0000000..bfa6b25
--- /dev/null
+++ b/Assets/Sources/Gameplay/Cleanup/GameCleanupSystems.cs
@@ -0,0 +1,6 @@
+public sealed class GameCleanupSystems : Feature {
+
+ public GameCleanupSystems(Contexts contexts) {
+ Add(new DestroyDestroyedGameSystem(contexts));
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Gameplay/Cleanup/GameCleanupSystems.cs.meta b/Assets/Sources/Gameplay/Cleanup/GameCleanupSystems.cs.meta
new file mode 100644
index 0000000..5835dd7
--- /dev/null
+++ b/Assets/Sources/Gameplay/Cleanup/GameCleanupSystems.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a98d0021cf2dc2a44961d60da2b77009
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Gameplay/Client.meta b/Assets/Sources/Gameplay/Client.meta
new file mode 100644
index 0000000..bd24e41
--- /dev/null
+++ b/Assets/Sources/Gameplay/Client.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: ce4bd5193e9442f6bf0b0dfe28c3b1ad
+timeCreated: 1557775740
\ No newline at end of file
diff --git a/Assets/Sources/Gameplay/ClientGameplayFeature.cs b/Assets/Sources/Gameplay/ClientGameplayFeature.cs
new file mode 100644
index 0000000..ab6b236
--- /dev/null
+++ b/Assets/Sources/Gameplay/ClientGameplayFeature.cs
@@ -0,0 +1,6 @@
+public class ClientGameplayFeature : Feature
+{
+ public ClientGameplayFeature(Contexts contexts, Services services)
+ {
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Gameplay/ClientGameplayFeature.cs.meta b/Assets/Sources/Gameplay/ClientGameplayFeature.cs.meta
new file mode 100644
index 0000000..0091a09
--- /dev/null
+++ b/Assets/Sources/Gameplay/ClientGameplayFeature.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 60fe02e654cc4660b676ecd8b1c434d0
+timeCreated: 1557775928
\ No newline at end of file
diff --git a/Assets/Sources/Gameplay/Common.meta b/Assets/Sources/Gameplay/Common.meta
new file mode 100644
index 0000000..2149a62
--- /dev/null
+++ b/Assets/Sources/Gameplay/Common.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: ce47a1fe8d0c48dbbe92e88b368be477
+timeCreated: 1557775724
\ No newline at end of file
diff --git a/Assets/Sources/Gameplay/CommonGameplayFeature.cs b/Assets/Sources/Gameplay/CommonGameplayFeature.cs
new file mode 100644
index 0000000..77e3f51
--- /dev/null
+++ b/Assets/Sources/Gameplay/CommonGameplayFeature.cs
@@ -0,0 +1,6 @@
+public class CommonGameplayFeature : Feature
+{
+ public CommonGameplayFeature(Contexts contexts, Services services)
+ {
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Gameplay/CommonGameplayFeature.cs.meta b/Assets/Sources/Gameplay/CommonGameplayFeature.cs.meta
new file mode 100644
index 0000000..f8647b2
--- /dev/null
+++ b/Assets/Sources/Gameplay/CommonGameplayFeature.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 2c6135d09f474085ade568535be751c9
+timeCreated: 1557776025
\ No newline at end of file
diff --git a/Assets/Sources/Gameplay/Server.meta b/Assets/Sources/Gameplay/Server.meta
new file mode 100644
index 0000000..67f5249
--- /dev/null
+++ b/Assets/Sources/Gameplay/Server.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 26daafa7f2094000b01d40d7886cc47b
+timeCreated: 1557775731
\ No newline at end of file
diff --git a/Assets/Sources/Gameplay/Server/Character.meta b/Assets/Sources/Gameplay/Server/Character.meta
new file mode 100644
index 0000000..f6cded9
--- /dev/null
+++ b/Assets/Sources/Gameplay/Server/Character.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: add92519f9da47a8be206bf303ae2682
+timeCreated: 1558107065
\ No newline at end of file
diff --git a/Assets/Sources/Gameplay/Server/Character/Character.cs b/Assets/Sources/Gameplay/Server/Character/Character.cs
new file mode 100644
index 0000000..946ebf6
--- /dev/null
+++ b/Assets/Sources/Gameplay/Server/Character/Character.cs
@@ -0,0 +1,8 @@
+using Codegen.CodegenAttributes;
+using Entitas;
+
+[Game]
+[Sync]
+public partial class Character : IComponent
+{
+}
\ No newline at end of file
diff --git a/Assets/Sources/Gameplay/Server/Character/Character.cs.meta b/Assets/Sources/Gameplay/Server/Character/Character.cs.meta
new file mode 100644
index 0000000..d84c32b
--- /dev/null
+++ b/Assets/Sources/Gameplay/Server/Character/Character.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 7d6250aee6fc478cbf00a4b87a2265ff
+timeCreated: 1558107070
\ No newline at end of file
diff --git a/Assets/Sources/Gameplay/Server/Character/ControlledBy.cs b/Assets/Sources/Gameplay/Server/Character/ControlledBy.cs
new file mode 100644
index 0000000..db07e87
--- /dev/null
+++ b/Assets/Sources/Gameplay/Server/Character/ControlledBy.cs
@@ -0,0 +1,10 @@
+using Codegen.CodegenAttributes;
+using Entitas;
+using Entitas.CodeGeneration.Attributes;
+
+[Game]
+[Sync]
+public partial class ControlledBy : IComponent
+{
+ [PrimaryEntityIndex] public ushort Value;
+}
\ No newline at end of file
diff --git a/Assets/Sources/Gameplay/Server/Character/ControlledBy.cs.meta b/Assets/Sources/Gameplay/Server/Character/ControlledBy.cs.meta
new file mode 100644
index 0000000..3f61c5c
--- /dev/null
+++ b/Assets/Sources/Gameplay/Server/Character/ControlledBy.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 6e64bdea8db349a5bfe64490ce656e0d
+timeCreated: 1558107120
\ No newline at end of file
diff --git a/Assets/Sources/Gameplay/ServerGameplayFeature.cs b/Assets/Sources/Gameplay/ServerGameplayFeature.cs
new file mode 100644
index 0000000..4570ca6
--- /dev/null
+++ b/Assets/Sources/Gameplay/ServerGameplayFeature.cs
@@ -0,0 +1,6 @@
+public class ServerGameplayFeature : Feature
+{
+ public ServerGameplayFeature(Contexts contexts, Services services)
+ {
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Gameplay/ServerGameplayFeature.cs.meta b/Assets/Sources/Gameplay/ServerGameplayFeature.cs.meta
new file mode 100644
index 0000000..f02dd2e
--- /dev/null
+++ b/Assets/Sources/Gameplay/ServerGameplayFeature.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: ed61ffd1840f4e52ba1d7b308145a0dc
+timeCreated: 1557775992
\ No newline at end of file
diff --git a/Assets/Sources/Generated.meta b/Assets/Sources/Generated.meta
new file mode 100644
index 0000000..218e744
--- /dev/null
+++ b/Assets/Sources/Generated.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 2b068ead1c3f5d54eb74f04148a25d08
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Command.meta b/Assets/Sources/Generated/Command.meta
new file mode 100644
index 0000000..77259e4
--- /dev/null
+++ b/Assets/Sources/Generated/Command.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c9ceef8a286f46a4b9fe205d7fd61f11
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Command/Client.meta b/Assets/Sources/Generated/Command/Client.meta
new file mode 100644
index 0000000..486f852
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Client.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5e3d5da0ebf3dd84b9eaec269e3fbee2
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Command/Client/ChatMessageCommand.cs b/Assets/Sources/Generated/Command/Client/ChatMessageCommand.cs
new file mode 100644
index 0000000..06ffe86
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Client/ChatMessageCommand.cs
@@ -0,0 +1,17 @@
+using NetStack.Serialization;
+
+public struct ClientChatMessageCommand : ICommand, IClientCommand
+{
+ public System.String Message;
+ public void Serialize(BitBuffer bitBuffer)
+ {
+ bitBuffer.AddUShort(0);
+
+ bitBuffer.AddString(Message);
+ }
+
+ public void Deserialize(BitBuffer bitBuffer)
+ {
+ Message = bitBuffer.ReadString();
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Command/Client/ChatMessageCommand.cs.meta b/Assets/Sources/Generated/Command/Client/ChatMessageCommand.cs.meta
new file mode 100644
index 0000000..ce91369
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Client/ChatMessageCommand.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b9a6c41b5ff5467479f6f8105f68393e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Command/Client/RequestCharacterCommand.cs b/Assets/Sources/Generated/Command/Client/RequestCharacterCommand.cs
new file mode 100644
index 0000000..6f9e109
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Client/RequestCharacterCommand.cs
@@ -0,0 +1,14 @@
+using NetStack.Serialization;
+
+public struct ClientRequestCharacterCommand : ICommand, IClientCommand
+{
+ public void Serialize(BitBuffer bitBuffer)
+ {
+ bitBuffer.AddUShort(1);
+
+ }
+
+ public void Deserialize(BitBuffer bitBuffer)
+ {
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Command/Client/RequestCharacterCommand.cs.meta b/Assets/Sources/Generated/Command/Client/RequestCharacterCommand.cs.meta
new file mode 100644
index 0000000..a0b8910
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Client/RequestCharacterCommand.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3bcaeb854aef90449887d074aeb6f9c9
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Command/Client/SetTickrateCommand.cs b/Assets/Sources/Generated/Command/Client/SetTickrateCommand.cs
new file mode 100644
index 0000000..e213981
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Client/SetTickrateCommand.cs
@@ -0,0 +1,17 @@
+using NetStack.Serialization;
+
+public struct ClientSetTickrateCommand : ICommand, IClientCommand
+{
+ public System.UInt16 Tickrate;
+ public void Serialize(BitBuffer bitBuffer)
+ {
+ bitBuffer.AddUShort(2);
+
+ bitBuffer.AddUShort(Tickrate);
+ }
+
+ public void Deserialize(BitBuffer bitBuffer)
+ {
+ Tickrate = bitBuffer.ReadUShort();
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Command/Client/SetTickrateCommand.cs.meta b/Assets/Sources/Generated/Command/Client/SetTickrateCommand.cs.meta
new file mode 100644
index 0000000..7016fd0
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Client/SetTickrateCommand.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 1caa3b54131741c45af9ebe904e37b06
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Command/Compressors.meta b/Assets/Sources/Generated/Command/Compressors.meta
new file mode 100644
index 0000000..c126871
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Compressors.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 66079a72588ae4c4683dc879c97d5e24
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Command/Compressors/SyncCompressors.cs b/Assets/Sources/Generated/Command/Compressors/SyncCompressors.cs
new file mode 100644
index 0000000..dfa4dcc
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Compressors/SyncCompressors.cs
@@ -0,0 +1,9 @@
+using NetStack.Compression;
+
+public static class CommandCompressors
+{
+
+ static CommandCompressors()
+ {
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Command/Compressors/SyncCompressors.cs.meta b/Assets/Sources/Generated/Command/Compressors/SyncCompressors.cs.meta
new file mode 100644
index 0000000..690ddaa
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Compressors/SyncCompressors.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4851cb22edcf4ba4e87310230be6ecfd
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Command/Execution.meta b/Assets/Sources/Generated/Command/Execution.meta
new file mode 100644
index 0000000..0301c1b
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Execution.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 2cbb8536ae171ae4a8a7074e91c541d9
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Command/Execution/ClientCommandExecutor.cs b/Assets/Sources/Generated/Command/Execution/ClientCommandExecutor.cs
new file mode 100644
index 0000000..27f18d4
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Execution/ClientCommandExecutor.cs
@@ -0,0 +1,43 @@
+using NetStack.Serialization;
+using Sources.Tools;
+
+public static class ClientCommandExecutor
+{
+ public static void Execute(IClientHandler handler, BitBuffer buffer, ushort commandCount)
+ {
+ for (int i = 0; i < commandCount; i++)
+ {
+ var commandId = buffer.ReadUShort();
+ switch (commandId)
+ {
+
+ case 0:
+ {
+ Logger.I.Log("ClientCommandExecutor", "Executing ServerChatMessageCommand");
+ var c = new ServerChatMessageCommand();
+ c.Deserialize(buffer);
+ handler.HandleChatMessageCommand(ref c);
+ break;
+ }
+
+ case 1:
+ {
+ Logger.I.Log("ClientCommandExecutor", "Executing ServerGrantedIdCommand");
+ var c = new ServerGrantedIdCommand();
+ c.Deserialize(buffer);
+ handler.HandleGrantedIdCommand(ref c);
+ break;
+ }
+
+ case 2:
+ {
+ Logger.I.Log("ClientCommandExecutor", "Executing ServerSetTickrateCommand");
+ var c = new ServerSetTickrateCommand();
+ c.Deserialize(buffer);
+ handler.HandleSetTickrateCommand(ref c);
+ break;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Command/Execution/ClientCommandExecutor.cs.meta b/Assets/Sources/Generated/Command/Execution/ClientCommandExecutor.cs.meta
new file mode 100644
index 0000000..08a38dc
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Execution/ClientCommandExecutor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ae152834dfbf07a4982e3c86ba2a5f5a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Command/Execution/IClientHandler.cs b/Assets/Sources/Generated/Command/Execution/IClientHandler.cs
new file mode 100644
index 0000000..33b1a8f
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Execution/IClientHandler.cs
@@ -0,0 +1,8 @@
+public interface IClientHandler
+{
+ void HandleChatMessageCommand(ref ServerChatMessageCommand command);
+ void HandleGrantedIdCommand(ref ServerGrantedIdCommand command);
+ void HandleSetTickrateCommand(ref ServerSetTickrateCommand command);
+}
+
+public interface IClientCommand{}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Command/Execution/IClientHandler.cs.meta b/Assets/Sources/Generated/Command/Execution/IClientHandler.cs.meta
new file mode 100644
index 0000000..52948e3
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Execution/IClientHandler.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f185a23acafaebc4889899f003aeca13
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Command/Execution/IServerHandler.cs b/Assets/Sources/Generated/Command/Execution/IServerHandler.cs
new file mode 100644
index 0000000..89f4b28
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Execution/IServerHandler.cs
@@ -0,0 +1,8 @@
+public interface IServerHandler
+{
+ void HandleChatMessageCommand(ref ClientChatMessageCommand command);
+ void HandleRequestCharacterCommand(ref ClientRequestCharacterCommand command);
+ void HandleSetTickrateCommand(ref ClientSetTickrateCommand command);
+}
+
+public interface IServerCommand{}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Command/Execution/IServerHandler.cs.meta b/Assets/Sources/Generated/Command/Execution/IServerHandler.cs.meta
new file mode 100644
index 0000000..d59797e
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Execution/IServerHandler.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4bac11dfd945caa459dcb90879e764f7
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Command/Execution/ServerCommandExecutor.cs b/Assets/Sources/Generated/Command/Execution/ServerCommandExecutor.cs
new file mode 100644
index 0000000..bac9c18
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Execution/ServerCommandExecutor.cs
@@ -0,0 +1,43 @@
+using NetStack.Serialization;
+using Sources.Tools;
+
+public static class ServerCommandExecutor
+{
+ public static void Execute(IServerHandler handler, BitBuffer buffer, ushort commandCount)
+ {
+ for (int i = 0; i < commandCount; i++)
+ {
+ var commandId = buffer.ReadUShort();
+ switch (commandId)
+ {
+
+ case 0:
+ {
+ Logger.I.Log("ServerCommandExecutor", "Executing ClientChatMessageCommand");
+ var c = new ClientChatMessageCommand();
+ c.Deserialize(buffer);
+ handler.HandleChatMessageCommand(ref c);
+ break;
+ }
+
+ case 1:
+ {
+ Logger.I.Log("ServerCommandExecutor", "Executing ClientRequestCharacterCommand");
+ var c = new ClientRequestCharacterCommand();
+ c.Deserialize(buffer);
+ handler.HandleRequestCharacterCommand(ref c);
+ break;
+ }
+
+ case 2:
+ {
+ Logger.I.Log("ServerCommandExecutor", "Executing ClientSetTickrateCommand");
+ var c = new ClientSetTickrateCommand();
+ c.Deserialize(buffer);
+ handler.HandleSetTickrateCommand(ref c);
+ break;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Command/Execution/ServerCommandExecutor.cs.meta b/Assets/Sources/Generated/Command/Execution/ServerCommandExecutor.cs.meta
new file mode 100644
index 0000000..7cd23a8
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Execution/ServerCommandExecutor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b32e8bc56c359104abbe05d4946fd74d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Command/Server.meta b/Assets/Sources/Generated/Command/Server.meta
new file mode 100644
index 0000000..ad920d0
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Server.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a89b58cc54c3ee74fb07528eca827228
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Command/Server/ChatMessageCommand.cs b/Assets/Sources/Generated/Command/Server/ChatMessageCommand.cs
new file mode 100644
index 0000000..1a04d54
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Server/ChatMessageCommand.cs
@@ -0,0 +1,20 @@
+using NetStack.Serialization;
+
+public struct ServerChatMessageCommand : ICommand, IServerCommand
+{
+ public System.String Message;
+ public System.UInt16 Sender;
+ public void Serialize(BitBuffer bitBuffer)
+ {
+ bitBuffer.AddUShort(0);
+
+ bitBuffer.AddString(Message);
+ bitBuffer.AddUShort(Sender);
+ }
+
+ public void Deserialize(BitBuffer bitBuffer)
+ {
+ Message = bitBuffer.ReadString();
+ Sender = bitBuffer.ReadUShort();
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Command/Server/ChatMessageCommand.cs.meta b/Assets/Sources/Generated/Command/Server/ChatMessageCommand.cs.meta
new file mode 100644
index 0000000..770926f
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Server/ChatMessageCommand.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5211e1d87b1728b4bb7a618fb612ed09
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Command/Server/GrantedIdCommand.cs b/Assets/Sources/Generated/Command/Server/GrantedIdCommand.cs
new file mode 100644
index 0000000..499779d
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Server/GrantedIdCommand.cs
@@ -0,0 +1,17 @@
+using NetStack.Serialization;
+
+public struct ServerGrantedIdCommand : ICommand, IServerCommand
+{
+ public System.UInt16 Id;
+ public void Serialize(BitBuffer bitBuffer)
+ {
+ bitBuffer.AddUShort(1);
+
+ bitBuffer.AddUShort(Id);
+ }
+
+ public void Deserialize(BitBuffer bitBuffer)
+ {
+ Id = bitBuffer.ReadUShort();
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Command/Server/GrantedIdCommand.cs.meta b/Assets/Sources/Generated/Command/Server/GrantedIdCommand.cs.meta
new file mode 100644
index 0000000..66bac0b
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Server/GrantedIdCommand.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ab0d8d88cbd960f478a1c2cfc30b422d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Command/Server/SetTickrateCommand.cs b/Assets/Sources/Generated/Command/Server/SetTickrateCommand.cs
new file mode 100644
index 0000000..aed523e
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Server/SetTickrateCommand.cs
@@ -0,0 +1,17 @@
+using NetStack.Serialization;
+
+public struct ServerSetTickrateCommand : ICommand, IServerCommand
+{
+ public System.UInt16 Tickrate;
+ public void Serialize(BitBuffer bitBuffer)
+ {
+ bitBuffer.AddUShort(2);
+
+ bitBuffer.AddUShort(Tickrate);
+ }
+
+ public void Deserialize(BitBuffer bitBuffer)
+ {
+ Tickrate = bitBuffer.ReadUShort();
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Command/Server/SetTickrateCommand.cs.meta b/Assets/Sources/Generated/Command/Server/SetTickrateCommand.cs.meta
new file mode 100644
index 0000000..a0843ad
--- /dev/null
+++ b/Assets/Sources/Generated/Command/Server/SetTickrateCommand.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7d197b5ff57fa8c49a60c25eb679973e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync.meta b/Assets/Sources/Generated/Sync.meta
new file mode 100644
index 0000000..0d25511
--- /dev/null
+++ b/Assets/Sources/Generated/Sync.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a051aa1e17d55d74cb8de545e492b667
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Capture.meta b/Assets/Sources/Generated/Sync/Capture.meta
new file mode 100644
index 0000000..ba1d43c
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: aef0405c7e145b84ebe7f844e8b38e11
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedCharacterSystem.cs b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedCharacterSystem.cs
new file mode 100644
index 0000000..f7b9069
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedCharacterSystem.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using Entitas;
+using Sources.Networking.Server;
+
+
+public class ServerCaptureChangedCharacterSystem : ReactiveSystem
+{
+ private readonly ServerNetworkSystem _server;
+ public ServerCaptureChangedCharacterSystem (Contexts contexts, Services services) : base(contexts.game)
+ {
+ _server = services.ServerSystem;
+ }
+
+ protected override ICollector GetTrigger(IContext context) {
+ return context.CreateCollector(GameMatcher.Character.Added());
+ }
+
+ protected override bool Filter(GameEntity entity)
+ {
+ return !entity.isDestroyed && entity.isWasSynced && entity.isCharacter;
+ }
+
+ protected override void Execute(List entities) {
+ if (_server.State != ServerState.Working) return;
+
+ foreach (var e in entities) {
+ _server.ChangedComponents.AddUShort(e.id.Value);
+ _server.ChangedComponents.AddUShort(1);
+ _server.ChangedComponentsCount++;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedCharacterSystem.cs.meta b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedCharacterSystem.cs.meta
new file mode 100644
index 0000000..15f24a3
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedCharacterSystem.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 636d0e1ffa182b24f9cecdb486fd2fb9
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedConnectionSystem.cs b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedConnectionSystem.cs
new file mode 100644
index 0000000..de920e9
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedConnectionSystem.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using Entitas;
+using Sources.Networking.Server;
+
+
+public class ServerCaptureChangedConnectionSystem : ReactiveSystem
+{
+ private readonly ServerNetworkSystem _server;
+ public ServerCaptureChangedConnectionSystem (Contexts contexts, Services services) : base(contexts.game)
+ {
+ _server = services.ServerSystem;
+ }
+
+ protected override ICollector GetTrigger(IContext context) {
+ return context.CreateCollector(GameMatcher.Connection.Added());
+ }
+
+ protected override bool Filter(GameEntity entity)
+ {
+ return !entity.isDestroyed && entity.isWasSynced && entity.hasConnection;
+ }
+
+ protected override void Execute(List entities) {
+ if (_server.State != ServerState.Working) return;
+
+ foreach (var e in entities) {
+ _server.ChangedComponents.AddUShort(e.id.Value);
+ e.connection.Serialize(_server.ChangedComponents);
+ _server.ChangedComponentsCount++;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedConnectionSystem.cs.meta b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedConnectionSystem.cs.meta
new file mode 100644
index 0000000..d6d328d
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedConnectionSystem.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c393bad8a325ed841821b2f15b5d8e5a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedControlledBySystem.cs b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedControlledBySystem.cs
new file mode 100644
index 0000000..ac77266
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedControlledBySystem.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using Entitas;
+using Sources.Networking.Server;
+
+
+public class ServerCaptureChangedControlledBySystem : ReactiveSystem
+{
+ private readonly ServerNetworkSystem _server;
+ public ServerCaptureChangedControlledBySystem (Contexts contexts, Services services) : base(contexts.game)
+ {
+ _server = services.ServerSystem;
+ }
+
+ protected override ICollector GetTrigger(IContext context) {
+ return context.CreateCollector(GameMatcher.ControlledBy.Added());
+ }
+
+ protected override bool Filter(GameEntity entity)
+ {
+ return !entity.isDestroyed && entity.isWasSynced && entity.hasControlledBy;
+ }
+
+ protected override void Execute(List entities) {
+ if (_server.State != ServerState.Working) return;
+
+ foreach (var e in entities) {
+ _server.ChangedComponents.AddUShort(e.id.Value);
+ e.controlledBy.Serialize(_server.ChangedComponents);
+ _server.ChangedComponentsCount++;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedControlledBySystem.cs.meta b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedControlledBySystem.cs.meta
new file mode 100644
index 0000000..0a857db
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedControlledBySystem.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ff531dfa0001c0544aa1001e4ef43f78
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedIdSystem.cs b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedIdSystem.cs
new file mode 100644
index 0000000..3112569
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedIdSystem.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using Entitas;
+using Sources.Networking.Server;
+
+
+public class ServerCaptureChangedIdSystem : ReactiveSystem
+{
+ private readonly ServerNetworkSystem _server;
+ public ServerCaptureChangedIdSystem (Contexts contexts, Services services) : base(contexts.game)
+ {
+ _server = services.ServerSystem;
+ }
+
+ protected override ICollector GetTrigger(IContext context) {
+ return context.CreateCollector(GameMatcher.Id.Added());
+ }
+
+ protected override bool Filter(GameEntity entity)
+ {
+ return !entity.isDestroyed && entity.isWasSynced && entity.hasId;
+ }
+
+ protected override void Execute(List entities) {
+ if (_server.State != ServerState.Working) return;
+
+ foreach (var e in entities) {
+ _server.ChangedComponents.AddUShort(e.id.Value);
+ e.id.Serialize(_server.ChangedComponents);
+ _server.ChangedComponentsCount++;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedIdSystem.cs.meta b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedIdSystem.cs.meta
new file mode 100644
index 0000000..8d33873
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedIdSystem.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: fd87814bfd1322542a74e8c71be6ccd7
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedSyncSystem.cs b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedSyncSystem.cs
new file mode 100644
index 0000000..47933f1
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedSyncSystem.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using Entitas;
+using Sources.Networking.Server;
+
+
+public class ServerCaptureChangedSyncSystem : ReactiveSystem
+{
+ private readonly ServerNetworkSystem _server;
+ public ServerCaptureChangedSyncSystem (Contexts contexts, Services services) : base(contexts.game)
+ {
+ _server = services.ServerSystem;
+ }
+
+ protected override ICollector GetTrigger(IContext context) {
+ return context.CreateCollector(GameMatcher.Sync.Added());
+ }
+
+ protected override bool Filter(GameEntity entity)
+ {
+ return !entity.isDestroyed && entity.isWasSynced && entity.isSync;
+ }
+
+ protected override void Execute(List entities) {
+ if (_server.State != ServerState.Working) return;
+
+ foreach (var e in entities) {
+ _server.ChangedComponents.AddUShort(e.id.Value);
+ _server.ChangedComponents.AddUShort(4);
+ _server.ChangedComponentsCount++;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedSyncSystem.cs.meta b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedSyncSystem.cs.meta
new file mode 100644
index 0000000..a6d6f07
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureChangedSyncSystem.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c17a8b303444dca49a4b8e6903d5ab04
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedCharacterSystem.cs b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedCharacterSystem.cs
new file mode 100644
index 0000000..78950be
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedCharacterSystem.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using Entitas;
+using Sources.Networking.Server;
+
+public class ServerCaptureRemovedCharacterSystem : ReactiveSystem
+{
+ private readonly ServerNetworkSystem _server;
+ public ServerCaptureRemovedCharacterSystem (Contexts contexts, Services services) : base(contexts.game)
+ {
+ _server = services.ServerSystem;
+ }
+
+ protected override ICollector GetTrigger(IContext context) {
+ return context.CreateCollector(GameMatcher.Character.Removed());
+ }
+
+ protected override bool Filter(GameEntity entity)
+ {
+ return !entity.isDestroyed && entity.isWasSynced && entity.isCharacter;
+ }
+
+ protected override void Execute(List entities) {
+ if (_server.State != ServerState.Working) return;
+
+ foreach (var e in entities) {
+ _server.RemovedComponents.AddUShort(e.id.Value);
+ _server.RemovedComponents.AddUShort(1);
+ _server.RemovedComponentsCount++;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedCharacterSystem.cs.meta b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedCharacterSystem.cs.meta
new file mode 100644
index 0000000..a982701
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedCharacterSystem.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 932899bd60c3eb1458bb7ccb5a8edf48
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedConnectionSystem.cs b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedConnectionSystem.cs
new file mode 100644
index 0000000..5163a6a
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedConnectionSystem.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using Entitas;
+using Sources.Networking.Server;
+
+public class ServerCaptureRemovedConnectionSystem : ReactiveSystem
+{
+ private readonly ServerNetworkSystem _server;
+ public ServerCaptureRemovedConnectionSystem (Contexts contexts, Services services) : base(contexts.game)
+ {
+ _server = services.ServerSystem;
+ }
+
+ protected override ICollector GetTrigger(IContext context) {
+ return context.CreateCollector(GameMatcher.Connection.Removed());
+ }
+
+ protected override bool Filter(GameEntity entity)
+ {
+ return !entity.isDestroyed && entity.isWasSynced && !entity.hasConnection;
+ }
+
+ protected override void Execute(List entities) {
+ if (_server.State != ServerState.Working) return;
+
+ foreach (var e in entities) {
+ _server.RemovedComponents.AddUShort(e.id.Value);
+ _server.RemovedComponents.AddUShort(3);
+ _server.RemovedComponentsCount++;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedConnectionSystem.cs.meta b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedConnectionSystem.cs.meta
new file mode 100644
index 0000000..79a4c90
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedConnectionSystem.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5f80f69ef94173441977116e7bc1b988
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedControlledBySystem.cs b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedControlledBySystem.cs
new file mode 100644
index 0000000..da3dbb2
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedControlledBySystem.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using Entitas;
+using Sources.Networking.Server;
+
+public class ServerCaptureRemovedControlledBySystem : ReactiveSystem
+{
+ private readonly ServerNetworkSystem _server;
+ public ServerCaptureRemovedControlledBySystem (Contexts contexts, Services services) : base(contexts.game)
+ {
+ _server = services.ServerSystem;
+ }
+
+ protected override ICollector GetTrigger(IContext context) {
+ return context.CreateCollector(GameMatcher.ControlledBy.Removed());
+ }
+
+ protected override bool Filter(GameEntity entity)
+ {
+ return !entity.isDestroyed && entity.isWasSynced && !entity.hasControlledBy;
+ }
+
+ protected override void Execute(List entities) {
+ if (_server.State != ServerState.Working) return;
+
+ foreach (var e in entities) {
+ _server.RemovedComponents.AddUShort(e.id.Value);
+ _server.RemovedComponents.AddUShort(2);
+ _server.RemovedComponentsCount++;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedControlledBySystem.cs.meta b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedControlledBySystem.cs.meta
new file mode 100644
index 0000000..6ff3e9a
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedControlledBySystem.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9206889da990bb949a669328bcb27745
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedIdSystem.cs b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedIdSystem.cs
new file mode 100644
index 0000000..ac5fc3e
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedIdSystem.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using Entitas;
+using Sources.Networking.Server;
+
+public class ServerCaptureRemovedIdSystem : ReactiveSystem
+{
+ private readonly ServerNetworkSystem _server;
+ public ServerCaptureRemovedIdSystem (Contexts contexts, Services services) : base(contexts.game)
+ {
+ _server = services.ServerSystem;
+ }
+
+ protected override ICollector GetTrigger(IContext context) {
+ return context.CreateCollector(GameMatcher.Id.Removed());
+ }
+
+ protected override bool Filter(GameEntity entity)
+ {
+ return !entity.isDestroyed && entity.isWasSynced && !entity.hasId;
+ }
+
+ protected override void Execute(List entities) {
+ if (_server.State != ServerState.Working) return;
+
+ foreach (var e in entities) {
+ _server.RemovedComponents.AddUShort(e.id.Value);
+ _server.RemovedComponents.AddUShort(0);
+ _server.RemovedComponentsCount++;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedIdSystem.cs.meta b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedIdSystem.cs.meta
new file mode 100644
index 0000000..879efc0
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedIdSystem.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5d64118b099d86942a62628f13633cd2
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedSyncSystem.cs b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedSyncSystem.cs
new file mode 100644
index 0000000..2d7d195
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedSyncSystem.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using Entitas;
+using Sources.Networking.Server;
+
+public class ServerCaptureRemovedSyncSystem : ReactiveSystem
+{
+ private readonly ServerNetworkSystem _server;
+ public ServerCaptureRemovedSyncSystem (Contexts contexts, Services services) : base(contexts.game)
+ {
+ _server = services.ServerSystem;
+ }
+
+ protected override ICollector GetTrigger(IContext context) {
+ return context.CreateCollector(GameMatcher.Sync.Removed());
+ }
+
+ protected override bool Filter(GameEntity entity)
+ {
+ return !entity.isDestroyed && entity.isWasSynced && entity.isSync;
+ }
+
+ protected override void Execute(List entities) {
+ if (_server.State != ServerState.Working) return;
+
+ foreach (var e in entities) {
+ _server.RemovedComponents.AddUShort(e.id.Value);
+ _server.RemovedComponents.AddUShort(4);
+ _server.RemovedComponentsCount++;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedSyncSystem.cs.meta b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedSyncSystem.cs.meta
new file mode 100644
index 0000000..02f904c
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Capture/ServerCaptureRemovedSyncSystem.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c07c9a250da33b74786c75a9d208a37f
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Components.meta b/Assets/Sources/Generated/Sync/Components.meta
new file mode 100644
index 0000000..3c03239
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Components.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 61aef9424aa37ab4fa531201bfa1b728
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Components/Character.cs b/Assets/Sources/Generated/Sync/Components/Character.cs
new file mode 100644
index 0000000..6663e1d
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Components/Character.cs
@@ -0,0 +1,14 @@
+using NetStack.Serialization;
+
+public partial class Character : INetworkComponent
+{
+ public void Serialize(BitBuffer bitBuffer)
+ {
+ bitBuffer.AddUShort(1);
+
+ }
+
+ public void Deserialize(BitBuffer bitBuffer)
+ {
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Components/Character.cs.meta b/Assets/Sources/Generated/Sync/Components/Character.cs.meta
new file mode 100644
index 0000000..2aea38e
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Components/Character.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 127678bdb84643c4596d592076480bf6
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Components/Connection.cs b/Assets/Sources/Generated/Sync/Components/Connection.cs
new file mode 100644
index 0000000..4e7ebbf
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Components/Connection.cs
@@ -0,0 +1,16 @@
+using NetStack.Serialization;
+
+public partial class Connection : INetworkComponent
+{
+ public void Serialize(BitBuffer bitBuffer)
+ {
+ bitBuffer.AddUShort(3);
+
+ bitBuffer.AddUShort(Id);
+ }
+
+ public void Deserialize(BitBuffer bitBuffer)
+ {
+ Id = bitBuffer.ReadUShort();
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Components/Connection.cs.meta b/Assets/Sources/Generated/Sync/Components/Connection.cs.meta
new file mode 100644
index 0000000..6472751
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Components/Connection.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5e4f796d844b2d746988928ff7eb3834
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Components/ControlledBy.cs b/Assets/Sources/Generated/Sync/Components/ControlledBy.cs
new file mode 100644
index 0000000..12e93f9
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Components/ControlledBy.cs
@@ -0,0 +1,16 @@
+using NetStack.Serialization;
+
+public partial class ControlledBy : INetworkComponent
+{
+ public void Serialize(BitBuffer bitBuffer)
+ {
+ bitBuffer.AddUShort(2);
+
+ bitBuffer.AddUShort(Value);
+ }
+
+ public void Deserialize(BitBuffer bitBuffer)
+ {
+ Value = bitBuffer.ReadUShort();
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Components/ControlledBy.cs.meta b/Assets/Sources/Generated/Sync/Components/ControlledBy.cs.meta
new file mode 100644
index 0000000..9973ca5
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Components/ControlledBy.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e7ed7ca713cd617429e5845af6ed1922
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Components/IdComponent.cs b/Assets/Sources/Generated/Sync/Components/IdComponent.cs
new file mode 100644
index 0000000..c766916
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Components/IdComponent.cs
@@ -0,0 +1,16 @@
+using NetStack.Serialization;
+
+public partial class IdComponent : INetworkComponent
+{
+ public void Serialize(BitBuffer bitBuffer)
+ {
+ bitBuffer.AddUShort(0);
+
+ bitBuffer.AddUShort(Value);
+ }
+
+ public void Deserialize(BitBuffer bitBuffer)
+ {
+ Value = bitBuffer.ReadUShort();
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Components/IdComponent.cs.meta b/Assets/Sources/Generated/Sync/Components/IdComponent.cs.meta
new file mode 100644
index 0000000..9e978ca
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Components/IdComponent.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8d0654b0014bf8a44af178beafb316c2
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Components/Sync.cs b/Assets/Sources/Generated/Sync/Components/Sync.cs
new file mode 100644
index 0000000..c93cc2f
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Components/Sync.cs
@@ -0,0 +1,14 @@
+using NetStack.Serialization;
+
+public partial class Sync : INetworkComponent
+{
+ public void Serialize(BitBuffer bitBuffer)
+ {
+ bitBuffer.AddUShort(4);
+
+ }
+
+ public void Deserialize(BitBuffer bitBuffer)
+ {
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Components/Sync.cs.meta b/Assets/Sources/Generated/Sync/Components/Sync.cs.meta
new file mode 100644
index 0000000..fdf0b9e
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Components/Sync.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 66939820ae6c67a4fb03a0db93006c95
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Compressors.meta b/Assets/Sources/Generated/Sync/Compressors.meta
new file mode 100644
index 0000000..f634b5d
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Compressors.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f3a9b44acca2ffe41a9b8dfb4e8eabc4
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Compressors/SyncCompressors.cs b/Assets/Sources/Generated/Sync/Compressors/SyncCompressors.cs
new file mode 100644
index 0000000..15af4f5
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Compressors/SyncCompressors.cs
@@ -0,0 +1,9 @@
+using NetStack.Compression;
+
+public static class SyncCompressors
+{
+
+ static SyncCompressors()
+ {
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Compressors/SyncCompressors.cs.meta b/Assets/Sources/Generated/Sync/Compressors/SyncCompressors.cs.meta
new file mode 100644
index 0000000..669bb04
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Compressors/SyncCompressors.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 00f6375f03eaa834ea120f0b31ad8ec1
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Feature.meta b/Assets/Sources/Generated/Sync/Feature.meta
new file mode 100644
index 0000000..449e007
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Feature.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 2e9cbba561e89a449a0d8ae0e0e567b9
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Feature/ServerStateCaptureFeature.cs b/Assets/Sources/Generated/Sync/Feature/ServerStateCaptureFeature.cs
new file mode 100644
index 0000000..9c6ec1a
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Feature/ServerStateCaptureFeature.cs
@@ -0,0 +1,22 @@
+using Sources.Networking.Server.StateCapture;
+
+public class ServerStateCaptureFeature : Feature
+{
+ public ServerStateCaptureFeature(Contexts contexts, Services services)
+ {
+ Add(new ServerCaptureChangedIdSystem(contexts, services));
+ Add(new ServerCaptureRemovedIdSystem(contexts, services));
+ Add(new ServerCaptureChangedCharacterSystem(contexts, services));
+ Add(new ServerCaptureRemovedCharacterSystem(contexts, services));
+ Add(new ServerCaptureChangedControlledBySystem(contexts, services));
+ Add(new ServerCaptureRemovedControlledBySystem(contexts, services));
+ Add(new ServerCaptureChangedConnectionSystem(contexts, services));
+ Add(new ServerCaptureRemovedConnectionSystem(contexts, services));
+ Add(new ServerCaptureChangedSyncSystem(contexts, services));
+ Add(new ServerCaptureRemovedSyncSystem(contexts, services));
+
+ Add(new ServerCreateWorldStateSystem(contexts));
+ Add(new ServerCaptureCreatedEntitiesSystem(contexts, services));
+ Add(new ServerCaptureRemovedEntitiesSystem(contexts, services));
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Feature/ServerStateCaptureFeature.cs.meta b/Assets/Sources/Generated/Sync/Feature/ServerStateCaptureFeature.cs.meta
new file mode 100644
index 0000000..42fbe42
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Feature/ServerStateCaptureFeature.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b5b518ef5ef748f4a98a98889c2b8aba
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Utility.meta b/Assets/Sources/Generated/Sync/Utility.meta
new file mode 100644
index 0000000..fbad2c9
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Utility.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: fd8a42ea3ddabbf41a3e9afe3a83167f
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Utility/PackEntityUtility.cs b/Assets/Sources/Generated/Sync/Utility/PackEntityUtility.cs
new file mode 100644
index 0000000..2c16e6f
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Utility/PackEntityUtility.cs
@@ -0,0 +1,73 @@
+using NetStack.Serialization;
+
+public static class PackEntityUtility
+{
+ public static void Pack(GameEntity e, BitBuffer buffer)
+ {
+ ushort counter = 0;
+
+ var hasId = false;
+ if(e.hasId)
+ {
+ hasId = true;
+ counter++;
+ }
+
+ var hasCharacter = false;
+ if(e.isCharacter)
+ {
+ hasCharacter = true;
+ counter++;
+ }
+
+ var hasControlledBy = false;
+ if(e.hasControlledBy)
+ {
+ hasControlledBy = true;
+ counter++;
+ }
+
+ var hasConnection = false;
+ if(e.hasConnection)
+ {
+ hasConnection = true;
+ counter++;
+ }
+
+ var hasSync = false;
+ if(e.isSync)
+ {
+ hasSync = true;
+ counter++;
+ }
+
+
+ buffer.AddUShort(counter);
+
+ if (hasId)
+ {
+ e.id.Serialize(buffer);
+ }
+
+ if (hasCharacter)
+ {
+ buffer.AddUShort(1);
+ }
+
+ if (hasControlledBy)
+ {
+ e.controlledBy.Serialize(buffer);
+ }
+
+ if (hasConnection)
+ {
+ e.connection.Serialize(buffer);
+ }
+
+ if (hasSync)
+ {
+ buffer.AddUShort(4);
+ }
+
+ }
+}
diff --git a/Assets/Sources/Generated/Sync/Utility/PackEntityUtility.cs.meta b/Assets/Sources/Generated/Sync/Utility/PackEntityUtility.cs.meta
new file mode 100644
index 0000000..0052c6c
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Utility/PackEntityUtility.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d11314fa33b50b649882f5d3abff425d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Generated/Sync/Utility/UnpackEntityUtility.cs b/Assets/Sources/Generated/Sync/Utility/UnpackEntityUtility.cs
new file mode 100644
index 0000000..d80b6c8
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Utility/UnpackEntityUtility.cs
@@ -0,0 +1,175 @@
+using System.Text;
+using NetStack.Serialization;
+using Sources.Tools;
+
+public static class UnpackEntityUtility
+{
+ public static void CreateEntities(GameContext game, BitBuffer buffer, ushort entityCount)
+ {
+ for (int i = 0; i < entityCount; i++)
+ {
+ var addedComponents = new StringBuilder(128);
+
+ var e = game.CreateEntity();
+
+ var componentsCount = buffer.ReadUShort();
+
+ for (int j = 0; j < componentsCount; j++)
+ {
+ var componentId = buffer.ReadUShort();
+
+ switch (componentId)
+ {
+ case 0:
+ {
+ addedComponents.Append(" Id ");
+ var lookup = GameComponentsLookup.Id;
+ var comp = e.CreateComponent(lookup);
+ comp.Deserialize(buffer);
+ e.AddComponent(lookup, comp);
+ }
+ break;
+ case 1:
+ {
+ addedComponents.Append(" Character ");
+ e.isCharacter = true;
+ }
+ break;
+ case 2:
+ {
+ addedComponents.Append(" ControlledBy ");
+ var lookup = GameComponentsLookup.ControlledBy;
+ var comp = e.CreateComponent(lookup);
+ comp.Deserialize(buffer);
+ e.AddComponent(lookup, comp);
+ }
+ break;
+ case 3:
+ {
+ addedComponents.Append(" Connection ");
+ var lookup = GameComponentsLookup.Connection;
+ var comp = e.CreateComponent(lookup);
+ comp.Deserialize(buffer);
+ e.AddComponent(lookup, comp);
+ }
+ break;
+ case 4:
+ {
+ addedComponents.Append(" Sync ");
+ e.isSync = true;
+ }
+ break;
+ }
+ }
+ Logger.I.Log("UnpackEntityUtility", $" Entity-{e.id.Value}: created - ({addedComponents})");
+ }
+ }
+
+ public static void ChangeComponents(GameContext game, BitBuffer buffer, ushort componentCount)
+ {
+ for (int i = 0; i < componentCount; i++)
+ {
+ var entityId = buffer.ReadUShort();
+ var componentId = buffer.ReadUShort();
+ var e = game.GetEntityWithId(entityId);
+
+ switch (componentId)
+ {
+ case 0:
+ {
+ Logger.I.Log("UnpackEntityUtility", $" Entity-{entityId}: Changed Id component");
+ var lookup = GameComponentsLookup.Id;
+ var comp = e.CreateComponent(lookup);
+ comp.Deserialize(buffer);
+ e.ReplaceComponent(lookup, comp);
+ }
+ break;
+ case 1:
+ {
+ Logger.I.Log("UnpackEntityUtility", $" Entity-{entityId}: Changed Character component");
+ e.isCharacter = true;
+ }
+ break;
+ case 2:
+ {
+ Logger.I.Log("UnpackEntityUtility", $" Entity-{entityId}: Changed ControlledBy component");
+ var lookup = GameComponentsLookup.ControlledBy;
+ var comp = e.CreateComponent(lookup);
+ comp.Deserialize(buffer);
+ e.ReplaceComponent(lookup, comp);
+ }
+ break;
+ case 3:
+ {
+ Logger.I.Log("UnpackEntityUtility", $" Entity-{entityId}: Changed Connection component");
+ var lookup = GameComponentsLookup.Connection;
+ var comp = e.CreateComponent(lookup);
+ comp.Deserialize(buffer);
+ e.ReplaceComponent(lookup, comp);
+ }
+ break;
+ case 4:
+ {
+ Logger.I.Log("UnpackEntityUtility", $" Entity-{entityId}: Changed Sync component");
+ e.isSync = true;
+ }
+ break;
+ }
+ }
+ }
+
+ public static void RemoveComponents(GameContext game, BitBuffer buffer, ushort componentCount)
+ {
+ for (int i = 0; i < componentCount; i++)
+ {
+ var entityId = buffer.ReadUShort();
+ var componentId = buffer.ReadUShort();
+ var e = game.GetEntityWithId(entityId);
+
+ switch (componentId)
+ {
+ case 0:
+ {
+ Logger.I.Log("UnpackEntityUtility", $" Entity-{entityId}: Removed Id component");
+ e.RemoveId();
+ }
+ break;
+ case 1:
+ {
+ Logger.I.Log("UnpackEntityUtility", $" Entity-{entityId}: Removed Character component");
+ e.isCharacter = false;
+ }
+ break;
+ case 2:
+ {
+ Logger.I.Log("UnpackEntityUtility", $" Entity-{entityId}: Removed ControlledBy component");
+ e.RemoveControlledBy();
+ }
+ break;
+ case 3:
+ {
+ Logger.I.Log("UnpackEntityUtility", $" Entity-{entityId}: Removed Connection component");
+ e.RemoveConnection();
+ }
+ break;
+ case 4:
+ {
+ Logger.I.Log("UnpackEntityUtility", $" Entity-{entityId}: Removed Sync component");
+ e.isSync = false;
+ }
+ break;
+ }
+ }
+ }
+
+ public static void RemoveEntities(GameContext game, BitBuffer buffer, ushort entityCount)
+ {
+ for (int i = 0; i < entityCount; i++)
+ {
+ var id = buffer.ReadUShort();
+ var e = game.GetEntityWithId(id);
+ e.isDestroyed = true;
+ Logger.I.Log("UnpackEntityUtility", $" Entity-{id}: is removed");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Generated/Sync/Utility/UnpackEntityUtility.cs.meta b/Assets/Sources/Generated/Sync/Utility/UnpackEntityUtility.cs.meta
new file mode 100644
index 0000000..865ae76
--- /dev/null
+++ b/Assets/Sources/Generated/Sync/Utility/UnpackEntityUtility.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6154746269b648de8fd6f7349120d4ab
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sources/Networking.meta b/Assets/Sources/Networking.meta
new file mode 100644
index 0000000..777c5e5
--- /dev/null
+++ b/Assets/Sources/Networking.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 8628921752ea4af09fa81cf6d4a894a6
+timeCreated: 1557590894
\ No newline at end of file
diff --git a/Assets/Sources/Networking/Client.meta b/Assets/Sources/Networking/Client.meta
new file mode 100644
index 0000000..ece6686
--- /dev/null
+++ b/Assets/Sources/Networking/Client.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 3e900997d0904237bc0be96e0fe54d78
+timeCreated: 1557679839
\ No newline at end of file
diff --git a/Assets/Sources/Networking/Client/ClientCommandHandler.cs b/Assets/Sources/Networking/Client/ClientCommandHandler.cs
new file mode 100644
index 0000000..c725c20
--- /dev/null
+++ b/Assets/Sources/Networking/Client/ClientCommandHandler.cs
@@ -0,0 +1,49 @@
+using ENet;
+using Sources.Tools;
+
+namespace Sources.Networking.Client
+{
+ public class ClientCommandHandler : IClientHandler
+ {
+ private readonly ClientNetworkSystem _client;
+ private readonly GameContext _game;
+
+ public ClientCommandHandler(GameContext game, ClientNetworkSystem client)
+ {
+ _game = game;
+ _client = client;
+ }
+
+ public void HandleChatMessageCommand(ref ServerChatMessageCommand command)
+ {
+ Logger.I.Log(this, $"Client-{command.Sender}: {command.Message}");
+ }
+
+ public void HandleGrantedIdCommand(ref ServerGrantedIdCommand command)
+ {
+ Logger.I.Log(this, $"Got ID - {command.Id}");
+ _client.State = ClientState.Connected;
+ _client.ConnectionId.IsSet = true;
+ _client.ConnectionId.Id = command.Id;
+ }
+
+ public void HandleSetTickrateCommand(ref ServerSetTickrateCommand command)
+ {
+ _client.TickRate = command.Tickrate;
+ }
+
+ public void OnConnected(Peer peer)
+ {
+ Logger.I.Log(this, $"Connected to server {peer.IP} {peer.Port}, waiting for ID");
+ _client.State = ClientState.WaitingForId;
+ _client.ServerConnection = peer;
+ }
+
+ public void OnDisconnected(Peer peer)
+ {
+ Logger.I.Log(this, "Disconnected from server");
+ _client.EnqueueRequest(NetworkThreadRequest.Cleanup);
+ _client.CleanupState();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Networking/Client/ClientCommandHandler.cs.meta b/Assets/Sources/Networking/Client/ClientCommandHandler.cs.meta
new file mode 100644
index 0000000..06f5c0e
--- /dev/null
+++ b/Assets/Sources/Networking/Client/ClientCommandHandler.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 711fefb517cf44708e3d0e7c54e5a55e
+timeCreated: 1557920852
\ No newline at end of file
diff --git a/Assets/Sources/Networking/Client/ClientNetworkFeature.cs b/Assets/Sources/Networking/Client/ClientNetworkFeature.cs
new file mode 100644
index 0000000..310d882
--- /dev/null
+++ b/Assets/Sources/Networking/Client/ClientNetworkFeature.cs
@@ -0,0 +1,10 @@
+namespace Sources.Networking.Client
+{
+ public class ClientNetworkFeature : Feature
+ {
+ public ClientNetworkFeature(Contexts contexts, Services services)
+ {
+ Add(new ClientSendPacketSystem(services));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Networking/Client/ClientNetworkFeature.cs.meta b/Assets/Sources/Networking/Client/ClientNetworkFeature.cs.meta
new file mode 100644
index 0000000..7496322
--- /dev/null
+++ b/Assets/Sources/Networking/Client/ClientNetworkFeature.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 7fc8981c089f455899ecba9292962692
+timeCreated: 1557679967
\ No newline at end of file
diff --git a/Assets/Sources/Networking/Client/ClientNetworkSystem.cs b/Assets/Sources/Networking/Client/ClientNetworkSystem.cs
new file mode 100644
index 0000000..40ea8ef
--- /dev/null
+++ b/Assets/Sources/Networking/Client/ClientNetworkSystem.cs
@@ -0,0 +1,410 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Threading;
+using DisruptorUnity3d;
+using ENet;
+using Entitas;
+using NetStack.Serialization;
+using Sources.Networking.Server;
+using Sources.Tools;
+
+namespace Sources.Networking.Client
+{
+ public class ClientNetworkSystem : IExecuteSystem, ITearDownSystem
+ {
+ public ClientState State = ClientState.Disconnected;
+ public ConnectionId ConnectionId;
+ public Peer ServerConnection;
+
+ public ushort TickRate = 20;
+ public int PanicCleanupTarget = 6;
+ public int PanicStateCount = 10;
+
+ public int StatesCount => _states.Count;
+
+ private readonly GameContext _game;
+ private readonly ClientCommandHandler _handler;
+
+ private readonly Thread _networkThread;
+ private readonly RingBuffer _eventsToHandle = new RingBuffer(1024);
+ private readonly RingBuffer _sendData = new RingBuffer(64);
+ private readonly RingBuffer _responses = new RingBuffer(8);
+ private readonly RingBuffer _requests = new RingBuffer(8);
+ private Address _address;
+
+ private readonly Queue _states = new Queue(124);
+
+ private readonly IGroup _syncGroup;
+ private readonly List _syncBuffer = new List(ServerNetworkSystem.MaxPlayers);
+
+ public ushort EnqueuedCommandCount;
+ public readonly BitBuffer ToServer = new BitBuffer(512);
+
+ private readonly BitBuffer _fromServer = new BitBuffer(512);
+
+ private bool _firstPacket = true;
+ private Host _host = new Host();
+
+ private readonly PacketFreeCallback _freeCallback = packet => { Marshal.FreeHGlobal(packet.Data); };
+ private readonly IntPtr _cachedFreeCallback;
+
+ public ClientNetworkSystem(Contexts contexts)
+ {
+ Logger.I.Log(this, "Created");
+
+ _game = contexts.game;
+ _host.Create();
+ _handler = new ClientCommandHandler(_game, this);
+ ConnectionId.IsSet = false;
+
+ _networkThread = NetworkThread();
+ _networkThread.Start();
+ _syncGroup = _game.GetGroup(GameMatcher.Sync);
+ _cachedFreeCallback = Marshal.GetFunctionPointerForDelegate(_freeCallback);
+ }
+
+ public void Execute()
+ {
+ if (_states.Count > PanicStateCount)
+ {
+ //Catchup after lag
+ while (_states.Count > PanicCleanupTarget)
+ {
+ var state = _states.Dequeue();
+ ExecuteState(state);
+ }
+ }
+ else if (_states.Count > 0)
+ {
+ var state = _states.Dequeue();
+ ExecuteState(state);
+ }
+ }
+
+ public void TearDown()
+ {
+ if (State == ClientState.Connected) _requests.Enqueue(NetworkThreadRequest.Disconnect);
+
+ Thread.Sleep(20);
+ _networkThread.Abort();
+ }
+
+
+ private Thread NetworkThread()
+ {
+ return new Thread(() =>
+ {
+ while (true)
+ {
+ while (_sendData.TryDequeue(out var data))
+ {
+ var packet = new Packet();
+ packet.Create(data.Data, data.Length, PacketFlags.Reliable | PacketFlags.NoAllocate);
+ packet.SetFreeCallback(_cachedFreeCallback);
+ data.Peer.Send(0, ref packet);
+ }
+
+ while (_requests.TryDequeue(out var request))
+ switch (request)
+ {
+ case NetworkThreadRequest.Connect:
+ try
+ {
+ _host.Connect(_address, 2);
+ }
+ catch (Exception e)
+ {
+ Logger.I.Log(this, e.Message);
+ _host = new Host();
+ _host.Create();
+ _responses.Enqueue(NetworkThreadResponse.ConnectFailure);
+ }
+
+ break;
+ case NetworkThreadRequest.Disconnect:
+ ServerConnection.DisconnectNow(0);
+ _host.Flush();
+ _host.Dispose();
+ _host = new Host();
+ _host.Create();
+ _responses.Enqueue(NetworkThreadResponse.Disconnected);
+ break;
+ case NetworkThreadRequest.Cleanup:
+ _host = new Host();
+ _host.Create();
+ break;
+ case NetworkThreadRequest.CancelConnect:
+ _host.Dispose();
+ _host = new Host();
+ _host.Create();
+ _responses.Enqueue(NetworkThreadResponse.ConnectCancelled);
+ break;
+ }
+
+ if (!_host.IsSet) Thread.Sleep(15);
+ if (_host.Service(15, out var @event) > 0)
+ switch (@event.Type)
+ {
+ case EventType.Connect:
+ case EventType.Disconnect:
+ case EventType.Timeout:
+ _eventsToHandle.Enqueue(new ReceivedEvent
+ {EventType = @event.Type, Peer = @event.Peer});
+ break;
+ case EventType.Receive:
+ unsafe
+ {
+ var length = @event.Packet.Length;
+ var newPtr = Marshal.AllocHGlobal(length);
+ Buffer.MemoryCopy(@event.Packet.Data.ToPointer(), newPtr.ToPointer(), length,
+ length);
+ _eventsToHandle.Enqueue(new ReceivedEvent
+ {Data = newPtr, Peer = @event.Peer, EventType = EventType.Receive});
+ }
+
+ break;
+ }
+ }
+ });
+ }
+
+ public void Connect(Address address)
+ {
+ if (State != ClientState.Disconnected) return;
+
+ Logger.I.Log(this, $"Connecting to {address.GetIP()}:{address.Port}");
+ State = ClientState.Connecting;
+
+ _address = address;
+ _requests.Enqueue(NetworkThreadRequest.Connect);
+ }
+
+ public void Disconnect()
+ {
+ if (State != ClientState.Connected) return;
+
+ Logger.I.Log(this, "Disconnecting");
+
+ State = ClientState.Disconnecting;
+ _requests.Enqueue(NetworkThreadRequest.Disconnect);
+ }
+
+ public void EnqueueCommand(T command) where T : ICommand, IClientCommand
+ {
+ Logger.I.Log(this, $"Enqueued {command.GetType().Name}");
+
+ EnqueuedCommandCount++;
+ command.Serialize(ToServer);
+ }
+
+ public void EnqueueSendData(SendData data)
+ {
+ _sendData.Enqueue(data);
+ }
+
+ public void EnqueueRequest(NetworkThreadRequest request)
+ {
+ _requests.Enqueue(request);
+ }
+
+ public void UpdateNetwork()
+ {
+ while (_responses.TryDequeue(out var response))
+ switch (response)
+ {
+ case NetworkThreadResponse.ConnectFailure:
+ State = ClientState.Disconnected;
+ break;
+ case NetworkThreadResponse.Disconnected:
+ CleanupState();
+ Logger.I.Log(this, "Disconnected");
+ break;
+ case NetworkThreadResponse.ConnectCancelled:
+ CleanupState();
+ Logger.I.Log(this, "Connect cancelled");
+ break;
+ }
+
+ if (State == ClientState.Disconnected) return;
+ while (_eventsToHandle.TryDequeue(out var @event))
+ switch (@event.EventType)
+ {
+ case EventType.Connect:
+ _handler.OnConnected(@event.Peer);
+ break;
+ case EventType.Disconnect:
+ _handler.OnDisconnected(@event.Peer);
+ break;
+ case EventType.Receive:
+ _states.Enqueue(@event.Data);
+ break;
+ case EventType.Timeout:
+ _handler.OnDisconnected(@event.Peer);
+ break;
+ }
+ }
+
+ private unsafe void ExecuteState(IntPtr state)
+ {
+ #region commands
+
+ var commandsHeaderSpan = new ReadOnlySpan(state.ToPointer(), 2);
+ var commandCount = commandsHeaderSpan[0];
+ var commandLength = commandsHeaderSpan[1];
+ var cursor = 4;
+
+ if (commandCount > 0)
+ {
+ var dataSpan = new ReadOnlySpan(IntPtr.Add(state, cursor).ToPointer(),
+ commandLength);
+ _fromServer.Clear();
+ _fromServer.FromSpan(ref dataSpan, commandLength);
+ ClientCommandExecutor.Execute(_handler, _fromServer, commandCount);
+ cursor += commandLength;
+ }
+
+ #endregion
+
+ #region created entities
+
+ var createdEntitiesHeaderSpan =
+ new ReadOnlySpan(IntPtr.Add(state, cursor).ToPointer(), 2);
+ var createdEntitiesCount = createdEntitiesHeaderSpan[0];
+ var createdEntitiesLength = createdEntitiesHeaderSpan[1];
+ cursor += 4;
+
+ if (createdEntitiesCount > 0)
+ {
+ var dataSpan = new ReadOnlySpan(IntPtr.Add(state, cursor).ToPointer(),
+ createdEntitiesLength);
+ _fromServer.Clear();
+ _fromServer.FromSpan(ref dataSpan, createdEntitiesLength);
+ UnpackEntityUtility.CreateEntities(_game, _fromServer, createdEntitiesCount);
+ cursor += createdEntitiesLength;
+ }
+
+ #endregion
+
+ if (_firstPacket)
+ {
+ _firstPacket = false;
+ Marshal.FreeHGlobal(state);
+ return;
+ }
+
+ #region removed entities
+
+ var removedEntitiesHeaderSpan =
+ new ReadOnlySpan(IntPtr.Add(state, cursor).ToPointer(), 2);
+ var removedEntitiesCount = removedEntitiesHeaderSpan[0];
+ var removedEntitiesLength = removedEntitiesHeaderSpan[1];
+
+ cursor += 4;
+
+ if (removedEntitiesCount > 0)
+ {
+ var dataSpan = new ReadOnlySpan(IntPtr.Add(state, cursor).ToPointer(),
+ removedEntitiesLength);
+ _fromServer.Clear();
+ _fromServer.FromSpan(ref dataSpan, removedEntitiesLength);
+ UnpackEntityUtility.RemoveEntities(_game, _fromServer, removedEntitiesCount);
+ cursor += removedEntitiesLength;
+ }
+
+ #endregion
+
+ #region removed components
+
+ var removedComponentsHeaderSpan =
+ new ReadOnlySpan(IntPtr.Add(state, cursor).ToPointer(), 2);
+ var removedComponentsCount = removedComponentsHeaderSpan[0];
+ var removedComponentsLength = removedComponentsHeaderSpan[1];
+ cursor += 4;
+
+ if (removedComponentsCount > 0)
+ {
+ var dataSpan = new ReadOnlySpan(IntPtr.Add(state, cursor).ToPointer(),
+ removedComponentsLength);
+ _fromServer.Clear();
+ _fromServer.FromSpan(ref dataSpan, removedComponentsLength);
+ UnpackEntityUtility.RemoveComponents(_game, _fromServer, removedComponentsCount);
+ cursor += removedComponentsLength;
+ }
+
+ #endregion
+
+ #region changed components
+
+ var changedComponentsHeaderSpan =
+ new ReadOnlySpan(IntPtr.Add(state, cursor).ToPointer(), 2);
+ var changedComponentsCount = changedComponentsHeaderSpan[0];
+ var changedComponentsLength = changedComponentsHeaderSpan[1];
+ cursor += 4;
+
+ if (changedComponentsCount > 0)
+ {
+ var dataSpan = new ReadOnlySpan(IntPtr.Add(state, cursor).ToPointer(),
+ changedComponentsLength);
+ _fromServer.Clear();
+ _fromServer.FromSpan(ref dataSpan, changedComponentsLength);
+ UnpackEntityUtility.ChangeComponents(_game, _fromServer, changedComponentsCount);
+ }
+
+ #endregion
+
+ Marshal.FreeHGlobal(state);
+ }
+
+ public void CleanupState()
+ {
+ while (_eventsToHandle.TryDequeue(out _))
+ {
+ }
+
+ while (_states.Count > 0) Marshal.FreeHGlobal(_states.Dequeue());
+
+ State = ClientState.Disconnected;
+ ServerConnection = new Peer();
+ ConnectionId.IsSet = false;
+ _firstPacket = true;
+
+ _syncGroup.GetEntities(_syncBuffer);
+ foreach (var e in _syncBuffer) e.isDestroyed = true;
+
+ EnqueuedCommandCount = 0;
+ ToServer.Clear();
+ _fromServer.Clear();
+ }
+ }
+
+ public enum NetworkThreadRequest
+ {
+ Connect,
+ CancelConnect,
+ Disconnect,
+ Cleanup
+ }
+
+ public enum NetworkThreadResponse
+ {
+ ConnectCancelled,
+ ConnectFailure,
+ Disconnected
+ }
+
+ public enum ClientState
+ {
+ Disconnected,
+ Connecting,
+ WaitingForId,
+ Connected,
+ Disconnecting
+ }
+
+ public struct ConnectionId
+ {
+ public bool IsSet;
+ public ushort Id;
+ }
+}
\ No newline at end of file
diff --git a/Assets/Sources/Networking/Client/ClientNetworkSystem.cs.meta b/Assets/Sources/Networking/Client/ClientNetworkSystem.cs.meta
new file mode 100644
index 0000000..e56e2f3
--- /dev/null
+++ b/Assets/Sources/Networking/Client/ClientNetworkSystem.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 2511d306cda14fd195510160fd719bb6
+timeCreated: 1557606536
\ No newline at end of file
diff --git a/Assets/Sources/Networking/Client/ClientSendPacketSystem.cs b/Assets/Sources/Networking/Client/ClientSendPacketSystem.cs
new file mode 100644
index 0000000..f6d2c4d
--- /dev/null
+++ b/Assets/Sources/Networking/Client/ClientSendPacketSystem.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Runtime.InteropServices;
+using Entitas;
+
+namespace Sources.Networking.Client
+{
+ public class ClientSendPacketSystem : IExecuteSystem
+ {
+ private readonly ClientNetworkSystem _client;
+
+ private readonly byte[] _data = new byte[2048];
+
+ public ClientSendPacketSystem(Services services)
+ {
+ _client = services.ClientSystem;
+ }
+
+ public unsafe void Execute()
+ {
+ if (_client.State != ClientState.Connected) return;
+
+ var commandLength = _client.ToServer.Length;
+ var commandCount = _client.EnqueuedCommandCount;
+ var totalLength = commandLength + 4;
+
+ fixed (byte* destination = &_data[0])
+ {
+ var shortsSpan = new Span