diff --git a/TODO.md b/TODO.md index 0b831e4..94ffb01 100644 --- a/TODO.md +++ b/TODO.md @@ -46,6 +46,7 @@ * [x] add AttackTarget curve * [x] add FSM design document * [x] add FSM blog entry +* [ ] **add Attack delay / targeting** * [ ] add game state export / import * [ ] log to file, log non-fatal errors instead of erroring out (e.g. `Run`) * [ ] replace pathfinding with flow fields diff --git a/api/api.proto b/api/api.proto index 92ebea0..3ae0556 100644 --- a/api/api.proto +++ b/api/api.proto @@ -47,7 +47,10 @@ message GetStatusResponse { message AttackRequest { double tick = 1; + + // TODO(minkezhang): Remove after adding authentication. string client_id = 2; + repeated string entity_ids = 3; string target_entity_id = 4; } @@ -56,7 +59,10 @@ message AttackResponse {} message MoveRequest { double tick = 1; + + // TODO(minkezhang): Remove after adding authentication. string client_id = 2; + repeated string entity_ids = 3; game.api.data.Position destination = 4; game.api.constants.MoveType move_type = 5; @@ -66,6 +72,8 @@ message MoveResponse {} message StreamDataRequest { double tick = 1; + + // TODO(minkezhang): Remove after adding authentication. string client_id = 2; } @@ -78,5 +86,6 @@ message StreamDataResponse { message AddClientRequest {} message AddClientResponse { double tick = 1; - string client_id = 2; + + game.api.data.ClientID client_id = 2; } diff --git a/api/constants.proto b/api/constants.proto index b140a03..f2518b4 100644 --- a/api/constants.proto +++ b/api/constants.proto @@ -20,6 +20,8 @@ enum EntityProperty { ENTITY_PROPERTY_POSITION = 1; ENTITY_PROPERTY_ATTACK_TIMER = 2; ENTITY_PROPERTY_HEALTH = 3; + ENTITY_PROPERTY_ATTACK_TARGET = 4; + ENTITY_PROPERTY_CLIENT_ID = 5; } // CurveType indicates the interpolation method that should be used for the diff --git a/api/data.proto b/api/data.proto index 53887c2..b391916 100644 --- a/api/data.proto +++ b/api/data.proto @@ -11,6 +11,13 @@ import "api/constants.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; +// ClientID contains identification information about a specific client +// connected to the game. This struct is surfaced as public information and does +// not contain any authentication-related tokens. +message ClientID { + string client_id = 1; +} + // Position is a specific point in the map, representing a point in the map. message Position { double x = 1; @@ -73,7 +80,7 @@ message Entity { // TODO(minkezhang): Rename to id instead. string entity_id = 1; - game.api.constants.EntityType type = 2; + game.api.constants.EntityType type = 2; } message GameState { diff --git a/client/DownFlux/Assets/Engine/Client/Client.cs b/client/DownFlux/Assets/Engine/Client/Client.cs index 70248d8..c000cac 100644 --- a/client/DownFlux/Assets/Engine/Client/Client.cs +++ b/client/DownFlux/Assets/Engine/Client/Client.cs @@ -23,7 +23,7 @@ public string ID public string Connect() { var resp = _c.AddClient(new DF.Game.API.API.AddClientRequest()); - ID = resp.ClientId; + ID = resp.ClientId.ClientId; return ID; } diff --git a/client/DownFlux/Assets/Protos/Engine/Service.meta b/client/DownFlux/Assets/Engine/Utilities.meta similarity index 77% rename from client/DownFlux/Assets/Protos/Engine/Service.meta rename to client/DownFlux/Assets/Engine/Utilities.meta index d91c992..13a918f 100644 --- a/client/DownFlux/Assets/Protos/Engine/Service.meta +++ b/client/DownFlux/Assets/Engine/Utilities.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 243c905f0df3cbd57b90be661014bf6d +guid: f9d29df315f04d4fd8d886305ed299b4 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Engine/Service/Visitor.meta b/client/DownFlux/Assets/Engine/Utilities/FSM.meta similarity index 77% rename from client/DownFlux/Assets/Protos/Engine/Service/Visitor.meta rename to client/DownFlux/Assets/Engine/Utilities/FSM.meta index 6a9896b..3d83807 100644 --- a/client/DownFlux/Assets/Protos/Engine/Service/Visitor.meta +++ b/client/DownFlux/Assets/Engine/Utilities/FSM.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: f4b935d6a8b6da1d9b4673fe753c8c3e +guid: cd44addb1ba7029edb0856ea116611c2 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Engine/Utilities/FSM/FSM.cs b/client/DownFlux/Assets/Engine/Utilities/FSM/FSM.cs new file mode 100644 index 0000000..36b3a1e --- /dev/null +++ b/client/DownFlux/Assets/Engine/Utilities/FSM/FSM.cs @@ -0,0 +1,36 @@ +namespace DF.Game.Utilities.FSM { + // TODO(minkezhang): Change to Dictionary> instead. + using TransitionLookup = System.Collections.ObjectModel.ReadOnlyDictionary; + + public class State { + private int _s; + public State(int s) { + _s = s; + } + } + + public interface IFSM { + bool To(State a, State b); + State State(); + } + + public abstract class Base : IFSM { + private TransitionLookup _transitions; + private State _state; // Default state must be UNKNOWN. + + public Base(TransitionLookup transitions, State s) { + _transitions = transitions; + _state = s; + } + + public bool To(State a, State b) { + if (_transitions.ContainsKey(a) && _transitions[a] == b) { + _state = b; + return true; + } + return false; + } + + public abstract State State(); + } +} \ No newline at end of file diff --git a/client/DownFlux/Assets/Protos/Engine/Service/Visitor/API/Constants/Constants.g.cs.meta b/client/DownFlux/Assets/Engine/Utilities/FSM/FSM.cs.meta similarity index 83% rename from client/DownFlux/Assets/Protos/Engine/Service/Visitor/API/Constants/Constants.g.cs.meta rename to client/DownFlux/Assets/Engine/Utilities/FSM/FSM.cs.meta index a83f979..d796f82 100644 --- a/client/DownFlux/Assets/Protos/Engine/Service/Visitor/API/Constants/Constants.g.cs.meta +++ b/client/DownFlux/Assets/Engine/Utilities/FSM/FSM.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 1537de57282271cc49ccf32977326b6e +guid: beb328348d43d99aebd2b7b2e27edfc8 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/client/DownFlux/Assets/Packages.meta b/client/DownFlux/Assets/Packages.meta index cdcdab0..014701c 100644 --- a/client/DownFlux/Assets/Packages.meta +++ b/client/DownFlux/Assets/Packages.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: db7316590689bb0aabbb87861deb2c50 +guid: 60dd8a3b5d91327e884c91d7e2934b70 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Plugins/README.md b/client/DownFlux/Assets/Plugins/README.md index 144fcd6..7dfbd5f 100644 --- a/client/DownFlux/Assets/Plugins/README.md +++ b/client/DownFlux/Assets/Plugins/README.md @@ -3,7 +3,9 @@ ## gRPC DLLs gRPC requires some additionally packaged object files, e.g. -libgrpc_csharp_ext.so in order for Unity to run. These shared libraries may be +`libgrpc_csharp_ext.so` in order for Unity to run. These shared libraries may be found in the `Grpc.Core` NuGet package. -See [#25223](https://github.com/grpc/grpc/issues/25223) for more information. \ No newline at end of file +Remember to rename the runtime to the expected filename. + +See [#25223](https://github.com/grpc/grpc/issues/25223) for more information. diff --git a/client/DownFlux/Assets/Plugins/libgrpc_csharp_ext.so.meta b/client/DownFlux/Assets/Plugins/libgrpc_csharp_ext.so.meta index 6be7143..c159721 100644 --- a/client/DownFlux/Assets/Plugins/libgrpc_csharp_ext.so.meta +++ b/client/DownFlux/Assets/Plugins/libgrpc_csharp_ext.so.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: b9b3dd2567ed408c8a9d0c3a9e1faa30 +guid: 9a332295bf1862337b8f82ba155a7ed3 PluginImporter: externalObjects: {} serializedVersion: 2 diff --git a/client/DownFlux/Assets/Protos/API.meta b/client/DownFlux/Assets/Protos/API.meta index 2110291..085134d 100644 --- a/client/DownFlux/Assets/Protos/API.meta +++ b/client/DownFlux/Assets/Protos/API.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 1843803d72233844da4421c517f87114 +guid: f73324fc69b5685d4bb517ce0f30c961 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/API/API.meta b/client/DownFlux/Assets/Protos/API/API.meta index 800a599..349bb48 100644 --- a/client/DownFlux/Assets/Protos/API/API.meta +++ b/client/DownFlux/Assets/Protos/API/API.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: ee71923d6a5166e8bad1d904ece7c0db +guid: 7931b98c9fbb62f229de8e94c94ed9fb folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/API/API/Api.g.cs b/client/DownFlux/Assets/Protos/API/API/Api.g.cs index a838946..316ad7e 100644 --- a/client/DownFlux/Assets/Protos/API/API/Api.g.cs +++ b/client/DownFlux/Assets/Protos/API/API/Api.g.cs @@ -37,18 +37,18 @@ static ApiReflection() { "U3RyZWFtRGF0YVJlcXVlc3QSDAoEdGljaxgBIAEoARIRCgljbGllbnRfaWQY", "AiABKAkiSwoSU3RyZWFtRGF0YVJlc3BvbnNlEgwKBHRpY2sYASABKAESJwoF", "c3RhdGUYAiABKAsyGC5nYW1lLmFwaS5kYXRhLkdhbWVTdGF0ZSISChBBZGRD", - "bGllbnRSZXF1ZXN0IjQKEUFkZENsaWVudFJlc3BvbnNlEgwKBHRpY2sYASAB", - "KAESEQoJY2xpZW50X2lkGAIgASgJMpADCghEb3duRmx1eBJOCglBZGRDbGll", - "bnQSHi5nYW1lLmFwaS5hcGkuQWRkQ2xpZW50UmVxdWVzdBofLmdhbWUuYXBp", - "LmFwaS5BZGRDbGllbnRSZXNwb25zZSIAEkUKBkF0dGFjaxIbLmdhbWUuYXBp", - "LmFwaS5BdHRhY2tSZXF1ZXN0GhwuZ2FtZS5hcGkuYXBpLkF0dGFja1Jlc3Bv", - "bnNlIgASQgoETW92ZRIZLmdhbWUuYXBpLmFwaS5Nb3ZlUmVxdWVzdBoaLmdh", - "bWUuYXBpLmFwaS5Nb3ZlUmVzcG9uc2UiA5ACAhJWCgpTdHJlYW1EYXRhEh8u", - "Z2FtZS5hcGkuYXBpLlN0cmVhbURhdGFSZXF1ZXN0GiAuZ2FtZS5hcGkuYXBp", - "LlN0cmVhbURhdGFSZXNwb25zZSIDkAICMAESUQoJR2V0U3RhdHVzEh4uZ2Ft", - "ZS5hcGkuYXBpLkdldFN0YXR1c1JlcXVlc3QaHy5nYW1lLmFwaS5hcGkuR2V0", - "U3RhdHVzUmVzcG9uc2UiA5ACAkIgWgxnYW1lLmFwaS5hcGmqAg9ERi5HYW1l", - "LkFQSS5BUEliBnByb3RvMw==")); + "bGllbnRSZXF1ZXN0Ik0KEUFkZENsaWVudFJlc3BvbnNlEgwKBHRpY2sYASAB", + "KAESKgoJY2xpZW50X2lkGAIgASgLMhcuZ2FtZS5hcGkuZGF0YS5DbGllbnRJ", + "RDKQAwoIRG93bkZsdXgSTgoJQWRkQ2xpZW50Eh4uZ2FtZS5hcGkuYXBpLkFk", + "ZENsaWVudFJlcXVlc3QaHy5nYW1lLmFwaS5hcGkuQWRkQ2xpZW50UmVzcG9u", + "c2UiABJFCgZBdHRhY2sSGy5nYW1lLmFwaS5hcGkuQXR0YWNrUmVxdWVzdBoc", + "LmdhbWUuYXBpLmFwaS5BdHRhY2tSZXNwb25zZSIAEkIKBE1vdmUSGS5nYW1l", + "LmFwaS5hcGkuTW92ZVJlcXVlc3QaGi5nYW1lLmFwaS5hcGkuTW92ZVJlc3Bv", + "bnNlIgOQAgISVgoKU3RyZWFtRGF0YRIfLmdhbWUuYXBpLmFwaS5TdHJlYW1E", + "YXRhUmVxdWVzdBogLmdhbWUuYXBpLmFwaS5TdHJlYW1EYXRhUmVzcG9uc2Ui", + "A5ACAjABElEKCUdldFN0YXR1cxIeLmdhbWUuYXBpLmFwaS5HZXRTdGF0dXNS", + "ZXF1ZXN0Gh8uZ2FtZS5hcGkuYXBpLkdldFN0YXR1c1Jlc3BvbnNlIgOQAgJC", + "IFoMZ2FtZS5hcGkuYXBpqgIPREYuR2FtZS5BUEkuQVBJYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::DF.Game.API.Constants.ConstantsReflection.Descriptor, global::DF.Game.API.Data.DataReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { @@ -440,6 +440,9 @@ public double Tick { /// Field number for the "client_id" field. public const int ClientIdFieldNumber = 2; private string clientId_ = ""; + /// + /// TODO(minkezhang): Remove after adding authentication. + /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string ClientId { get { return clientId_; } @@ -846,6 +849,9 @@ public double Tick { /// Field number for the "client_id" field. public const int ClientIdFieldNumber = 2; private string clientId_ = ""; + /// + /// TODO(minkezhang): Remove after adding authentication. + /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string ClientId { get { return clientId_; } @@ -1293,6 +1299,9 @@ public double Tick { /// Field number for the "client_id" field. public const int ClientIdFieldNumber = 2; private string clientId_ = ""; + /// + /// TODO(minkezhang): Remove after adding authentication. + /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public string ClientId { get { return clientId_; } @@ -1834,7 +1843,7 @@ public AddClientResponse() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public AddClientResponse(AddClientResponse other) : this() { tick_ = other.tick_; - clientId_ = other.clientId_; + clientId_ = other.clientId_ != null ? other.clientId_.Clone() : null; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -1856,12 +1865,12 @@ public double Tick { /// Field number for the "client_id" field. public const int ClientIdFieldNumber = 2; - private string clientId_ = ""; + private global::DF.Game.API.Data.ClientID clientId_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public string ClientId { + public global::DF.Game.API.Data.ClientID ClientId { get { return clientId_; } set { - clientId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + clientId_ = value; } } @@ -1879,7 +1888,7 @@ public bool Equals(AddClientResponse other) { return true; } if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Tick, other.Tick)) return false; - if (ClientId != other.ClientId) return false; + if (!object.Equals(ClientId, other.ClientId)) return false; return Equals(_unknownFields, other._unknownFields); } @@ -1887,7 +1896,7 @@ public bool Equals(AddClientResponse other) { public override int GetHashCode() { int hash = 1; if (Tick != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Tick); - if (ClientId.Length != 0) hash ^= ClientId.GetHashCode(); + if (clientId_ != null) hash ^= ClientId.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -1908,9 +1917,9 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(9); output.WriteDouble(Tick); } - if (ClientId.Length != 0) { + if (clientId_ != null) { output.WriteRawTag(18); - output.WriteString(ClientId); + output.WriteMessage(ClientId); } if (_unknownFields != null) { _unknownFields.WriteTo(output); @@ -1925,9 +1934,9 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(9); output.WriteDouble(Tick); } - if (ClientId.Length != 0) { + if (clientId_ != null) { output.WriteRawTag(18); - output.WriteString(ClientId); + output.WriteMessage(ClientId); } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); @@ -1941,8 +1950,8 @@ public int CalculateSize() { if (Tick != 0D) { size += 1 + 8; } - if (ClientId.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(ClientId); + if (clientId_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ClientId); } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); @@ -1958,8 +1967,11 @@ public void MergeFrom(AddClientResponse other) { if (other.Tick != 0D) { Tick = other.Tick; } - if (other.ClientId.Length != 0) { - ClientId = other.ClientId; + if (other.clientId_ != null) { + if (clientId_ == null) { + ClientId = new global::DF.Game.API.Data.ClientID(); + } + ClientId.MergeFrom(other.ClientId); } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -1980,7 +1992,10 @@ public void MergeFrom(pb::CodedInputStream input) { break; } case 18: { - ClientId = input.ReadString(); + if (clientId_ == null) { + ClientId = new global::DF.Game.API.Data.ClientID(); + } + input.ReadMessage(ClientId); break; } } @@ -2002,7 +2017,10 @@ public void MergeFrom(pb::CodedInputStream input) { break; } case 18: { - ClientId = input.ReadString(); + if (clientId_ == null) { + ClientId = new global::DF.Game.API.Data.ClientID(); + } + input.ReadMessage(ClientId); break; } } diff --git a/client/DownFlux/Assets/Protos/API/API/Api.g.cs.meta b/client/DownFlux/Assets/Protos/API/API/Api.g.cs.meta index 7a4109d..e4108ac 100644 --- a/client/DownFlux/Assets/Protos/API/API/Api.g.cs.meta +++ b/client/DownFlux/Assets/Protos/API/API/Api.g.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 6e8910625a2747895845ca03096a88ee +guid: 35f5a8fa820c965baad21ebbec7880be MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/client/DownFlux/Assets/Protos/API/Constants.meta b/client/DownFlux/Assets/Protos/API/Constants.meta index 0db83f1..bc32ea9 100644 --- a/client/DownFlux/Assets/Protos/API/Constants.meta +++ b/client/DownFlux/Assets/Protos/API/Constants.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: f05d464cc767ebff2bb12eda8b495f60 +guid: b3d25861347c61de6bf2c2f5a65e5b0f folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/API/Constants/Constants.g.cs b/client/DownFlux/Assets/Protos/API/Constants/Constants.g.cs index c312aaa..92135d8 100644 --- a/client/DownFlux/Assets/Protos/API/Constants/Constants.g.cs +++ b/client/DownFlux/Assets/Protos/API/Constants/Constants.g.cs @@ -26,16 +26,18 @@ static ConstantsReflection() { string.Concat( "ChNhcGkvY29uc3RhbnRzLnByb3RvEhJnYW1lLmFwaS5jb25zdGFudHMqTwoI", "TW92ZVR5cGUSFQoRTU9WRV9UWVBFX1VOS05PV04QABIVChFNT1ZFX1RZUEVf", - "Rk9SV0FSRBABEhUKEU1PVkVfVFlQRV9SRVRSRUFUEAIqiQEKDkVudGl0eVBy", + "Rk9SV0FSRBABEhUKEU1PVkVfVFlQRV9SRVRSRUFUEAIqywEKDkVudGl0eVBy", "b3BlcnR5EhsKF0VOVElUWV9QUk9QRVJUWV9VTktOT1dOEAASHAoYRU5USVRZ", "X1BST1BFUlRZX1BPU0lUSU9OEAESIAocRU5USVRZX1BST1BFUlRZX0FUVEFD", - "S19USU1FUhACEhoKFkVOVElUWV9QUk9QRVJUWV9IRUFMVEgQAyqAAQoJQ3Vy", - "dmVUeXBlEhYKEkNVUlZFX1RZUEVfVU5LTk9XThAAEhoKFkNVUlZFX1RZUEVf", - "TElORUFSX01PVkUQARITCg9DVVJWRV9UWVBFX1NURVAQAhIUChBDVVJWRV9U", - "WVBFX0RFTFRBEAMSFAoQQ1VSVkVfVFlQRV9USU1FUhAEKlgKCkVudGl0eVR5", - "cGUSFwoTRU5USVRZX1RZUEVfVU5LTk9XThAAEhQKEEVOVElUWV9UWVBFX1RB", - "TksQARIbChdFTlRJVFlfVFlQRV9FTlRJVFlfTElTVBACQixaEmdhbWUuYXBp", - "LmNvbnN0YW50c6oCFURGLkdhbWUuQVBJLkNvbnN0YW50c2IGcHJvdG8z")); + "S19USU1FUhACEhoKFkVOVElUWV9QUk9QRVJUWV9IRUFMVEgQAxIhCh1FTlRJ", + "VFlfUFJPUEVSVFlfQVRUQUNLX1RBUkdFVBAEEh0KGUVOVElUWV9QUk9QRVJU", + "WV9DTElFTlRfSUQQBSqAAQoJQ3VydmVUeXBlEhYKEkNVUlZFX1RZUEVfVU5L", + "Tk9XThAAEhoKFkNVUlZFX1RZUEVfTElORUFSX01PVkUQARITCg9DVVJWRV9U", + "WVBFX1NURVAQAhIUChBDVVJWRV9UWVBFX0RFTFRBEAMSFAoQQ1VSVkVfVFlQ", + "RV9USU1FUhAEKlgKCkVudGl0eVR5cGUSFwoTRU5USVRZX1RZUEVfVU5LTk9X", + "ThAAEhQKEEVOVElUWV9UWVBFX1RBTksQARIbChdFTlRJVFlfVFlQRV9FTlRJ", + "VFlfTElTVBACQixaEmdhbWUuYXBpLmNvbnN0YW50c6oCFURGLkdhbWUuQVBJ", + "LkNvbnN0YW50c2IGcHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::DF.Game.API.Constants.MoveType), typeof(global::DF.Game.API.Constants.EntityProperty), typeof(global::DF.Game.API.Constants.CurveType), typeof(global::DF.Game.API.Constants.EntityType), }, null, null)); @@ -61,6 +63,8 @@ public enum EntityProperty { [pbr::OriginalName("ENTITY_PROPERTY_POSITION")] Position = 1, [pbr::OriginalName("ENTITY_PROPERTY_ATTACK_TIMER")] AttackTimer = 2, [pbr::OriginalName("ENTITY_PROPERTY_HEALTH")] Health = 3, + [pbr::OriginalName("ENTITY_PROPERTY_ATTACK_TARGET")] AttackTarget = 4, + [pbr::OriginalName("ENTITY_PROPERTY_CLIENT_ID")] ClientId = 5, } /// diff --git a/client/DownFlux/Assets/Protos/API/Constants/Constants.g.cs.meta b/client/DownFlux/Assets/Protos/API/Constants/Constants.g.cs.meta index 94ce201..2aef890 100644 --- a/client/DownFlux/Assets/Protos/API/Constants/Constants.g.cs.meta +++ b/client/DownFlux/Assets/Protos/API/Constants/Constants.g.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 4c5fbd4e5b27ad8e79bd85550d5d2aff +guid: 2b2e66fc2c8011499a4de7aa9faefb5f MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/client/DownFlux/Assets/Protos/API/Data.meta b/client/DownFlux/Assets/Protos/API/Data.meta index 9255af9..18c1793 100644 --- a/client/DownFlux/Assets/Protos/API/Data.meta +++ b/client/DownFlux/Assets/Protos/API/Data.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 53a6ce4c7c7e89ff08f1f8c64db4a658 +guid: e85f43d02fbbf7118a8fefd4c4b3c174 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/API/Data/Data.g.cs b/client/DownFlux/Assets/Protos/API/Data/Data.g.cs index 9425273..ccf5e49 100644 --- a/client/DownFlux/Assets/Protos/API/Data/Data.g.cs +++ b/client/DownFlux/Assets/Protos/API/Data/Data.g.cs @@ -26,27 +26,29 @@ static DataReflection() { string.Concat( "Cg5hcGkvZGF0YS5wcm90bxINZ2FtZS5hcGkuZGF0YRoTYXBpL2NvbnN0YW50", "cy5wcm90bxoeZ29vZ2xlL3Byb3RvYnVmL2R1cmF0aW9uLnByb3RvGh9nb29n", - "bGUvcHJvdG9idWYvdGltZXN0YW1wLnByb3RvIiAKCFBvc2l0aW9uEgkKAXgY", - "ASABKAESCQoBeRgCIAEoASIiCgpDb29yZGluYXRlEgkKAXgYASABKAUSCQoB", - "eRgCIAEoBSKbAQoKQ3VydmVEYXR1bRIMCgR0aWNrGAEgASgBEhQKCmJvb2xf", - "ZGF0dW0YAiABKAhIABIVCgtpbnQzMl9kYXR1bRgDIAEoBUgAEhYKDGRvdWJs", - "ZV9kYXR1bRgEIAEoAUgAEjEKDnBvc2l0aW9uX2RhdHVtGAUgASgLMhcuZ2Ft", - "ZS5hcGkuZGF0YS5Qb3NpdGlvbkgAQgcKBWRhdHVtIrQBCgVDdXJ2ZRIRCgll", - "bnRpdHlfaWQYASABKAkSNAoIcHJvcGVydHkYAiABKA4yIi5nYW1lLmFwaS5j", - "b25zdGFudHMuRW50aXR5UHJvcGVydHkSKwoEdHlwZRgDIAEoDjIdLmdhbWUu", - "YXBpLmNvbnN0YW50cy5DdXJ2ZVR5cGUSJwoEZGF0YRgEIAMoCzIZLmdhbWUu", - "YXBpLmRhdGEuQ3VydmVEYXR1bRIMCgR0aWNrGAUgASgBIpIBCgxTZXJ2ZXJT", - "dGF0dXMSEgoKaXNfc3RhcnRlZBgBIAEoCBIMCgR0aWNrGAIgASgBEjAKDXRp", - "Y2tfZHVyYXRpb24YAyABKAsyGS5nb29nbGUucHJvdG9idWYuRHVyYXRpb24S", - "LgoKc3RhcnRfdGltZRgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3Rh", - "bXAiSQoGRW50aXR5EhEKCWVudGl0eV9pZBgBIAEoCRIsCgR0eXBlGAIgASgO", - "Mh4uZ2FtZS5hcGkuY29uc3RhbnRzLkVudGl0eVR5cGUiWgoJR2FtZVN0YXRl", - "EiQKBmN1cnZlcxgBIAMoCzIULmdhbWUuYXBpLmRhdGEuQ3VydmUSJwoIZW50", - "aXRpZXMYAiADKAsyFS5nYW1lLmFwaS5kYXRhLkVudGl0eUIiWg1nYW1lLmFw", - "aS5kYXRhqgIQREYuR2FtZS5BUEkuRGF0YWIGcHJvdG8z")); + "bGUvcHJvdG9idWYvdGltZXN0YW1wLnByb3RvIh0KCENsaWVudElEEhEKCWNs", + "aWVudF9pZBgBIAEoCSIgCghQb3NpdGlvbhIJCgF4GAEgASgBEgkKAXkYAiAB", + "KAEiIgoKQ29vcmRpbmF0ZRIJCgF4GAEgASgFEgkKAXkYAiABKAUimwEKCkN1", + "cnZlRGF0dW0SDAoEdGljaxgBIAEoARIUCgpib29sX2RhdHVtGAIgASgISAAS", + "FQoLaW50MzJfZGF0dW0YAyABKAVIABIWCgxkb3VibGVfZGF0dW0YBCABKAFI", + "ABIxCg5wb3NpdGlvbl9kYXR1bRgFIAEoCzIXLmdhbWUuYXBpLmRhdGEuUG9z", + "aXRpb25IAEIHCgVkYXR1bSK0AQoFQ3VydmUSEQoJZW50aXR5X2lkGAEgASgJ", + "EjQKCHByb3BlcnR5GAIgASgOMiIuZ2FtZS5hcGkuY29uc3RhbnRzLkVudGl0", + "eVByb3BlcnR5EisKBHR5cGUYAyABKA4yHS5nYW1lLmFwaS5jb25zdGFudHMu", + "Q3VydmVUeXBlEicKBGRhdGEYBCADKAsyGS5nYW1lLmFwaS5kYXRhLkN1cnZl", + "RGF0dW0SDAoEdGljaxgFIAEoASKSAQoMU2VydmVyU3RhdHVzEhIKCmlzX3N0", + "YXJ0ZWQYASABKAgSDAoEdGljaxgCIAEoARIwCg10aWNrX2R1cmF0aW9uGAMg", + "ASgLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEi4KCnN0YXJ0X3RpbWUY", + "BCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIkkKBkVudGl0eRIR", + "CgllbnRpdHlfaWQYASABKAkSLAoEdHlwZRgCIAEoDjIeLmdhbWUuYXBpLmNv", + "bnN0YW50cy5FbnRpdHlUeXBlIloKCUdhbWVTdGF0ZRIkCgZjdXJ2ZXMYASAD", + "KAsyFC5nYW1lLmFwaS5kYXRhLkN1cnZlEicKCGVudGl0aWVzGAIgAygLMhUu", + "Z2FtZS5hcGkuZGF0YS5FbnRpdHlCIloNZ2FtZS5hcGkuZGF0YaoCEERGLkdh", + "bWUuQVBJLkRhdGFiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::DF.Game.API.Constants.ConstantsReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::DF.Game.API.Data.ClientID), global::DF.Game.API.Data.ClientID.Parser, new[]{ "ClientId" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::DF.Game.API.Data.Position), global::DF.Game.API.Data.Position.Parser, new[]{ "X", "Y" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::DF.Game.API.Data.Coordinate), global::DF.Game.API.Data.Coordinate.Parser, new[]{ "X", "Y" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::DF.Game.API.Data.CurveDatum), global::DF.Game.API.Data.CurveDatum.Parser, new[]{ "Tick", "BoolDatum", "Int32Datum", "DoubleDatum", "PositionDatum" }, new[]{ "Datum" }, null, null, null), @@ -60,6 +62,183 @@ static DataReflection() { } #region Messages + /// + /// ClientID contains identification information about a specific client + /// connected to the game. This struct is surfaced as public information and does + /// not contain any authentication-related tokens. + /// + public sealed partial class ClientID : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ClientID()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::DF.Game.API.Data.DataReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ClientID() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ClientID(ClientID other) : this() { + clientId_ = other.clientId_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ClientID Clone() { + return new ClientID(this); + } + + /// Field number for the "client_id" field. + public const int ClientIdFieldNumber = 1; + private string clientId_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string ClientId { + get { return clientId_; } + set { + clientId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ClientID); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ClientID other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ClientId != other.ClientId) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (ClientId.Length != 0) hash ^= ClientId.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (ClientId.Length != 0) { + output.WriteRawTag(10); + output.WriteString(ClientId); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (ClientId.Length != 0) { + output.WriteRawTag(10); + output.WriteString(ClientId); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (ClientId.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ClientId); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ClientID other) { + if (other == null) { + return; + } + if (other.ClientId.Length != 0) { + ClientId = other.ClientId; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + ClientId = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + ClientId = input.ReadString(); + break; + } + } + } + } + #endif + + } + /// /// Position is a specific point in the map, representing a point in the map. /// @@ -75,7 +254,7 @@ public sealed partial class Position : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { - get { return global::DF.Game.API.Data.DataReflection.Descriptor.MessageTypes[0]; } + get { return global::DF.Game.API.Data.DataReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -287,7 +466,7 @@ public sealed partial class Coordinate : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { - get { return global::DF.Game.API.Data.DataReflection.Descriptor.MessageTypes[1]; } + get { return global::DF.Game.API.Data.DataReflection.Descriptor.MessageTypes[2]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -500,7 +679,7 @@ public sealed partial class CurveDatum : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { - get { return global::DF.Game.API.Data.DataReflection.Descriptor.MessageTypes[2]; } + get { return global::DF.Game.API.Data.DataReflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -870,7 +1049,7 @@ public sealed partial class Curve : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { - get { return global::DF.Game.API.Data.DataReflection.Descriptor.MessageTypes[3]; } + get { return global::DF.Game.API.Data.DataReflection.Descriptor.MessageTypes[4]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1183,7 +1362,7 @@ public sealed partial class ServerStatus : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { - get { return global::DF.Game.API.Data.DataReflection.Descriptor.MessageTypes[4]; } + get { return global::DF.Game.API.Data.DataReflection.Descriptor.MessageTypes[5]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1493,7 +1672,7 @@ public sealed partial class Entity : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { - get { return global::DF.Game.API.Data.DataReflection.Descriptor.MessageTypes[5]; } + get { return global::DF.Game.API.Data.DataReflection.Descriptor.MessageTypes[6]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1704,7 +1883,7 @@ public sealed partial class GameState : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { - get { return global::DF.Game.API.Data.DataReflection.Descriptor.MessageTypes[6]; } + get { return global::DF.Game.API.Data.DataReflection.Descriptor.MessageTypes[7]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] diff --git a/client/DownFlux/Assets/Protos/API/Data/Data.g.cs.meta b/client/DownFlux/Assets/Protos/API/Data/Data.g.cs.meta index d9d7154..3f1ed81 100644 --- a/client/DownFlux/Assets/Protos/API/Data/Data.g.cs.meta +++ b/client/DownFlux/Assets/Protos/API/Data/Data.g.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: e84207228d95eea1a943b8e04bae869d +guid: 4ae2e2de8d8b26104af37ebbf05b78d1 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/client/DownFlux/Assets/Protos/ApiGrpc.cs.meta b/client/DownFlux/Assets/Protos/ApiGrpc.cs.meta index 73470c9..c16ff74 100644 --- a/client/DownFlux/Assets/Protos/ApiGrpc.cs.meta +++ b/client/DownFlux/Assets/Protos/ApiGrpc.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: f1248dd36d97ede5780ac23ca1ae763d +guid: 513e0418d9f20f5989e3e67177ed1673 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/client/DownFlux/Assets/Protos/Engine.meta b/client/DownFlux/Assets/Protos/Engine.meta index b1d6e60..03b43a5 100644 --- a/client/DownFlux/Assets/Protos/Engine.meta +++ b/client/DownFlux/Assets/Protos/Engine.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 341ff9a715747d215b889a54ef7fa0bd +guid: 5cbcfb1b8a69725aaa0edd3c0cc067af folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Engine/FSM.meta b/client/DownFlux/Assets/Protos/Engine/FSM.meta index cf9ceba..b28b82e 100644 --- a/client/DownFlux/Assets/Protos/Engine/FSM.meta +++ b/client/DownFlux/Assets/Protos/Engine/FSM.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 5301a9e58793fd6f6bbea3ff82643037 +guid: 8a118d5bd6343dc2dae272005223d7a4 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Engine/FSM/API.meta b/client/DownFlux/Assets/Protos/Engine/FSM/API.meta index 8bc22c7..6dd40fc 100644 --- a/client/DownFlux/Assets/Protos/Engine/FSM/API.meta +++ b/client/DownFlux/Assets/Protos/Engine/FSM/API.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 5cbe69df6f91d82fa8f36cadcb01d93b +guid: 39f3d5f3e3bd32981bcda40b78c35031 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Engine/FSM/API/Constants.meta b/client/DownFlux/Assets/Protos/Engine/FSM/API/Constants.meta index cb02222..ae15395 100644 --- a/client/DownFlux/Assets/Protos/Engine/FSM/API/Constants.meta +++ b/client/DownFlux/Assets/Protos/Engine/FSM/API/Constants.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 9cd0f19f5b9f7c368a2a418862b5753d +guid: 3d83275c861ff125e800654b7c3fd8e8 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Engine/FSM/API/Constants/Constants.g.cs b/client/DownFlux/Assets/Protos/Engine/FSM/API/Constants/Constants.g.cs index 22c7f76..c6cb0fb 100644 --- a/client/DownFlux/Assets/Protos/Engine/FSM/API/Constants/Constants.g.cs +++ b/client/DownFlux/Assets/Protos/Engine/FSM/API/Constants/Constants.g.cs @@ -30,15 +30,17 @@ static ConstantsReflection() { "RRACEhIKDkZTTV9UWVBFX0NIQVNFEAMSEwoPRlNNX1RZUEVfQVRUQUNLEAQS", "FAoPRlNNX1RZUEVfQ0xJRU5UEOgHKl0KCkNoYXNlU3RhdGUSFwoTQ0hBU0Vf", "U1RBVEVfVU5LTk9XThAAEhgKFENIQVNFX1NUQVRFX0lOX1JBTkdFEAESHAoY", - "Q0hBU0VfU1RBVEVfT1VUX09GX1JBTkdFEAIqkwEKC0NvbW1vblN0YXRlEhgK", - "FENPTU1PTl9TVEFURV9VTktOT1dOEAASGAoUQ09NTU9OX1NUQVRFX1BFTkRJ", - "TkcQARIaChZDT01NT05fU1RBVEVfRVhFQ1VUSU5HEAISGQoVQ09NTU9OX1NU", - "QVRFX0NBTkNFTEVEEAMSGQoVQ09NTU9OX1NUQVRFX0ZJTklTSEVEEARCQlod", - "Z2FtZS5lbmdpbmUuZnNtLmFwaS5jb25zdGFudHOqAiBERi5HYW1lLkVuZ2lu", - "ZS5GU00uQVBJLkNvbnN0YW50c2IGcHJvdG8z")); + "Q0hBU0VfU1RBVEVfT1VUX09GX1JBTkdFEAIqQAoLQXR0YWNrU3RhdGUSGAoU", + "QVRUQUNLX1NUQVRFX1VOS05PV04QABIXChNBVFRBQ0tfU1RBVEVfRklSSU5H", + "EAEqkwEKC0NvbW1vblN0YXRlEhgKFENPTU1PTl9TVEFURV9VTktOT1dOEAAS", + "GAoUQ09NTU9OX1NUQVRFX1BFTkRJTkcQARIaChZDT01NT05fU1RBVEVfRVhF", + "Q1VUSU5HEAISGQoVQ09NTU9OX1NUQVRFX0NBTkNFTEVEEAMSGQoVQ09NTU9O", + "X1NUQVRFX0ZJTklTSEVEEARCQlodZ2FtZS5lbmdpbmUuZnNtLmFwaS5jb25z", + "dGFudHOqAiBERi5HYW1lLkVuZ2luZS5GU00uQVBJLkNvbnN0YW50c2IGcHJv", + "dG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedClrTypeInfo(new[] {typeof(global::DF.Game.Engine.FSM.API.Constants.FSMType), typeof(global::DF.Game.Engine.FSM.API.Constants.ChaseState), typeof(global::DF.Game.Engine.FSM.API.Constants.CommonState), }, null, null)); + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::DF.Game.Engine.FSM.API.Constants.FSMType), typeof(global::DF.Game.Engine.FSM.API.Constants.ChaseState), typeof(global::DF.Game.Engine.FSM.API.Constants.AttackState), typeof(global::DF.Game.Engine.FSM.API.Constants.CommonState), }, null, null)); } #endregion @@ -53,18 +55,30 @@ public enum FSMType { [pbr::OriginalName("FSM_TYPE_CLIENT")] Client = 1000, } + /// + /// TODO(minkezhang): Migrate to //server/fsm/api/. + /// public enum ChaseState { [pbr::OriginalName("CHASE_STATE_UNKNOWN")] Unknown = 0, [pbr::OriginalName("CHASE_STATE_IN_RANGE")] InRange = 1, [pbr::OriginalName("CHASE_STATE_OUT_OF_RANGE")] OutOfRange = 2, } + /// + /// TODO(minkezhang): Migrate to //server/fsm/api/. + /// + public enum AttackState { + [pbr::OriginalName("ATTACK_STATE_UNKNOWN")] Unknown = 0, + [pbr::OriginalName("ATTACK_STATE_FIRING")] Firing = 1, + } + public enum CommonState { [pbr::OriginalName("COMMON_STATE_UNKNOWN")] Unknown = 0, [pbr::OriginalName("COMMON_STATE_PENDING")] Pending = 1, [pbr::OriginalName("COMMON_STATE_EXECUTING")] Executing = 2, /// - /// External cancellation due to precedence. + /// External cancellation due to explicit call or implicitly via precedence + /// testing. /// [pbr::OriginalName("COMMON_STATE_CANCELED")] Canceled = 3, [pbr::OriginalName("COMMON_STATE_FINISHED")] Finished = 4, diff --git a/client/DownFlux/Assets/Protos/Engine/FSM/API/Constants/Constants.g.cs.meta b/client/DownFlux/Assets/Protos/Engine/FSM/API/Constants/Constants.g.cs.meta index 445e53a..08b74ac 100644 --- a/client/DownFlux/Assets/Protos/Engine/FSM/API/Constants/Constants.g.cs.meta +++ b/client/DownFlux/Assets/Protos/Engine/FSM/API/Constants/Constants.g.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 0c57722d064317e84a0cb53a2013cbac +guid: 566fd6ad1f8c45775a6e00379c032f29 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/client/DownFlux/Assets/Protos/Engine/Server.meta b/client/DownFlux/Assets/Protos/Engine/Server.meta index 84183e4..d76a4e0 100644 --- a/client/DownFlux/Assets/Protos/Engine/Server.meta +++ b/client/DownFlux/Assets/Protos/Engine/Server.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 0e4dcd32fc639042a888e295c8691327 +guid: c2229972e657b56fe809a128c3c8d618 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Engine/Server/Client.meta b/client/DownFlux/Assets/Protos/Engine/Server/Client.meta index 3ca2fb2..23b646c 100644 --- a/client/DownFlux/Assets/Protos/Engine/Server/Client.meta +++ b/client/DownFlux/Assets/Protos/Engine/Server/Client.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: ef73f87be80dd5ad7997a17fe0411690 +guid: f765b0f65fea6d2418adc141258bdf9f folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Engine/Server/Client/API.meta b/client/DownFlux/Assets/Protos/Engine/Server/Client/API.meta index 4fcd8b4..727c65b 100644 --- a/client/DownFlux/Assets/Protos/Engine/Server/Client/API.meta +++ b/client/DownFlux/Assets/Protos/Engine/Server/Client/API.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: b12ef97c6c38273feba8087d4653046d +guid: cb1b07cc1cf062b36b21c19cfac173dd folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Engine/Server/Client/API/Constants.meta b/client/DownFlux/Assets/Protos/Engine/Server/Client/API/Constants.meta index fde03d0..e4d1366 100644 --- a/client/DownFlux/Assets/Protos/Engine/Server/Client/API/Constants.meta +++ b/client/DownFlux/Assets/Protos/Engine/Server/Client/API/Constants.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: d8a97fee6285cf98d94e8fa53b114cd8 +guid: 4eba38492b6e0df9c9cd276b91c75c3d folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Engine/Server/Client/API/Constants/Constants.g.cs.meta b/client/DownFlux/Assets/Protos/Engine/Server/Client/API/Constants/Constants.g.cs.meta index 6d41ef1..94686ee 100644 --- a/client/DownFlux/Assets/Protos/Engine/Server/Client/API/Constants/Constants.g.cs.meta +++ b/client/DownFlux/Assets/Protos/Engine/Server/Client/API/Constants/Constants.g.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 471d5bfdccf93e4b18952a92fcc96448 +guid: e01309a5899ad6245bf0fd26302920a9 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/client/DownFlux/Assets/Protos/Engine/Service/Visitor/API/Constants.meta b/client/DownFlux/Assets/Protos/Engine/Service/Visitor/API/Constants.meta deleted file mode 100644 index 8445f38..0000000 --- a/client/DownFlux/Assets/Protos/Engine/Service/Visitor/API/Constants.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: a80d34ec27c802db5992c3fb4e02af5a -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/client/DownFlux/Assets/Protos/Engine/Service/Visitor/API/Constants/Constants.g.cs b/client/DownFlux/Assets/Protos/Engine/Service/Visitor/API/Constants/Constants.g.cs deleted file mode 100644 index 12ed3a6..0000000 --- a/client/DownFlux/Assets/Protos/Engine/Service/Visitor/API/Constants/Constants.g.cs +++ /dev/null @@ -1,62 +0,0 @@ -// -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: engine/visitor/api/constants.proto -// -#pragma warning disable 1591, 0612, 3021 -#region Designer generated code - -using pb = global::Google.Protobuf; -using pbc = global::Google.Protobuf.Collections; -using pbr = global::Google.Protobuf.Reflection; -using scg = global::System.Collections.Generic; -namespace DF.Game.Engine.Service.Visitor.API.Constants { - - /// Holder for reflection information generated from engine/visitor/api/constants.proto - public static partial class ConstantsReflection { - - #region Descriptor - /// File descriptor for engine/visitor/api/constants.proto - public static pbr::FileDescriptor Descriptor { - get { return descriptor; } - } - private static pbr::FileDescriptor descriptor; - - static ConstantsReflection() { - byte[] descriptorData = global::System.Convert.FromBase64String( - string.Concat( - "CiJlbmdpbmUvdmlzaXRvci9hcGkvY29uc3RhbnRzLnByb3RvEilnYW1lLmVu", - "Z2luZS5zZXJ2aWNlLnZpc2l0b3IuYXBpLmNvbnN0YW50cypQCglBZ2VudFR5", - "cGUSFgoSQUdFTlRfVFlQRV9VTktOT1dOEAASEgoOQUdFTlRfVFlQRV9GU00Q", - "ARIXChNBR0VOVF9UWVBFX0ZTTV9MSVNUEAIqiQEKC1Zpc2l0b3JUeXBlEhgK", - "FFZJU0lUT1JfVFlQRV9VTktOT1dOEAASFQoRVklTSVRPUl9UWVBFX01PVkUQ", - "ARIYChRWSVNJVE9SX1RZUEVfUFJPRFVDRRACEhYKElZJU0lUT1JfVFlQRV9D", - "SEFTRRADEhcKE1ZJU0lUT1JfVFlQRV9BVFRBQ0sQBEJZWihnYW1lLnNlcnZl", - "ci5lbmdpbmUudmlzaXRvci5hcGkuY29uc3RhbnRzqgIsREYuR2FtZS5Fbmdp", - "bmUuU2VydmljZS5WaXNpdG9yLkFQSS5Db25zdGFudHNiBnByb3RvMw==")); - descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, - new pbr::FileDescriptor[] { }, - new pbr::GeneratedClrTypeInfo(new[] {typeof(global::DF.Game.Engine.Service.Visitor.API.Constants.AgentType), typeof(global::DF.Game.Engine.Service.Visitor.API.Constants.VisitorType), }, null, null)); - } - #endregion - - } - #region Enums - public enum AgentType { - [pbr::OriginalName("AGENT_TYPE_UNKNOWN")] Unknown = 0, - [pbr::OriginalName("AGENT_TYPE_FSM")] Fsm = 1, - [pbr::OriginalName("AGENT_TYPE_FSM_LIST")] FsmList = 2, - } - - public enum VisitorType { - [pbr::OriginalName("VISITOR_TYPE_UNKNOWN")] Unknown = 0, - [pbr::OriginalName("VISITOR_TYPE_MOVE")] Move = 1, - [pbr::OriginalName("VISITOR_TYPE_PRODUCE")] Produce = 2, - [pbr::OriginalName("VISITOR_TYPE_CHASE")] Chase = 3, - [pbr::OriginalName("VISITOR_TYPE_ATTACK")] Attack = 4, - } - - #endregion - -} - -#endregion Designer generated code diff --git a/client/DownFlux/Assets/Protos/Map.meta b/client/DownFlux/Assets/Protos/Map.meta index eab5b6f..09e4d3b 100644 --- a/client/DownFlux/Assets/Protos/Map.meta +++ b/client/DownFlux/Assets/Protos/Map.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 09ab26d3c5ef51a7ebfc15c22cbfd080 +guid: c08d1c145c89fce6e8295f4f95499ea7 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Map/API.meta b/client/DownFlux/Assets/Protos/Map/API.meta index d3cecc2..7aae792 100644 --- a/client/DownFlux/Assets/Protos/Map/API.meta +++ b/client/DownFlux/Assets/Protos/Map/API.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 9667390293b81a5fc868f2750c4bb903 +guid: 0b227a5317d9cb72aac138f7fd40ef94 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Map/API/Constants.meta b/client/DownFlux/Assets/Protos/Map/API/Constants.meta index 9d2eed7..93af26c 100644 --- a/client/DownFlux/Assets/Protos/Map/API/Constants.meta +++ b/client/DownFlux/Assets/Protos/Map/API/Constants.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: b03bfd8f0ad99ad8da9bc91e2739666b +guid: 2fd10454e3754d6828961d1eb9150b85 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Map/API/Constants/Constants.g.cs.meta b/client/DownFlux/Assets/Protos/Map/API/Constants/Constants.g.cs.meta index 80a8aa7..b997d25 100644 --- a/client/DownFlux/Assets/Protos/Map/API/Constants/Constants.g.cs.meta +++ b/client/DownFlux/Assets/Protos/Map/API/Constants/Constants.g.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: e592423b706e1a27fa864f670889b84f +guid: 2f87a5d10c1b319399254e3577de2098 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/client/DownFlux/Assets/Protos/Map/API/Data.meta b/client/DownFlux/Assets/Protos/Map/API/Data.meta index 155fa2b..7035edb 100644 --- a/client/DownFlux/Assets/Protos/Map/API/Data.meta +++ b/client/DownFlux/Assets/Protos/Map/API/Data.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 48ca00b8e96010274b1f539566375e4b +guid: d49815746dda863e8bf5d6297517a9c0 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Map/API/Data/Data.g.cs.meta b/client/DownFlux/Assets/Protos/Map/API/Data/Data.g.cs.meta index 46a0221..783fb6c 100644 --- a/client/DownFlux/Assets/Protos/Map/API/Data/Data.g.cs.meta +++ b/client/DownFlux/Assets/Protos/Map/API/Data/Data.g.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 2fd8f0a3bd9404046bcaa06b2578be92 +guid: 86a8a47ca498ae1609e86899e7449464 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/client/DownFlux/Assets/Protos/Pathing.meta b/client/DownFlux/Assets/Protos/Pathing.meta index 8599842..96826f4 100644 --- a/client/DownFlux/Assets/Protos/Pathing.meta +++ b/client/DownFlux/Assets/Protos/Pathing.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 691377661827b9b1d84dbfeca0a1c166 +guid: 51f93c5de3cf650eaae1b0d4189cd614 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Pathing/API.meta b/client/DownFlux/Assets/Protos/Pathing/API.meta index 359ecf8..2176aec 100644 --- a/client/DownFlux/Assets/Protos/Pathing/API.meta +++ b/client/DownFlux/Assets/Protos/Pathing/API.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: edc6839b20e07f97d80eab96a3b60ffe +guid: e8dcf988fa76f7fd4aec69ac6f73895e folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Pathing/API/Constants.meta b/client/DownFlux/Assets/Protos/Pathing/API/Constants.meta index 0fc4fed..fde7252 100644 --- a/client/DownFlux/Assets/Protos/Pathing/API/Constants.meta +++ b/client/DownFlux/Assets/Protos/Pathing/API/Constants.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 684b4d5902f329457b5049ae4aa01568 +guid: 6756d1395aa2b77b08336ebcd4a85efe folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Pathing/API/Constants/Constants.g.cs.meta b/client/DownFlux/Assets/Protos/Pathing/API/Constants/Constants.g.cs.meta index 0c69cb2..b8a6069 100644 --- a/client/DownFlux/Assets/Protos/Pathing/API/Constants/Constants.g.cs.meta +++ b/client/DownFlux/Assets/Protos/Pathing/API/Constants/Constants.g.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c6ee116b1bcafb37c80aa493ba980473 +guid: 2147ba7904a4be9fe8a1d630ccf4910c MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/client/DownFlux/Assets/Protos/Pathing/API/Data.meta b/client/DownFlux/Assets/Protos/Pathing/API/Data.meta index bf22b58..31a9fb5 100644 --- a/client/DownFlux/Assets/Protos/Pathing/API/Data.meta +++ b/client/DownFlux/Assets/Protos/Pathing/API/Data.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 1a36b1e07fc9f4082b6096ce5c7c75fd +guid: 938bedc08aa44cfa4b88214c558df7ec folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Pathing/API/Data/Data.g.cs.meta b/client/DownFlux/Assets/Protos/Pathing/API/Data/Data.g.cs.meta index db4bc28..48081cd 100644 --- a/client/DownFlux/Assets/Protos/Pathing/API/Data/Data.g.cs.meta +++ b/client/DownFlux/Assets/Protos/Pathing/API/Data/Data.g.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 5e1b48a066c30d6f89cec22577064233 +guid: 3dea9973283358abe8f568aebbf8b0ad MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/client/DownFlux/Assets/Protos/ProtoAssembly.asmdef b/client/DownFlux/Assets/Protos/ProtoAssembly.asmdef index 5c58faa..681d219 100644 --- a/client/DownFlux/Assets/Protos/ProtoAssembly.asmdef +++ b/client/DownFlux/Assets/Protos/ProtoAssembly.asmdef @@ -10,4 +10,4 @@ "defineConstraints": [], "versionDefines": [], "noEngineReferences": false -} \ No newline at end of file +} diff --git a/client/DownFlux/Assets/Protos/Server.meta b/client/DownFlux/Assets/Protos/Server.meta index 77566c3..723e01a 100644 --- a/client/DownFlux/Assets/Protos/Server.meta +++ b/client/DownFlux/Assets/Protos/Server.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: f64f00c1588c44b6995ad3e51b15a0e4 +guid: f1d4e102db37493bea2343b64ae14cde folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Server/Service.meta b/client/DownFlux/Assets/Protos/Server/Service.meta index 4211bd3..8ae6330 100644 --- a/client/DownFlux/Assets/Protos/Server/Service.meta +++ b/client/DownFlux/Assets/Protos/Server/Service.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 39772b5504d9ff81ba0ef5ba8eba4c7b +guid: 6b0c06f3c75597f2fb7b615e7c4aae82 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Server/Service/API.meta b/client/DownFlux/Assets/Protos/Server/Service/API.meta index 2ac6f0d..8c57cf0 100644 --- a/client/DownFlux/Assets/Protos/Server/Service/API.meta +++ b/client/DownFlux/Assets/Protos/Server/Service/API.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c6c5c01709addf59cb821f1c14048f35 +guid: c14b6b113e1d184f3892874a71d69c9d folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Server/Service/API/Constants.meta b/client/DownFlux/Assets/Protos/Server/Service/API/Constants.meta index 9bdd5bb..053ebea 100644 --- a/client/DownFlux/Assets/Protos/Server/Service/API/Constants.meta +++ b/client/DownFlux/Assets/Protos/Server/Service/API/Constants.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: e69940044a2e65b3abf9ca3760327c2e +guid: 6643b7d73ecff8780abecd2e9738fe07 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Protos/Server/Service/API/Constants/Constants.g.cs.meta b/client/DownFlux/Assets/Protos/Server/Service/API/Constants/Constants.g.cs.meta index 8c6dca4..32cce24 100644 --- a/client/DownFlux/Assets/Protos/Server/Service/API/Constants/Constants.g.cs.meta +++ b/client/DownFlux/Assets/Protos/Server/Service/API/Constants/Constants.g.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 9d91c66827883aa039193ed1abe57e6c +guid: 6015394d397c30c289aa5892a101d752 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/client/DownFlux/Assets/Protos/Engine/Service/Visitor/API.meta b/client/DownFlux/Assets/Scripts/Utilities.meta similarity index 77% rename from client/DownFlux/Assets/Protos/Engine/Service/Visitor/API.meta rename to client/DownFlux/Assets/Scripts/Utilities.meta index 17198bc..19419a5 100644 --- a/client/DownFlux/Assets/Protos/Engine/Service/Visitor/API.meta +++ b/client/DownFlux/Assets/Scripts/Utilities.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 285b0b2156d7bf8afa4dfbcf49268c95 +guid: d0d87dc02adea4622b2ca80fa8858f00 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/client/DownFlux/Assets/Scripts/Utilities/IntentState.cs b/client/DownFlux/Assets/Scripts/Utilities/IntentState.cs new file mode 100644 index 0000000..4167571 --- /dev/null +++ b/client/DownFlux/Assets/Scripts/Utilities/IntentState.cs @@ -0,0 +1,40 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace DF.Utilities.IntentState +{ + enum _StateLookup + { + Unknown = 0 + } + + public class IntentState : DF.Game.Utilities.FSM.Base + { + private static System.Collections.ObjectModel.ReadOnlyDictionary< + _StateLookup, DF.Game.Utilities.FSM.State> _lookup = new System.Collections.ObjectModel.ReadOnlyDictionary< + _StateLookup, DF.Game.Utilities.FSM.State>( + new Dictionary<_StateLookup, DF.Game.Utilities.FSM.State>() + { + { _StateLookup.Unknown, new DF.Game.Utilities.FSM.State((int) _StateLookup.Unknown) } + } + ); + + private static System.Collections.ObjectModel.ReadOnlyDictionary< + DF.Game.Utilities.FSM.State, DF.Game.Utilities.FSM.State> _transitions = new System.Collections.ObjectModel.ReadOnlyDictionary< + DF.Game.Utilities.FSM.State, DF.Game.Utilities.FSM.State>( + new Dictionary() + { + } + ); + + public IntentState(DF.Game.Utilities.FSM.State s) : base(transitions: _transitions, s: s) { } + public override DF.Game.Utilities.FSM.State State() + { + if (Input.GetMouseButtonDown(0)) { + return _lookup[_StateLookup.Unknown]; + } + return _lookup[_StateLookup.Unknown]; + } + } +} \ No newline at end of file diff --git a/client/DownFlux/Assets/Scripts/Utilities/IntentState.cs.meta b/client/DownFlux/Assets/Scripts/Utilities/IntentState.cs.meta new file mode 100644 index 0000000..3d25199 --- /dev/null +++ b/client/DownFlux/Assets/Scripts/Utilities/IntentState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d7207f0bc3ec1a1c8ab189769932665a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/client/DownFlux/README.md b/client/DownFlux/README.md index b6dec50..8e7fcc5 100644 --- a/client/DownFlux/README.md +++ b/client/DownFlux/README.md @@ -108,7 +108,8 @@ Generate protobufs from root GitHub repo directory. See for `protoc` flag explanation. ```bash -rm -rf ${PWD}/client/DownFlux/Assets/Protos/* +find ${PWD}/client/DownFlux/Assets/Protos/ -type f ! -iname *.asmdef -delete +find ${PWD}/client/DownFlux/Assets/Protos/ -type d -empty -delete protoc \ -I=${PWD} \ -I=${PWD}/client/DownFlux/Packages/Google.Protobuf.Tools.3.14.0/tools/ \ diff --git a/engine/curve/curve.go b/engine/curve/curve.go index 6e7a45a..aea6acd 100644 --- a/engine/curve/curve.go +++ b/engine/curve/curve.go @@ -19,6 +19,8 @@ import ( // TODO(minkezhang): Translate to generics instead. See // https://blog.golang.org/generics-next-step. // +// TODO(minkezhang): Add ReadOnlyCurve once generics lands. +// // type Curve[T any] interface { // Get(t Tick) T // } diff --git a/engine/entity/BUILD b/engine/entity/BUILD index b59210a..e4d53eb 100644 --- a/engine/entity/BUILD +++ b/engine/entity/BUILD @@ -1,4 +1,4 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") +load("@io_bazel_rules_go//go:def.bzl", "go_library") package(default_visibility=["//visibility:public"]) @@ -8,7 +8,9 @@ go_library( importpath = "github.com/downflux/game/engine/entity/entity", deps = [ "//api:constants_go_proto", + "//api:data_go_proto", "//engine/curve:list", + "//engine/curve/common:step", "//engine/id:id", ], ) diff --git a/engine/entity/entity.go b/engine/entity/entity.go index bfae04f..44daf6a 100644 --- a/engine/entity/entity.go +++ b/engine/entity/entity.go @@ -4,6 +4,7 @@ // Example // // type ConcreteEntity struct { +// entity.Base // entity.LifeCycle // ... // } @@ -12,10 +13,12 @@ package entity import ( "sync" + "github.com/downflux/game/engine/curve/common/step" "github.com/downflux/game/engine/curve/list" "github.com/downflux/game/engine/id/id" gcpb "github.com/downflux/game/api/constants_go_proto" + gdpb "github.com/downflux/game/api/data_go_proto" ) type Entity interface { @@ -26,6 +29,7 @@ type Entity interface { ID() id.EntityID Curves() *list.List + Export() *gdpb.Entity // Start returns the game tick at which the Entity was created. Start() id.Tick @@ -42,6 +46,33 @@ type Entity interface { Delete(tick id.Tick) } +type Base struct { + entityType gcpb.EntityType // Read-only. + id id.EntityID // Read-only. + cidc *step.Curve +} + +func New(t gcpb.EntityType, eid id.EntityID, cidc *step.Curve) *Base { + return &Base{ + entityType: t, + id: eid, + cidc: cidc, + } +} + +func (e Base) Type() gcpb.EntityType { return e.entityType } +func (e Base) ID() id.EntityID { return e.id } + +// Export converts the static properties of the entity into a gdpb.Entity +// object. Note that dynamic properties (e.g. position) are not considered here. +// These properties must be manually converted via Curve.Export instead. +func (e Base) Export() *gdpb.Entity { + return &gdpb.Entity{ + EntityId: e.ID().Value(), + Type: e.Type(), + } +} + // LifeCycle implements a subset of the Entity interface concerned with // tracking the lifecycle of the Entity. Entities such as tanks are created // inside a factory, and are destroyed at the end of the game or when attacked diff --git a/engine/entity/mock/BUILD b/engine/entity/mock/BUILD new file mode 100644 index 0000000..bef1203 --- /dev/null +++ b/engine/entity/mock/BUILD @@ -0,0 +1,25 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +package(default_visibility=["//engine:__subpackages__"]) + +go_library( + name = "simple", + srcs = [":simple.go"], + importpath = "github.com/downflux/game/engine/entity/mock/simple", + deps = [ + "//api:constants_go_proto", + "//engine/curve:list", + "//engine/entity:entity", + "//engine/id:id", + ] +) + +go_test( + name = "simple_test", + srcs = [":simple_test.go"], + importpath = "github.com/downflux/game/engine/entity/mock/simple_test", + embed = [":simple"], + deps = [ + "//engine/entity:entity", + ], +) diff --git a/engine/entity/mock/simple.go b/engine/entity/mock/simple.go new file mode 100644 index 0000000..6d3fca8 --- /dev/null +++ b/engine/entity/mock/simple.go @@ -0,0 +1,22 @@ +package simple + +import ( + "github.com/downflux/game/engine/curve/list" + "github.com/downflux/game/engine/entity/entity" + "github.com/downflux/game/engine/id/id" + + gcpb "github.com/downflux/game/api/constants_go_proto" +) + +type Entity struct { + entity.Base + entity.LifeCycle +} + +func New(eid id.EntityID) *Entity { + return &Entity{ + Base: *entity.New(gcpb.EntityType_ENTITY_TYPE_TANK, eid, nil), + } +} + +func (e *Entity) Curves() *list.List { return nil } diff --git a/engine/entity/mock/simple_test.go b/engine/entity/mock/simple_test.go new file mode 100644 index 0000000..40a6d07 --- /dev/null +++ b/engine/entity/mock/simple_test.go @@ -0,0 +1,9 @@ +package simple + +import ( + "github.com/downflux/game/engine/entity/entity" +) + +var ( + _ entity.Entity = &Entity{} +) diff --git a/engine/fsm/BUILD b/engine/fsm/BUILD index 26ab8b3..609d94c 100644 --- a/engine/fsm/BUILD +++ b/engine/fsm/BUILD @@ -10,10 +10,8 @@ go_test( deps = [ ":action", "//engine/fsm/api:constants_go_proto", + "//engine/fsm/mock:simple", "//engine/id:id", - "//engine/status:status", - "//server/fsm:move", - "//server/entity:tank", ], ) @@ -38,16 +36,11 @@ go_test( deps = [ ":action", ":fsm", - "//api:data_go_proto", "//engine/fsm/api:constants_go_proto", + "//engine/fsm/mock:simple", "//engine/id:id", - "//engine/status:status", - "//engine/visitor:visitor", - "//server/fsm:move", - "//server/entity:tank", "@com_github_google_go_cmp//cmp:go_default_library", "@com_github_google_go_cmp//cmp/cmpopts:go_default_library", - "@org_golang_google_protobuf//testing/protocmp:go_default_library", ], ) @@ -61,7 +54,6 @@ go_library( "//engine/id:id", "//engine/fsm/api:constants_go_proto", "//engine/visitor:visitor", - "//engine/visitor/api:constants_go_proto", "@org_golang_google_grpc//codes:go_default_library", "@org_golang_google_grpc//status:go_default_library", "@org_golang_x_sync//errgroup:go_default_library", @@ -76,7 +68,6 @@ go_library( "//engine/fsm:fsm", "//engine/fsm/api:constants_go_proto", "//engine/visitor:visitor", - "//engine/visitor/api:constants_go_proto", "//engine/id:id", "@org_golang_google_grpc//codes:go_default_library", "@org_golang_google_grpc//status:go_default_library", diff --git a/engine/fsm/action.go b/engine/fsm/action.go index 4459e14..eb33565 100644 --- a/engine/fsm/action.go +++ b/engine/fsm/action.go @@ -8,7 +8,6 @@ import ( "google.golang.org/grpc/status" fcpb "github.com/downflux/game/engine/fsm/api/constants_go_proto" - vcpb "github.com/downflux/game/engine/visitor/api/constants_go_proto" ) type Action interface { @@ -23,17 +22,14 @@ type Action interface { } type Base struct { - visitor.BaseAgent - fsm *fsm.FSM state fsm.State } func New(fsm *fsm.FSM, state fsm.State) *Base { return &Base{ - BaseAgent: *visitor.NewBaseAgent(vcpb.AgentType_AGENT_TYPE_FSM), - fsm: fsm, - state: state, + fsm: fsm, + state: state, } } diff --git a/engine/fsm/api/constants.proto b/engine/fsm/api/constants.proto index 8a1a646..14ff563 100644 --- a/engine/fsm/api/constants.proto +++ b/engine/fsm/api/constants.proto @@ -17,18 +17,26 @@ enum FSMType { FSM_TYPE_CLIENT = 1000; } +// TODO(minkezhang): Migrate to //server/fsm/api/. enum ChaseState { CHASE_STATE_UNKNOWN = 0; CHASE_STATE_IN_RANGE = 1; CHASE_STATE_OUT_OF_RANGE = 2; } +// TODO(minkezhang): Migrate to //server/fsm/api/. +enum AttackState { + ATTACK_STATE_UNKNOWN = 0; + ATTACK_STATE_FIRING = 1; +} + enum CommonState { COMMON_STATE_UNKNOWN = 0; COMMON_STATE_PENDING = 1; COMMON_STATE_EXECUTING = 2; - // External cancellation due to precedence. + // External cancellation due to explicit call or implicitly via precedence + // testing. COMMON_STATE_CANCELED = 3; COMMON_STATE_FINISHED = 4; diff --git a/engine/fsm/list.go b/engine/fsm/list.go index fd3e181..e17b8e1 100644 --- a/engine/fsm/list.go +++ b/engine/fsm/list.go @@ -1,3 +1,4 @@ +// Package list implements a collection of FSM actions. package list import ( @@ -10,11 +11,6 @@ import ( "google.golang.org/grpc/status" fcpb "github.com/downflux/game/engine/fsm/api/constants_go_proto" - vcpb "github.com/downflux/game/engine/visitor/api/constants_go_proto" -) - -const ( - agentType = vcpb.AgentType_AGENT_TYPE_FSM_LIST ) var ( @@ -34,9 +30,9 @@ func New(fsmType fcpb.FSMType) *List { } } -func (l *List) AgentType() vcpb.AgentType { return agentType } -func (l *List) Type() fcpb.FSMType { return l.fsmType } +// TODO(minkezhang): Rename Action. func (l *List) Get(iid id.ActionID) action.Action { return l.actions[iid] } +func (l *List) Type() fcpb.FSMType { return l.fsmType } func (l *List) Clear() error { for iid, i := range l.actions { @@ -52,11 +48,8 @@ func (l *List) Clear() error { return nil } +// TODO(minkezhang): Rename to make clear List is not an FSM agent. func (l *List) Accept(v visitor.Visitor) error { - if err := v.Visit(l); err != nil { - return err - } - var eg errgroup.Group for _, i := range l.actions { i := i diff --git a/engine/fsm/list_test.go b/engine/fsm/list_test.go index e58a037..999f8f6 100644 --- a/engine/fsm/list_test.go +++ b/engine/fsm/list_test.go @@ -1,21 +1,15 @@ package list import ( - "log" "testing" "github.com/downflux/game/engine/fsm/action" "github.com/downflux/game/engine/fsm/fsm" + "github.com/downflux/game/engine/fsm/mock/simple" "github.com/downflux/game/engine/id/id" - "github.com/downflux/game/engine/status/status" - "github.com/downflux/game/engine/visitor/visitor" - "github.com/downflux/game/server/entity/tank" - "github.com/downflux/game/server/fsm/move" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "google.golang.org/protobuf/testing/protocmp" - gdpb "github.com/downflux/game/api/data_go_proto" fcpb "github.com/downflux/game/engine/fsm/api/constants_go_proto" ) @@ -23,31 +17,17 @@ const ( fsmType = fcpb.FSMType_FSM_TYPE_MOVE ) -func newTank(t *testing.T, eid id.EntityID, tick id.Tick, p *gdpb.Position) *tank.Entity { - tankEntity, err := tank.New(eid, tick, p) - if err != nil { - t.Fatalf("New() = %v, want = nil", err) - } - return tankEntity -} - func TestNew(t *testing.T) { l := New(fsmType) if got := l.Type(); got != fsmType { t.Fatalf("Type() = %v, want = %v", got, fsmType) } - - if got := l.AgentType(); got != agentType { - t.Errorf("AgentType() = %v, want = %v", got, agentType) - } } func TestAddError(t *testing.T) { l := New(fcpb.FSMType_FSM_TYPE_UNKNOWN) - i := move.New(newTank(t, "entity-id", 0, nil), status.New(0), nil) - - log.Println(l.Type(), i.Type()) + i := simple.New(id.ActionID("action-id"), 0) if err := l.Add(i); err == nil { t.Error("Add() = nil, want a non-nil error") @@ -55,50 +35,45 @@ func TestAddError(t *testing.T) { } func TestAdd(t *testing.T) { - const iid = "entity-id" + aid := id.ActionID("action-id") l := New(fsmType) - i := move.New(newTank(t, iid, 0, nil), status.New(0), nil) + i := simple.New(aid, 0) if err := l.Add(i); err != nil { t.Fatalf("Add() = %v, want = nil", err) } - if got := l.Get(iid).ID(); got != iid { - t.Errorf("ID() = %v, want = %v", got, iid) + if got := l.Get(aid).ID(); got != aid { + t.Errorf("ID() = %v, want = %v", got, aid) } } func TestAddCancel(t *testing.T) { - const iid = "entity-id" + aid := id.ActionID("action-id") l := New(fsmType) - e := newTank(t, iid, 0, nil) - dfStatus := status.New(0) - i1 := move.New(e, dfStatus, &gdpb.Position{X: 0, Y: 0}) - dfStatus.IncrementTick() - i2 := move.New(e, dfStatus, &gdpb.Position{X: 1, Y: 1}) + a1 := simple.New(aid, 0) + a2 := simple.New(aid, 1) - if err := l.Add(i1); err != nil { + if err := l.Add(a1); err != nil { t.Fatalf("Add() = %v, want = nil", err) } - if err := l.Add(i2); err != nil { + if err := l.Add(a2); err != nil { t.Fatalf("Add() = %v, want = nil", err) } - want := fsm.State(fcpb.CommonState_COMMON_STATE_CANCELED.String()) - if got, err := i1.State(); err != nil || got != want { + want := fsm.State(simple.Canceled) + if got, err := a1.State(); err != nil || got != want { t.Fatalf("State() = %v, %v, want = %v, nil", got, err, want) } if diff := cmp.Diff( - i2, - l.Get(i2.ID()), - cmp.AllowUnexported(move.Action{}, action.Base{}, visitor.BaseAgent{}), + a2, + l.Get(a2.ID()), + cmp.AllowUnexported(simple.Action{}, action.Base{}), cmpopts.IgnoreFields(action.Base{}, "fsm"), - cmpopts.IgnoreFields(move.Action{}, "status", "mux", "e"), - protocmp.Transform(), ); diff != "" { t.Errorf("Get() mismatch (-want +got):\n%v", diff) } diff --git a/engine/fsm/mock/BUILD b/engine/fsm/mock/BUILD new file mode 100644 index 0000000..0a8895a --- /dev/null +++ b/engine/fsm/mock/BUILD @@ -0,0 +1,27 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +package(default_visibility=["//engine:__subpackages__"]) + +go_library( + name = "simple", + srcs = [":simple.go"], + importpath = "github.com/downflux/game/engine/fsm/mock/simple", + deps = [ + "//engine/fsm:action", + "//engine/fsm/api:constants_go_proto", + "//engine/fsm:fsm", + "//engine/id:id", + "//engine/visitor:visitor", + ] +) + +go_test( + name = "simple_test", + srcs = ["simple_test.go"], + importpath = "github.com/downflux/game/engine/fsm/mock/simple_test", + embed = [":simple"], + deps = [ + "//engine/fsm:action", + "//engine/id:id", + ], +) diff --git a/engine/fsm/mock/simple.go b/engine/fsm/mock/simple.go new file mode 100644 index 0000000..b74b400 --- /dev/null +++ b/engine/fsm/mock/simple.go @@ -0,0 +1,65 @@ +package simple + +import ( + "github.com/downflux/game/engine/fsm/action" + "github.com/downflux/game/engine/fsm/fsm" + "github.com/downflux/game/engine/id/id" + "github.com/downflux/game/engine/visitor/visitor" + + fcpb "github.com/downflux/game/engine/fsm/api/constants_go_proto" +) + +const ( + fsmType = fcpb.FSMType_FSM_TYPE_MOVE + Pending = "PENDING" + Canceled = "CANCELED" +) + +var ( + transitions = []fsm.Transition{ + {From: Pending, To: Canceled}, + } + + FSM = fsm.New(transitions, fsmType) +) + +type Action struct { + *action.Base + + id id.ActionID + priority int +} + +func New(aid id.ActionID, priority int) *Action { + return &Action{ + Base: action.New(FSM, Pending), + id: aid, + priority: priority, + } +} + +func (n *Action) Accept(v visitor.Visitor) error { return v.Visit(n) } +func (n *Action) ID() id.ActionID { return n.id } + +func (n *Action) Precedence(i action.Action) bool { + if i.Type() != fsmType || n.ID() != i.ID() { + return false + } + + s, err := n.State() + if err != nil { + return false + } + + m := i.(*Action) + return s == Canceled || n.priority >= m.priority +} + +func (n *Action) Cancel() error { + s, err := n.State() + if err != nil { + return err + } + + return n.To(s, Canceled, false) +} diff --git a/engine/fsm/mock/simple_test.go b/engine/fsm/mock/simple_test.go new file mode 100644 index 0000000..87bb91e --- /dev/null +++ b/engine/fsm/mock/simple_test.go @@ -0,0 +1,96 @@ +package simple + +import ( + "testing" + + "github.com/downflux/game/engine/fsm/action" + "github.com/downflux/game/engine/id/id" +) + +var ( + _ action.Action = &Action{} +) + +func TestNew(t *testing.T) { + aid := id.ActionID("action-id") + priority := 1 + + a := New(aid, priority) + + if got, err := a.State(); err != nil || got != Pending { + t.Fatalf("State() = %v, %v, want = %v, nil", got, err, Pending) + } + + if got := a.ID(); got != aid { + t.Fatalf("ID() = %v, want = %v", got, aid) + } + if got := a.priority; got != priority { + t.Errorf("a.priority = %v, want = %v", got, priority) + } +} + +func TestPrecedence(t *testing.T) { + cancelAction := New(id.ActionID("action-id"), 0) + cancelAction.Cancel() + + low := New(id.ActionID("action-id"), 1) + high := New(id.ActionID("action-id"), 19) + + highDiffID := New(id.ActionID("diff-action-id"), 19) + + testConfigs := []struct { + name string + a1 *Action + a2 *Action + want bool + }{ + {name: "SimpleCase", a1: low, a2: high, want: false}, + {name: "SimpleCaseReverse", a1: high, a2: low, want: true}, + {name: "CancelLowPriority", a1: cancelAction, a2: low, want: true}, + {name: "DifferentID", a1: highDiffID, a2: low, want: false}, + } + + for _, c := range testConfigs { + t.Run(c.name, func(t *testing.T) { + if got := c.a1.Precedence(c.a2); got != c.want { + t.Errorf("Precedence() = %v, want = %v", got, c.want) + } + }) + } +} + +func TestCancel(t *testing.T) { + cancelAction := New(id.ActionID("entity-id"), 0) + if err := cancelAction.Cancel(); err != nil { + t.Fatalf("Cancel() = %v, want = nil", err) + } + + testConfigs := []struct { + name string + action *Action + success bool + }{ + { + name: "PendingCancelTransition", + action: New(id.ActionID("entity-id"), 0), + success: true, + }, + { + name: "InvalidCancel", + action: cancelAction, + success: false, + }, + } + + for _, c := range testConfigs { + t.Run(c.name, func(t *testing.T) { + err := c.action.Cancel() + if c.success && err != nil { + t.Fatalf("Cancel() = %v, want = nil", err) + } + if !c.success && err == nil { + t.Error("Cancel() = nil, want a non-nil error") + } + }) + } +} diff --git a/engine/fsm/schedule.go b/engine/fsm/schedule.go index de330fa..284b3ff 100644 --- a/engine/fsm/schedule.go +++ b/engine/fsm/schedule.go @@ -11,13 +11,6 @@ import ( fcpb "github.com/downflux/game/engine/fsm/api/constants_go_proto" ) -var ( - FSMTypes = []fcpb.FSMType{ - fcpb.FSMType_FSM_TYPE_MOVE, - fcpb.FSMType_FSM_TYPE_PRODUCE, - } -) - type Schedule struct { fsmTypes map[fcpb.FSMType]bool @@ -91,6 +84,7 @@ func (s *Schedule) Merge(t *Schedule) error { return nil } +// TODO(minkezhang): Rename List. func (s *Schedule) Get(fsmType fcpb.FSMType) *list.List { s.mux.Lock() defer s.mux.Unlock() diff --git a/engine/fsm/schedule_test.go b/engine/fsm/schedule_test.go index b79c5ae..ea1a0ef 100644 --- a/engine/fsm/schedule_test.go +++ b/engine/fsm/schedule_test.go @@ -4,47 +4,39 @@ import ( "testing" "github.com/downflux/game/engine/fsm/action" + "github.com/downflux/game/engine/fsm/mock/simple" "github.com/downflux/game/engine/id/id" - "github.com/downflux/game/engine/status/status" - "github.com/downflux/game/server/entity/tank" - "github.com/downflux/game/server/fsm/move" fcpb "github.com/downflux/game/engine/fsm/api/constants_go_proto" ) -func newTank(t *testing.T, eid id.EntityID, tick id.Tick) *tank.Entity { - tankEntity, err := tank.New(eid, tick, nil) - if err != nil { - t.Fatalf("New() = %v, want = nil", err) - } - return tankEntity -} - +// TestAddError validates we cannot add unknown FSMs to the schedule. func TestAddError(t *testing.T) { s := New(nil) - i := move.New(newTank(t, id.EntityID("entity-id"), id.Tick(0)), status.New(0), nil) - if err := s.Add(i); err == nil { - t.Errorf("Add() = nil, want a non-nil error") + a := simple.New(id.ActionID("action-id"), 0) + if err := s.Add(a); err == nil { + t.Errorf("Add() = nil, want a non-nil error %s", err) } } func TestAdd(t *testing.T) { - const eid = "entity-id" + aid := id.ActionID("action-id") s := New([]fcpb.FSMType{fcpb.FSMType_FSM_TYPE_MOVE}) - i := move.New(newTank(t, eid, id.Tick(0)), status.New(0), nil) + i := simple.New(aid, 0) if err := s.Add(i); err != nil { t.Fatalf("Add() = %v, want = nil", err) } - if got := s.Get(fcpb.FSMType_FSM_TYPE_MOVE).Get(eid); got.ID() != eid { - t.Errorf("ID() = %v, want = %v", got, eid) + if got := s.Get(fcpb.FSMType_FSM_TYPE_MOVE).Get(aid); got.ID() != aid { + t.Errorf("ID() = %v, want = %v", got, aid) } } func TestMerge(t *testing.T) { const eid = "entity-id" + aid := id.ActionID("action-id") testConfigs := []struct { name string @@ -58,10 +50,10 @@ func TestMerge(t *testing.T) { s1Types: []fcpb.FSMType{fcpb.FSMType_FSM_TYPE_MOVE}, s2Types: []fcpb.FSMType{fcpb.FSMType_FSM_TYPE_MOVE}, actions: []action.Action{ - move.New(newTank(t, eid, id.Tick(0)), status.New(0), nil), + simple.New(aid, 0), }, want: []action.Action{ - move.New(newTank(t, eid, id.Tick(0)), status.New(0), nil), + simple.New(aid, 0), }, }, { @@ -69,7 +61,7 @@ func TestMerge(t *testing.T) { s1Types: []fcpb.FSMType{fcpb.FSMType_FSM_TYPE_MOVE}, s2Types: nil, actions: []action.Action{ - move.New(newTank(t, eid, id.Tick(0)), status.New(0), nil), + simple.New(aid, 0), }, want: nil, }, @@ -91,7 +83,7 @@ func TestMerge(t *testing.T) { } for _, i := range c.want { - if got := s2.Get(i.Type()).Get(i.ID()); got.ID() != eid { + if got := s2.Get(i.Type()).Get(i.ID()); got.ID() != aid { t.Fatalf("ID() = %v, want = %v", got, eid) } } @@ -100,19 +92,19 @@ func TestMerge(t *testing.T) { } func TestPop(t *testing.T) { - const eid = "entity-id" + aid := id.ActionID("entity-id") s1 := New([]fcpb.FSMType{fcpb.FSMType_FSM_TYPE_MOVE}) - i := move.New(newTank(t, eid, id.Tick(0)), status.New(0), nil) - if err := s1.Add(i); err != nil { + a := simple.New(aid, 0) + if err := s1.Add(a); err != nil { t.Fatalf("Add() = %v, want = nil", err) } s2 := s1.Pop() - if got := s2.Get(fcpb.FSMType_FSM_TYPE_MOVE).Get(eid); got.ID() != eid { - t.Fatalf("ID() = %v, want = %v", got, eid) + if got := s2.Get(fcpb.FSMType_FSM_TYPE_MOVE).Get(aid); got.ID() != aid { + t.Fatalf("ID() = %v, want = %v", got, aid) } - if got := s1.Get(fcpb.FSMType_FSM_TYPE_MOVE).Get(eid); got != nil { + if got := s1.Get(fcpb.FSMType_FSM_TYPE_MOVE).Get(aid); got != nil { t.Errorf("Get() = %v, want = nil", got) } } diff --git a/engine/gamestate/gamestate.go b/engine/gamestate/gamestate.go index 3df71e4..d074702 100644 --- a/engine/gamestate/gamestate.go +++ b/engine/gamestate/gamestate.go @@ -51,10 +51,7 @@ func (s *GameState) Export(tick id.Tick, filter *dirty.List) *gdpb.GameState { for _, e := range filter.Entities() { state.Entities = append( state.GetEntities(), - &gdpb.Entity{ - EntityId: e.ID.Value(), - Type: s.entities.Get(e.ID).Type(), - }, + s.entities.Get(e.ID).Export(), ) } diff --git a/engine/server/executor/BUILD b/engine/server/executor/BUILD index 71de0e4..a998bed 100644 --- a/engine/server/executor/BUILD +++ b/engine/server/executor/BUILD @@ -14,10 +14,8 @@ go_library( "//engine/id:id", "//engine/fsm:action", "//engine/fsm:schedule", - "//engine/fsm/api:constants_go_proto", "//engine/server/client:list", "//engine/visitor:list", - "//engine/visitor/api:constants_go_proto", "@org_golang_google_grpc//codes:go_default_library", "@org_golang_google_grpc//status:go_default_library", ], @@ -29,30 +27,16 @@ go_test( importpath = "github.com/downflux/game/engine/server/executor/executor_test", embed = [":executor"], deps = [ - "//api:api_go_proto", - "//api:constants_go_proto", - "//api:data_go_proto", "//engine/entity:list", "//engine/fsm:schedule", "//engine/fsm/api:constants_go_proto", + "//engine/fsm/mock:simple", "//engine/gamestate:dirty", "//engine/gamestate:gamestate", "//engine/id:id", "//engine/status:status", "//engine/visitor:list", "//engine/visitor:visitor", - "//engine/visitor/api:constants_go_proto", - "//map:map", - "//map/api:constants_go_proto", - "//map/api:data_go_proto", - "//pathing/hpf:graph", - "//server/fsm:move", - "//server/fsm:produce", - "//server/visitor:move", - "//server/visitor:produce", - "//server/entity/component:moveable", - "@com_github_google_go_cmp//cmp:go_default_library", - "@org_golang_google_protobuf//testing/protocmp:go_default_library", - "@org_golang_x_sync//errgroup:go_default_library", + "//engine/visitor/mock:simple", ], ) diff --git a/engine/server/executor/executor.go b/engine/server/executor/executor.go index c3be97d..ab4e910 100644 --- a/engine/server/executor/executor.go +++ b/engine/server/executor/executor.go @@ -15,9 +15,7 @@ import ( apipb "github.com/downflux/game/api/api_go_proto" gdpb "github.com/downflux/game/api/data_go_proto" - fcpb "github.com/downflux/game/engine/fsm/api/constants_go_proto" clientlist "github.com/downflux/game/engine/server/client/list" - vcpb "github.com/downflux/game/engine/visitor/api/constants_go_proto" visitorlist "github.com/downflux/game/engine/visitor/list" ) @@ -30,11 +28,6 @@ const ( var ( notImplemented = status.Error( codes.Unimplemented, "function not implemented") - - fsmVisitorTypeLookup = map[vcpb.VisitorType]fcpb.FSMType{ - vcpb.VisitorType_VISITOR_TYPE_MOVE: fcpb.FSMType_FSM_TYPE_MOVE, - vcpb.VisitorType_VISITOR_TYPE_PRODUCE: fcpb.FSMType_FSM_TYPE_PRODUCE, - } ) // Executor encapsulates logic for executing the core game loop. @@ -57,7 +50,6 @@ type Executor struct { // clients is an append-only set of connected players / AI. clients *clientlist.List - fsmLookup map[vcpb.VisitorType]fcpb.FSMType schedule *schedule.Schedule scheduleCache *schedule.Schedule } @@ -67,7 +59,6 @@ func New( state *gamestate.GameState, dirtystate *dirty.List, fsmSchedule *schedule.Schedule, - fsmLookup map[vcpb.VisitorType]fcpb.FSMType, ) *Executor { return &Executor{ visitors: visitors, @@ -76,7 +67,6 @@ func New( clients: clientlist.New(idLen), schedule: fsmSchedule, scheduleCache: fsmSchedule.Pop(), - fsmLookup: fsmLookup, } } @@ -169,10 +159,8 @@ func (e *Executor) doTick() error { } for _, v := range e.visitors.Iter() { - if fsmType, found := e.fsmLookup[v.Type()]; found { - if err := e.schedule.Get(fsmType).Accept(v); err != nil { - return err - } + if err := e.schedule.Get(v.Type()).Accept(v); err != nil { + return err } } diff --git a/engine/server/executor/executor_test.go b/engine/server/executor/executor_test.go index 0438fb1..9eda4bc 100644 --- a/engine/server/executor/executor_test.go +++ b/engine/server/executor/executor_test.go @@ -1,7 +1,9 @@ +// Package executor tests the game executor. +// +// TODO(minkezhang): Add testing for broadcasting to clients here. package executor import ( - "sync" "testing" "time" @@ -9,342 +11,80 @@ import ( "github.com/downflux/game/engine/gamestate/dirty" "github.com/downflux/game/engine/gamestate/gamestate" "github.com/downflux/game/engine/id/id" + "github.com/downflux/game/engine/visitor/mock/simple" "github.com/downflux/game/engine/visitor/visitor" - "github.com/downflux/game/pathing/hpf/graph" - "github.com/downflux/game/server/entity/component/moveable" - "github.com/downflux/game/server/visitor/move" - "github.com/downflux/game/server/visitor/produce" - "github.com/google/go-cmp/cmp" - "golang.org/x/sync/errgroup" - "google.golang.org/protobuf/testing/protocmp" - apipb "github.com/downflux/game/api/api_go_proto" - gcpb "github.com/downflux/game/api/constants_go_proto" - gdpb "github.com/downflux/game/api/data_go_proto" entitylist "github.com/downflux/game/engine/entity/list" fcpb "github.com/downflux/game/engine/fsm/api/constants_go_proto" + simpleaction "github.com/downflux/game/engine/fsm/mock/simple" serverstatus "github.com/downflux/game/engine/status/status" - vcpb "github.com/downflux/game/engine/visitor/api/constants_go_proto" visitorlist "github.com/downflux/game/engine/visitor/list" - mcpb "github.com/downflux/game/map/api/constants_go_proto" - mdpb "github.com/downflux/game/map/api/data_go_proto" - tile "github.com/downflux/game/map/map" - moveaction "github.com/downflux/game/server/fsm/move" - produceaction "github.com/downflux/game/server/fsm/produce" -) - -const ( - minPathLength = 8 ) var ( - fsmLookup = map[vcpb.VisitorType]fcpb.FSMType{ - vcpb.VisitorType_VISITOR_TYPE_MOVE: fcpb.FSMType_FSM_TYPE_MOVE, - vcpb.VisitorType_VISITOR_TYPE_PRODUCE: fcpb.FSMType_FSM_TYPE_PRODUCE, - } - tickDuration = 100 * time.Millisecond - - /** - * Y = 0 - - - - - * X = 0 - */ - simpleLinearMapProto = &mdpb.TileMap{ - Dimension: &gdpb.Coordinate{X: 4, Y: 1}, - Tiles: []*mdpb.Tile{ - {Coordinate: &gdpb.Coordinate{X: 0, Y: 0}, TerrainType: mcpb.TerrainType_TERRAIN_TYPE_PLAINS}, - {Coordinate: &gdpb.Coordinate{X: 1, Y: 0}, TerrainType: mcpb.TerrainType_TERRAIN_TYPE_PLAINS}, - {Coordinate: &gdpb.Coordinate{X: 2, Y: 0}, TerrainType: mcpb.TerrainType_TERRAIN_TYPE_PLAINS}, - {Coordinate: &gdpb.Coordinate{X: 3, Y: 0}, TerrainType: mcpb.TerrainType_TERRAIN_TYPE_PLAINS}, - }, - } ) -func newExecutor(pb *mdpb.TileMap, d *gdpb.Coordinate) (*Executor, error) { - tm, err := tile.ImportMap(pb) - if err != nil { - return nil, err - } - g, err := graph.BuildGraph(tm, d) - if err != nil { - return nil, err - } - - dirties := dirty.New() - - state := gamestate.New(serverstatus.New(tickDuration), entitylist.New()) - - visitors, err := visitorlist.New([]visitor.Visitor{ - produce.New(state.Status(), state.Entities(), dirties), - move.New(tm, g, state.Status(), dirties, minPathLength), - }) +func newExecutor(t *testing.T) *Executor { + visitors, err := visitorlist.New([]visitor.Visitor{simple.New()}) if err != nil { - return nil, err + t.Fatalf("New() = %v, want = nil", err) } - fsmSchedule := schedule.New([]fcpb.FSMType{ - fcpb.FSMType_FSM_TYPE_MOVE, - fcpb.FSMType_FSM_TYPE_PRODUCE, - }) - - return New(visitors, state, dirties, fsmSchedule, fsmLookup), nil -} - -func TestNewExecutor(t *testing.T) { - _, err := newExecutor(simpleLinearMapProto, &gdpb.Coordinate{X: 2, Y: 1}) - if err != nil { - t.Errorf("newExecutor() = _, %v, want = nil", err) - } -} - -func TestAddEntity(t *testing.T) { - const ( - t0 = float64(0) - nClients = 1 - tankBaseHealth = 100 + return New( + visitors, + gamestate.New( + serverstatus.New(tickDuration), + entitylist.New(), + ), + dirty.New(), + schedule.New([]fcpb.FSMType{fcpb.FSMType_FSM_TYPE_MOVE}), ) - src := &gdpb.Position{X: 0, Y: 0} - - want := &apipb.StreamDataResponse{ - Tick: t0 + 1, - State: &gdpb.GameState{ - Entities: []*gdpb.Entity{{Type: gcpb.EntityType_ENTITY_TYPE_TANK}}, - Curves: []*gdpb.Curve{ - { - Type: gcpb.CurveType_CURVE_TYPE_LINEAR_MOVE, - Property: gcpb.EntityProperty_ENTITY_PROPERTY_POSITION, - Data: []*gdpb.CurveDatum{ - {Datum: &gdpb.CurveDatum_PositionDatum{&gdpb.Position{X: 0, Y: 0}}}, - }, - Tick: t0 + 1, - }, - { - Type: gcpb.CurveType_CURVE_TYPE_TIMER, - Property: gcpb.EntityProperty_ENTITY_PROPERTY_ATTACK_TIMER, - Tick: t0 + 1, - }, - { - Type: gcpb.CurveType_CURVE_TYPE_STEP, - Property: gcpb.EntityProperty_ENTITY_PROPERTY_HEALTH, - Tick: t0 + 1, - Data: []*gdpb.CurveDatum{ - {Datum: &gdpb.CurveDatum_DoubleDatum{tankBaseHealth}}, - }, - }, - }, - }, - } - - e, err := newExecutor(simpleLinearMapProto, &gdpb.Coordinate{X: 2, Y: 1}) - if err != nil { - t.Fatalf("newExecutor() = _, %v, want = nil", err) - } - if err := e.Schedule(produceaction.New( - e.gamestate.Status(), - e.gamestate.Status().Tick(), - gcpb.EntityType_ENTITY_TYPE_TANK, - src, - )); err != nil { - t.Fatalf("Schedule() = %v, want = nil", err) - } - - var cids []id.ClientID - for i := 0; i < nClients; i++ { - cid, err := e.AddClient() - if err != nil { - t.Fatalf("AddClient() = _, %v, want = nil", err) - } - cids = append(cids, cid) - } - - // Connect to server and signal intent to start listening for messages. - for i := 0; i < nClients; i++ { - if err := e.StartClientStream(cids[i]); err != nil { - t.Fatalf("StartClientStream() = %v, want = nil", err) - } - } - - var eg errgroup.Group - - var streamResponsesMux sync.Mutex - var streamResponses []*apipb.StreamDataResponse - for i := 0; i < nClients; i++ { - ch, err := e.ClientChannel(cids[i]) - if err != nil { - t.Fatalf("ClientChannel() = _, %v, want = _, nil", err) - } - // Assuming all clients will receive messages in a timely - // manner. Start listening for messages before the tick starts - // to guarantee we will recieve a message during - // broadcastCurves. - eg.Go(func() error { - m := <-ch - streamResponsesMux.Lock() - defer streamResponsesMux.Unlock() - streamResponses = append(streamResponses, m) - return nil - }) - } - - eg.Go(e.doTick) - if err := eg.Wait(); err != nil { - t.Fatalf("Wait() = %v, want = nil", err) - } - - for _, streamResponse := range streamResponses { - if diff := cmp.Diff( - want, - streamResponse, - protocmp.Transform(), - protocmp.IgnoreFields(&gdpb.CurveDatum{}, "tick"), - protocmp.IgnoreFields(&gdpb.Curve{}, "entity_id"), - protocmp.IgnoreFields(&gdpb.Entity{}, "entity_id"), - protocmp.SortRepeatedFields(&gdpb.GameState{}, "curves"), - ); diff != "" { - t.Errorf("<-e.ClientChannel() mismatch (-want +got):\n%v", diff) - } - } } -func TestDoMove(t *testing.T) { - const ( - t0 = float64(0) - nClients = 1000 - ) - dest := &gdpb.Position{X: 3, Y: 0} - src := &gdpb.Position{X: 0, Y: 0} - - e, err := newExecutor(simpleLinearMapProto, &gdpb.Coordinate{X: 2, Y: 1}) - if err != nil { - t.Fatalf("newExecutor() = _, %v, want = nil", err) - } - - if err := e.Schedule( - produceaction.New( - e.gamestate.Status(), - e.gamestate.Status().Tick(), - gcpb.EntityType_ENTITY_TYPE_TANK, - src, - )); err != nil { - t.Fatalf("Schedule() = %v, want = nil", err) - } - - var eg errgroup.Group - var streamResponsesMux sync.Mutex - var streamResponses []*apipb.StreamDataResponse - var cids []id.ClientID - chs := map[id.ClientID]<-chan *apipb.StreamDataResponse{} - for i := 0; i < nClients; i++ { - // Add client -- emulate AddClient gRPC call. - cid, err := e.AddClient() - if err != nil { - t.Fatalf("AddClient() = _, %v, want = nil", err) - } - cids = append(cids, cid) +func TestSchedule(t *testing.T) { + const priority = 0 + aid := id.ActionID("action-id") - // As in the StreamData gRPC endpoint, first mark the client as - // reachable. - if err := e.StartClientStream(cids[i]); err != nil { - t.Fatalf("StartClientStream() = %v, want = nil", err) - } - - ch, err := e.ClientChannel(cid) - if err != nil { - t.Fatalf("ClientChannel() = _, %v, want = _, nil", err) - } - - chs[cid] = ch + e := newExecutor(t) + if err := e.Schedule(simpleaction.New(aid, priority)); err != nil { + t.Errorf("Schedule() = %v, want = nil", err) } +} - // Listen for the initial tick execution, which will add the scheduled - // entity. - for _, ch := range chs { - ch := ch - eg.Go(func() error { - m := <-ch - - streamResponsesMux.Lock() - defer streamResponsesMux.Unlock() +func TestDoTick(t *testing.T) { + const priority = 0 + aid := id.ActionID("action-id") - streamResponses = append(streamResponses, m) - return nil - }) - } + e := newExecutor(t) - eg.Go(e.doTick) + tick := e.Status().GetTick() - if err := eg.Wait(); err != nil { - t.Fatalf("Wait() = %v, want = nil", err) + // Executor should have added action to the cache. + if err := e.Schedule(simpleaction.New(aid, priority)); err != nil { + t.Fatalf("Schedule() = %v, want = nil", err) } - - if gotLen := len(streamResponses); gotLen != nClients { - t.Fatalf("len() = %v, want = %v", gotLen, nClients) + if a := e.scheduleCache.Get(fcpb.FSMType_FSM_TYPE_MOVE).Get(aid); a == nil { + t.Fatal("Get() = nil, want a non-nil value") } - eid := streamResponses[0].GetState().GetEntities()[0].GetEntityId() - streamResponses = nil - - want := &apipb.StreamDataResponse{ - Tick: t0 + 2, - State: &gdpb.GameState{ - Curves: []*gdpb.Curve{{ - EntityId: eid, - Type: gcpb.CurveType_CURVE_TYPE_LINEAR_MOVE, - Property: gcpb.EntityProperty_ENTITY_PROPERTY_POSITION, - Data: []*gdpb.CurveDatum{ - // First element is the current position of - // the entity. This is necessary for the client - // to do a smooth interpolation. - {Datum: &gdpb.CurveDatum_PositionDatum{&gdpb.Position{X: 0, Y: 0}}}, + mock := e.visitors.Visitor(fcpb.FSMType_FSM_TYPE_MOVE).(*simple.Visitor) + count := mock.Count() - // Following elements relate to the actual tile - // coordinates for the path. - {Datum: &gdpb.CurveDatum_PositionDatum{&gdpb.Position{X: 0, Y: 0}}}, - {Datum: &gdpb.CurveDatum_PositionDatum{&gdpb.Position{X: 1, Y: 0}}}, - {Datum: &gdpb.CurveDatum_PositionDatum{&gdpb.Position{X: 2, Y: 0}}}, - {Datum: &gdpb.CurveDatum_PositionDatum{&gdpb.Position{X: 3, Y: 0}}}, - }, - Tick: t0 + 2, - }, - }}, + e.doTick() + if got := e.Status().GetTick(); got != tick+1 { + t.Fatalf("GetTick() = %v, want = %v", got, tick+1) } - if err := e.Schedule(moveaction.New( - e.gamestate.Entities().Get(id.EntityID(eid)).(moveable.Component), - e.gamestate.Status(), - dest, - )); err != nil { - t.Fatalf("Schedule() = %v, want = nil", err) + if a := e.scheduleCache.Get(fcpb.FSMType_FSM_TYPE_MOVE).Get(aid); a != nil { + t.Fatalf("Get() = %v, want = nil", a) } - - // Listen for the move command broadcast. - for _, ch := range chs { - ch := ch - eg.Go(func() error { - m := <-ch - - streamResponsesMux.Lock() - defer streamResponsesMux.Unlock() - - streamResponses = append(streamResponses, m) - return nil - }) - } - - eg.Go(e.doTick) - - if err := eg.Wait(); err != nil { - t.Fatalf("Wait() = %v, want = nil", err) + if a := e.schedule.Get(fcpb.FSMType_FSM_TYPE_MOVE).Get(aid); a == nil { + t.Fatal("Get() = nil, want a non-nil value") } - for _, streamResponse := range streamResponses { - if diff := cmp.Diff( - want, - streamResponse, - protocmp.Transform(), - protocmp.IgnoreFields(&gdpb.CurveDatum{}, "tick"), - ); diff != "" { - t.Errorf("<-e.ClientChannel() mismatch (-want +got):\n%v", diff) - } + // TODO(minkezhang): Change to 1 when we remove Visit(List). + if get := mock.Count(); get != count+1 { + t.Errorf("Count() = %v, want = %v", get, count+1) } } diff --git a/engine/visitor/BUILD b/engine/visitor/BUILD index acf3d99..e7c98fb 100644 --- a/engine/visitor/BUILD +++ b/engine/visitor/BUILD @@ -8,7 +8,7 @@ go_library( importpath = "github.com/downflux/game/engine/visitor/list", deps = [ ":visitor", - "//engine/visitor/api:constants_go_proto", + "//engine/fsm/api:constants_go_proto", "@org_golang_google_grpc//codes:go_default_library", "@org_golang_google_grpc//status:go_default_library", ], @@ -19,6 +19,6 @@ go_library( srcs = ["visitor.go"], importpath = "github.com/downflux/game/engine/visitor/visitor", deps = [ - "//engine/visitor/api:constants_go_proto", + "//engine/fsm/api:constants_go_proto", ], ) diff --git a/engine/visitor/api/BUILD b/engine/visitor/api/BUILD deleted file mode 100644 index 19cf203..0000000 --- a/engine/visitor/api/BUILD +++ /dev/null @@ -1,15 +0,0 @@ -load("@rules_proto//proto:defs.bzl", "proto_library") -load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library", "go_grpc_library") - -package(default_visibility=["//visibility:public"]) - -proto_library( - name = "constants_proto", - srcs = ["constants.proto"], -) - -go_proto_library( - name = "constants_go_proto", - importpath = "github.com/downflux/game/engine/visitor/api/constants_go_proto", - proto = ":constants_proto", -) diff --git a/engine/visitor/api/constants.proto b/engine/visitor/api/constants.proto deleted file mode 100644 index b7e84ed..0000000 --- a/engine/visitor/api/constants.proto +++ /dev/null @@ -1,20 +0,0 @@ -syntax = "proto3"; - -package game.engine.service.visitor.api.constants; -option go_package = "game.server.engine.visitor.api.constants"; -option csharp_namespace = "DF.Game.Engine.Service.Visitor.API.Constants"; - -enum AgentType { - AGENT_TYPE_UNKNOWN = 0; - - AGENT_TYPE_FSM = 1; - AGENT_TYPE_FSM_LIST = 2; -} - -enum VisitorType { - VISITOR_TYPE_UNKNOWN = 0; - VISITOR_TYPE_MOVE = 1; - VISITOR_TYPE_PRODUCE = 2; - VISITOR_TYPE_CHASE = 3; - VISITOR_TYPE_ATTACK = 4; -} diff --git a/engine/visitor/list.go b/engine/visitor/list.go index 7878647..e575a38 100644 --- a/engine/visitor/list.go +++ b/engine/visitor/list.go @@ -7,13 +7,13 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - vcpb "github.com/downflux/game/engine/visitor/api/constants_go_proto" + fcpb "github.com/downflux/game/engine/fsm/api/constants_go_proto" ) // List implements a managed list of Visitor instances. type List struct { - visitors map[vcpb.VisitorType]visitor.Visitor - order []vcpb.VisitorType + visitors map[fcpb.FSMType]visitor.Visitor + order []fcpb.FSMType } // New creates a new instance of the List object. @@ -30,7 +30,7 @@ func New(visitors []visitor.Visitor) (*List, error) { } // Get returns a concrete Visitor instance given the registered VisitorType. -func (l *List) Visitor(visitorType vcpb.VisitorType) visitor.Visitor { +func (l *List) Visitor(visitorType fcpb.FSMType) visitor.Visitor { return l.visitors[visitorType] } @@ -48,7 +48,7 @@ func (l *List) Iter() []visitor.Visitor { // appendVisitor registers a new Visitor instance into the managed List. func (l *List) appendVisitor(v visitor.Visitor) error { if l.visitors == nil { - l.visitors = map[vcpb.VisitorType]visitor.Visitor{} + l.visitors = map[fcpb.FSMType]visitor.Visitor{} } if _, found := l.visitors[v.Type()]; found { diff --git a/engine/visitor/mock/BUILD b/engine/visitor/mock/BUILD new file mode 100644 index 0000000..409cc02 --- /dev/null +++ b/engine/visitor/mock/BUILD @@ -0,0 +1,23 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +package(default_visibility=["//visibility:public"]) + +go_library( + name = "simple", + srcs = ["simple.go"], + importpath = "github.com/downflux/game/engine/visitor/mock/simple", + deps = [ + "//engine/fsm/api:constants_go_proto", + "//engine/visitor:visitor", + ], +) + +go_test( + name = "simple_test", + srcs = [":simple_test.go"], + importpath = "github.com/downflux/game/engine/visitor/mock/simple_test", + embed = [":simple"], + deps = [ + "//engine/visitor:visitor", + ], +) diff --git a/engine/visitor/mock/simple.go b/engine/visitor/mock/simple.go new file mode 100644 index 0000000..73e5863 --- /dev/null +++ b/engine/visitor/mock/simple.go @@ -0,0 +1,26 @@ +package simple + +import ( + "github.com/downflux/game/engine/visitor/visitor" + + fcpb "github.com/downflux/game/engine/fsm/api/constants_go_proto" +) + +type Visitor struct { + *visitor.Base + + counter int +} + +func New() *Visitor { + return &Visitor{ + Base: visitor.New(fcpb.FSMType_FSM_TYPE_MOVE), + } +} + +func (v *Visitor) Visit(a visitor.Agent) error { + v.counter += 1 + return nil +} + +func (v *Visitor) Count() int { return v.counter } diff --git a/engine/visitor/mock/simple_test.go b/engine/visitor/mock/simple_test.go new file mode 100644 index 0000000..36a0177 --- /dev/null +++ b/engine/visitor/mock/simple_test.go @@ -0,0 +1,9 @@ +package simple + +import ( + "github.com/downflux/game/engine/visitor/visitor" +) + +var ( + _ visitor.Visitor = &Visitor{} +) diff --git a/engine/visitor/visitor.go b/engine/visitor/visitor.go index 95d27cb..d0a3708 100644 --- a/engine/visitor/visitor.go +++ b/engine/visitor/visitor.go @@ -1,10 +1,12 @@ // Package visitor defines interfaces necessary for the visitor design pattern. // // See https://en.wikipedia.org/wiki/Visitor_pattern for more information. +// +// TODO(minkezhang): Refactor with generics (e.g. Visitor[Agent]). package visitor import ( - vcpb "github.com/downflux/game/engine/visitor/api/constants_go_proto" + fcpb "github.com/downflux/game/engine/fsm/api/constants_go_proto" ) type Agent interface { @@ -13,15 +15,13 @@ type Agent interface { // Example: // func (a *ConcreteAgent) Accept(v Vistor) { return v.Visit(a) } Accept(v Visitor) error - - AgentType() vcpb.AgentType } // Visitor defines the list of functions necessary for a process regularly // mutating arbitrary Entity instances. type Visitor interface { - // Type returns a registered VisitorType. - Type() vcpb.VisitorType + // Type returns a registered FSMType. + Type() fcpb.FSMType // Visit will run appropriate commands for the current tick. If // a timeout occurs, the function will return early. This function @@ -35,18 +35,9 @@ type Visitor interface { Visit(a Agent) error } -type BaseAgent struct { - agentType vcpb.AgentType +type Base struct { + fsmType fcpb.FSMType } -func NewBaseAgent(t vcpb.AgentType) *BaseAgent { return &BaseAgent{agentType: t} } - -func (a BaseAgent) AgentType() vcpb.AgentType { return a.agentType } - -type BaseVisitor struct { - visitorType vcpb.VisitorType -} - -func NewBaseVisitor(t vcpb.VisitorType) *BaseVisitor { return &BaseVisitor{visitorType: t} } - -func (v BaseVisitor) Type() vcpb.VisitorType { return v.visitorType } +func New(t fcpb.FSMType) *Base { return &Base{fsmType: t} } +func (v Base) Type() fcpb.FSMType { return v.fsmType } diff --git a/server/entity/BUILD b/server/entity/BUILD index 8aab04f..d2606a5 100644 --- a/server/entity/BUILD +++ b/server/entity/BUILD @@ -1,12 +1,8 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility=[ - # This is only true for intermediate testing. - # TODO(minkezhang): Remove visibility. - "//engine/fsm:__pkg__", - "//server/grpc:__pkg__", "//server/fsm:__pkg__", - + "//server/grpc:__pkg__", "//server/service:__pkg__", "//server/visitor:__pkg__", ]) diff --git a/server/entity/component/BUILD b/server/entity/component/BUILD index db2770f..4c8e8cd 100644 --- a/server/entity/component/BUILD +++ b/server/entity/component/BUILD @@ -1,10 +1,6 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") -package(default_visibility=[ - "//engine:__subpackages__", # Test-only. - - "//server:__subpackages__", -]) +package(default_visibility=["//server:__subpackages__"]) go_library( name = "moveable", @@ -23,6 +19,7 @@ go_library( deps = [ ":positionable", "//api:data_go_proto", + "//engine/curve/common:step", "//engine/curve/common:timer", "//engine/id:id", ], diff --git a/server/entity/component/attackable.go b/server/entity/component/attackable.go index 3283bd2..e60e757 100644 --- a/server/entity/component/attackable.go +++ b/server/entity/component/attackable.go @@ -1,6 +1,12 @@ +// Package attackable impart a primary attack function to the entity. +// +// An attack may have an optional travel time. Of attacks with a travel time, +// the attack may hit a stationary position or chase a target within some attack +// range. package attackable import ( + "github.com/downflux/game/engine/curve/common/step" "github.com/downflux/game/engine/curve/common/timer" "github.com/downflux/game/engine/id/id" "github.com/downflux/game/server/entity/component/positionable" @@ -10,25 +16,40 @@ type Component interface { positionable.Component ID() id.EntityID - Strength() float64 - Range() float64 + AttackStrength() float64 + + // AttackRange specifies the distance at which an attacker may start + // attacking the target. + AttackRange() float64 + + // AttackVelocity expresses the speed of the projectile. A velocity may + // be of speed positive infinity, representing a hitscan weapon. + AttackVelocity() float64 + + AttackTargetCurve() *step.Curve AttackTimerCurve() *timer.Curve } type Base struct { strength float64 attackRange float64 + velocity float64 + targetCurve *step.Curve attackTimer *timer.Curve } -func New(s float64, r float64, c *timer.Curve) *Base { +func New(s float64, r float64, v float64, t *step.Curve, c *timer.Curve) *Base { return &Base{ strength: s, attackRange: r, + velocity: v, + targetCurve: t, attackTimer: c, } } -func (c Base) Strength() float64 { return c.strength } -func (c Base) Range() float64 { return c.attackRange } +func (c Base) AttackStrength() float64 { return c.strength } +func (c Base) AttackRange() float64 { return c.attackRange } +func (c Base) AttackVelocity() float64 { return c.velocity } func (c Base) AttackTimerCurve() *timer.Curve { return c.attackTimer } +func (c Base) AttackTargetCurve() *step.Curve { return c.targetCurve } diff --git a/server/entity/component/moveable.go b/server/entity/component/moveable.go index 61576e7..940d123 100644 --- a/server/entity/component/moveable.go +++ b/server/entity/component/moveable.go @@ -9,7 +9,7 @@ type Component interface { positionable.Component ID() id.EntityID - Velocity() float64 + MoveVelocity() float64 } type Base struct { @@ -22,4 +22,4 @@ func New(v float64) *Base { } } -func (c Base) Velocity() float64 { return c.velocity } +func (c Base) MoveVelocity() float64 { return c.velocity } diff --git a/server/entity/component/targetable.go b/server/entity/component/targetable.go index dfa14d8..f13de70 100644 --- a/server/entity/component/targetable.go +++ b/server/entity/component/targetable.go @@ -10,8 +10,8 @@ type Component interface { positionable.Component ID() id.EntityID - Health(t id.Tick) float64 - HealthCurve() *delta.Curve + TargetHealth(t id.Tick) float64 + TargetHealthCurve() *delta.Curve } type Base struct { @@ -24,5 +24,5 @@ func New(hp *delta.Curve) *Base { } } -func (c *Base) Health(t id.Tick) float64 { return c.health.Get(t).(float64) } -func (c *Base) HealthCurve() *delta.Curve { return c.health } +func (c *Base) TargetHealth(t id.Tick) float64 { return c.health.Get(t).(float64) } +func (c *Base) TargetHealthCurve() *delta.Curve { return c.health } diff --git a/server/entity/tank.go b/server/entity/tank.go index d573a00..4c6b8b4 100644 --- a/server/entity/tank.go +++ b/server/entity/tank.go @@ -22,8 +22,11 @@ import ( ) const ( - // velocity is measured in tiles per second. - velocity = 2 + // moveVelocity is measured in tiles per second. + moveVelocity = 2 + + // attackVelocity is measured in tiles per second. + attackVelocity = 10 // cooloff is measured in ticks. // TODO(minkezhang): Refactor to be in terms of seconds instead. @@ -43,6 +46,7 @@ type positionComponent = positionable.Base // Entity implements the entity.Entity interface and represents a simple armored // unit. type Entity struct { + entity.Base entity.LifeCycle moveComponent attackComponent @@ -57,34 +61,40 @@ type Entity struct { } // New constructs a new instance of the Tank. -func New(eid id.EntityID, t id.Tick, p *gdpb.Position) (*Entity, error) { +func New(eid id.EntityID, t id.Tick, pos *gdpb.Position, cid id.ClientID) (*Entity, error) { mc := linearmove.New(eid, t) - mc.Add(t, p) + mc.Add(t, pos) ac := timer.New(eid, t, cooloff, gcpb.EntityProperty_ENTITY_PROPERTY_ATTACK_TIMER) + tc := step.New(eid, t, gcpb.EntityProperty_ENTITY_PROPERTY_ATTACK_TARGET, reflect.TypeOf(id.ClientID(""))) + + cidc := step.New( + eid, + t, + gcpb.EntityProperty_ENTITY_PROPERTY_CLIENT_ID, + reflect.TypeOf(id.ClientID("")), + ) + cidc.Add(t, cid) + hp := delta.New(step.New(eid, t, gcpb.EntityProperty_ENTITY_PROPERTY_HEALTH, reflect.TypeOf(float64(0)))) if err := hp.Add(t, health); err != nil { return nil, err } - curves, err := list.New([]curve.Curve{mc, ac, hp}) + curves, err := list.New([]curve.Curve{mc, ac, hp, cidc}) if err != nil { return nil, err } return &Entity{ - moveComponent: *moveable.New(velocity), - attackComponent: *attackable.New(strength, attackRange, ac), + Base: *entity.New( + gcpb.EntityType_ENTITY_TYPE_TANK, eid, cidc), + + moveComponent: *moveable.New(moveVelocity), + attackComponent: *attackable.New(strength, attackRange, attackVelocity, tc, ac), targetComponent: *targetable.New(hp), positionComponent: *positionable.New(mc), - eid: eid, curves: curves, }, nil } -// ID returns the UUID of the Tank. -func (e *Entity) ID() id.EntityID { return e.eid } - func (e *Entity) Curves() *list.List { return e.curves } - -// Type returns the registered EntityType. -func (e *Entity) Type() gcpb.EntityType { return gcpb.EntityType_ENTITY_TYPE_TANK } diff --git a/server/fsm/BUILD b/server/fsm/BUILD index 5703a4e..6c8c8ab 100644 --- a/server/fsm/BUILD +++ b/server/fsm/BUILD @@ -1,7 +1,6 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_visibility=[ - "//engine:__subpackages__", # test-only "//server:__subpackages__", ]) diff --git a/server/fsm/attack.go b/server/fsm/attack.go index 565060a..83ba9e4 100644 --- a/server/fsm/attack.go +++ b/server/fsm/attack.go @@ -89,16 +89,17 @@ func (a *Action) State() (fsm.State, error) { return commonstate.Unknown, err } + // TODO(minkezhang): Account for AttackVelocity and AttackTarget here. switch s { case commonstate.Pending: tick := a.status.Tick() - if a.target.Health(tick) <= 0 { + if a.target.TargetHealth(tick) <= 0 { return commonstate.Finished, a.To(s, commonstate.Finished, true) } if a.source.AttackTimerCurve().Ok(tick) && utils.Euclidean( a.source.Position(tick), a.target.Position(tick), - ) <= a.source.Range() { + ) <= a.source.AttackRange() { return commonstate.Executing, a.To(s, commonstate.Executing, true) } return s, nil diff --git a/server/fsm/attack_test.go b/server/fsm/attack_test.go index e876d60..be3e9e1 100644 --- a/server/fsm/attack_test.go +++ b/server/fsm/attack_test.go @@ -19,7 +19,8 @@ var ( ) func newTank(t *testing.T, eid id.EntityID, tick id.Tick, p *gdpb.Position) *tank.Entity { - tankEntity, err := tank.New(eid, tick, p) + cid := id.ClientID("client-id") + tankEntity, err := tank.New(eid, tick, p, cid) if err != nil { t.Fatalf("New() = %v, want = nil", err) } @@ -45,7 +46,7 @@ func TestState(t *testing.T) { newTank(t, "source", 0, &gdpb.Position{X: 0, Y: 0}), newTank(t, "target", 0, &gdpb.Position{X: 0, Y: 1}), ) - if err := targetDeadAction.target.HealthCurve().Add(0, -1*targetDeadAction.target.Health(0)); err != nil { + if err := targetDeadAction.target.TargetHealthCurve().Add(0, -1*targetDeadAction.target.TargetHealth(0)); err != nil { t.Fatalf("Add() = %v, want = nil", err) } @@ -60,7 +61,7 @@ func TestState(t *testing.T) { targetOutOfRangeSource := newTank(t, "source", 0, &gdpb.Position{X: 0, Y: 0}) targetOutOfRange := newAction( targetOutOfRangeSource, - newTank(t, "target", 0, &gdpb.Position{X: 0, Y: targetOutOfRangeSource.Range() + 1}), + newTank(t, "target", 0, &gdpb.Position{X: 0, Y: targetOutOfRangeSource.AttackRange() + 1}), ) attackCanceled := newAction( diff --git a/server/fsm/chase_test.go b/server/fsm/chase_test.go index 51d0ed0..b8de68e 100644 --- a/server/fsm/chase_test.go +++ b/server/fsm/chase_test.go @@ -18,7 +18,8 @@ var ( ) func newTank(t *testing.T, eid id.EntityID, tick id.Tick, p *gdpb.Position) *tank.Entity { - tankEntity, err := tank.New(eid, tick, p) + cid := id.ClientID("client-id") + tankEntity, err := tank.New(eid, tick, p, cid) if err != nil { t.Fatalf("New() = %v, want = nil", err) } diff --git a/server/fsm/move_test.go b/server/fsm/move_test.go index d6314b3..bed6266 100644 --- a/server/fsm/move_test.go +++ b/server/fsm/move_test.go @@ -18,7 +18,8 @@ var ( ) func newTank(t *testing.T, eid id.EntityID, tick id.Tick, p *gdpb.Position) *tank.Entity { - tankEntity, err := tank.New(eid, tick, p) + cid := id.ClientID("client-id") + tankEntity, err := tank.New(eid, tick, p, cid) if err != nil { t.Fatalf("New() = %v, want = nil", err) } diff --git a/server/fsm/produce.go b/server/fsm/produce.go index b178c12..b7f2bb0 100644 --- a/server/fsm/produce.go +++ b/server/fsm/produce.go @@ -35,14 +35,16 @@ type Action struct { executionTick id.Tick // Read-only. status status.ReadOnlyStatus // Read-only. entityType gcpb.EntityType // Read-only. - spawnPosition *gdpb.Position // read-only. + spawnPosition *gdpb.Position // Read-only. + spawnClientID id.ClientID // Read-only. } func New( dfStatus status.ReadOnlyStatus, executionTick id.Tick, entityType gcpb.EntityType, - spawnPosition *gdpb.Position) *Action { + spawnPosition *gdpb.Position, + spawnClientID id.ClientID) *Action { return &Action{ Base: action.New(FSM, commonstate.Pending), id: id.ActionID(id.RandomString(idLength)), @@ -50,6 +52,7 @@ func New( status: dfStatus, entityType: entityType, spawnPosition: spawnPosition, + spawnClientID: spawnClientID, } } @@ -57,6 +60,7 @@ func (n *Action) EntityType() gcpb.EntityType { return n.entityType } func (n *Action) Accept(v visitor.Visitor) error { return v.Visit(n) } func (n *Action) ID() id.ActionID { return n.id } func (n *Action) SpawnPosition() *gdpb.Position { return n.spawnPosition } +func (n *Action) SpawnClientID() id.ClientID { return n.spawnClientID } func (n *Action) Precedence(i action.Action) bool { if i.Type() != fsmType { diff --git a/server/fsm/produce_test.go b/server/fsm/produce_test.go index 05ba3e4..11c6c91 100644 --- a/server/fsm/produce_test.go +++ b/server/fsm/produce_test.go @@ -5,6 +5,7 @@ import ( "github.com/downflux/game/engine/fsm/action" "github.com/downflux/game/engine/fsm/fsm" + "github.com/downflux/game/engine/id/id" "github.com/downflux/game/engine/status/status" "github.com/downflux/game/server/fsm/commonstate" @@ -18,6 +19,7 @@ var ( func TestConstructor(t *testing.T) { s := status.New(0) + cid := id.ClientID("client-id") testConfigs := []struct { name string @@ -26,12 +28,12 @@ func TestConstructor(t *testing.T) { }{ { name: "NewPending", - i: New(s, s.Tick()+1, gcpb.EntityType_ENTITY_TYPE_TANK, &gdpb.Position{X: 0, Y: 0}), + i: New(s, s.Tick()+1, gcpb.EntityType_ENTITY_TYPE_TANK, &gdpb.Position{X: 0, Y: 0}, cid), want: commonstate.Pending, }, { name: "NewExecuting", - i: New(s, s.Tick(), gcpb.EntityType_ENTITY_TYPE_TANK, &gdpb.Position{X: 0, Y: 0}), + i: New(s, s.Tick(), gcpb.EntityType_ENTITY_TYPE_TANK, &gdpb.Position{X: 0, Y: 0}, cid), want: commonstate.Executing, }, } @@ -47,7 +49,9 @@ func TestConstructor(t *testing.T) { func TestFinish(t *testing.T) { s := status.New(0) - i := New(s, s.Tick(), gcpb.EntityType_ENTITY_TYPE_TANK, &gdpb.Position{X: 0, Y: 0}) + cid := id.ClientID("client-id") + + i := New(s, s.Tick(), gcpb.EntityType_ENTITY_TYPE_TANK, &gdpb.Position{X: 0, Y: 0}, cid) if err := i.Finish(); err != nil { t.Fatalf("Finish() = %v, want = nil", err) @@ -56,7 +60,9 @@ func TestFinish(t *testing.T) { func TestCancel(t *testing.T) { s := status.New(0) - i := New(s, s.Tick()+1, gcpb.EntityType_ENTITY_TYPE_TANK, &gdpb.Position{X: 0, Y: 0}) + cid := id.ClientID("client-id") + + i := New(s, s.Tick()+1, gcpb.EntityType_ENTITY_TYPE_TANK, &gdpb.Position{X: 0, Y: 0}, cid) if err := i.Cancel(); err != nil { t.Fatalf("Cancel() = %v, want = nil", err) diff --git a/server/grpc/BUILD b/server/grpc/BUILD index bd8c761..430f201 100644 --- a/server/grpc/BUILD +++ b/server/grpc/BUILD @@ -124,7 +124,6 @@ go_library( "//engine/status:status", "//engine/visitor:list", "//engine/visitor:visitor", - "//engine/visitor/api:constants_go_proto", "//map:map", "//map/api:data_go_proto", "//pathing/hpf:graph", diff --git a/server/grpc/executorutils.go b/server/grpc/executorutils.go index 43f0812..72db342 100644 --- a/server/grpc/executorutils.go +++ b/server/grpc/executorutils.go @@ -26,7 +26,6 @@ import ( entitylist "github.com/downflux/game/engine/entity/list" fcpb "github.com/downflux/game/engine/fsm/api/constants_go_proto" serverstatus "github.com/downflux/game/engine/status/status" - vcpb "github.com/downflux/game/engine/visitor/api/constants_go_proto" visitorlist "github.com/downflux/game/engine/visitor/list" mdpb "github.com/downflux/game/map/api/data_go_proto" tile "github.com/downflux/game/map/map" @@ -75,18 +74,12 @@ func New(pb *mdpb.TileMap, d *gdpb.Coordinate, tickDuration time.Duration, minPa } return &Utils{ - executor: executor.New(visitors, state, dirtystate, fsmSchedule, map[vcpb.VisitorType]fcpb.FSMType{ - vcpb.VisitorType_VISITOR_TYPE_CHASE: fcpb.FSMType_FSM_TYPE_CHASE, - vcpb.VisitorType_VISITOR_TYPE_MOVE: fcpb.FSMType_FSM_TYPE_MOVE, - vcpb.VisitorType_VISITOR_TYPE_PRODUCE: fcpb.FSMType_FSM_TYPE_PRODUCE, - vcpb.VisitorType_VISITOR_TYPE_ATTACK: fcpb.FSMType_FSM_TYPE_ATTACK, - }), + executor: executor.New(visitors, state, dirtystate, fsmSchedule), gamestate: state, }, nil } -func (u *Utils) Executor() *executor.Executor { return u.executor } - +func (u *Utils) Executor() *executor.Executor { return u.executor } func (u *Utils) Status() serverstatus.ReadOnlyStatus { return u.gamestate.Status() } // Move transforms the player MoveRequest input into a list of move actions @@ -94,15 +87,15 @@ func (u *Utils) Status() serverstatus.ReadOnlyStatus { return u.gamestate.Status func (u *Utils) Move(pb *apipb.MoveRequest) error { // TODO(minkezhang): If tick outside window, return error. + // TODO(minkezhang): Return list of errors instead. for _, eid := range pb.GetEntityIds() { - e, ok := u.gamestate.Entities().Get(id.EntityID(eid)).(moveable.Component) + m, ok := u.gamestate.Entities().Get(id.EntityID(eid)).(moveable.Component) if !ok { return status.Error(codes.FailedPrecondition, "specified entity is not moveable") } if err := u.executor.Schedule( - moveaction.New(e, u.Status(), pb.GetDestination()), - ); err != nil { + moveaction.New(m, u.Status(), pb.GetDestination())); err != nil { return err } } @@ -116,13 +109,14 @@ func (u *Utils) Attack(pb *apipb.AttackRequest) error { return status.Error(codes.FailedPrecondition, "specified entity is not targetable") } + // TODO(minkezhang): Return list of errors instead. for _, eid := range pb.GetEntityIds() { - a, ok := u.gamestate.Entities().Get(id.EntityID(eid)).(attackable.Component) + e := u.gamestate.Entities().Get(id.EntityID(eid)) + a, ok := e.(attackable.Component) if !ok { return status.Error(codes.FailedPrecondition, "specified entity is not attackable") } - - m, ok := u.gamestate.Entities().Get(id.EntityID(eid)).(moveable.Component) + m, ok := e.(moveable.Component) if !ok { return status.Error(codes.FailedPrecondition, "specified entity is not moveable") } @@ -142,5 +136,13 @@ func (u *Utils) Attack(pb *apipb.AttackRequest) error { // ProduceDebug schedules adding a new entity in the next game tick. func (u *Utils) ProduceDebug(entityType gcpb.EntityType, spawnPosition *gdpb.Position) error { - return u.executor.Schedule(produceaction.New(u.Status(), u.Status().Tick(), entityType, spawnPosition)) + // TODO(minkezhang): Use arbitrary client-id after implementing + // per-instance ACLs and setting to PublicWritable here. + return u.executor.Schedule( + produceaction.New( + u.Status(), + u.Status().Tick(), + entityType, + spawnPosition, + id.ClientID(""))) } diff --git a/server/grpc/server.go b/server/grpc/server.go index 8e51094..aba1ede 100644 --- a/server/grpc/server.go +++ b/server/grpc/server.go @@ -132,7 +132,9 @@ func (s *DownFluxServer) AddClient(ctx context.Context, req *apipb.AddClientRequ } resp := &apipb.AddClientResponse{ - ClientId: cid.Value(), + ClientId: &gdpb.ClientID{ + ClientId: cid.Value(), + }, } return resp, nil } diff --git a/server/grpc/server_network_test.go b/server/grpc/server_network_test.go index f6d5cce..8c5d15d 100644 --- a/server/grpc/server_network_test.go +++ b/server/grpc/server_network_test.go @@ -176,7 +176,7 @@ func TestServerCloseStream(t *testing.T) { } stream, err := client.StreamData(context.Background(), &apipb.StreamDataRequest{ - ClientId: clientResp.GetClientId(), + ClientId: clientResp.GetClientId().GetClientId(), }) if err != nil { t.Fatalf("StreamData() = _, %v, want = nil", err) diff --git a/server/grpc/server_test.go b/server/grpc/server_test.go index 772169c..458ae27 100644 --- a/server/grpc/server_test.go +++ b/server/grpc/server_test.go @@ -117,7 +117,7 @@ func TestSendMoveCommand(t *testing.T) { if err != nil { t.Fatalf("AddPlayer() = _, %v, want = nil", err) } - cid := resp.GetClientId() + cid := resp.GetClientId().GetClientId() stream, err := client.StreamData(s.ctx, &apipb.StreamDataRequest{ ClientId: cid, }) @@ -249,7 +249,7 @@ func TestAddClient(t *testing.T) { t.Fatalf("AddPlayer() = _, %v, want = nil", err) } - if resp.GetClientId() == "" { + if resp.GetClientId().GetClientId() == "" { t.Fatalf("GetClientId() = %v, want a non-empty value", err) } diff --git a/server/visitor/BUILD b/server/visitor/BUILD index 09fd4a5..96ef1ff 100644 --- a/server/visitor/BUILD +++ b/server/visitor/BUILD @@ -1,9 +1,6 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") -package(default_visibility=[ - "//server:__subpackages__", - "//engine:__subpackages__", # Test-only -]) +package(default_visibility=["//server:__subpackages__"]) go_library( name = "produce", @@ -13,11 +10,11 @@ go_library( "//api:constants_go_proto", "//engine/entity:entity", "//engine/entity:list", + "//engine/fsm/api:constants_go_proto", "//engine/gamestate:dirty", "//engine/id:id", "//engine/status:status", "//engine/visitor:visitor", - "//engine/visitor/api:constants_go_proto", "//server/entity:tank", "//server/fsm:commonstate", "//server/fsm:produce", @@ -67,10 +64,10 @@ go_library( "//api:data_go_proto", "//engine/curve/common:linearmove", "//engine/entity:entity", + "//engine/fsm/api:constants_go_proto", "//engine/gamestate:dirty", "//engine/status:status", "//engine/visitor:visitor", - "//engine/visitor/api:constants_go_proto", "//map:map", "//map:utils", "//pathing/hpf:astar", @@ -88,9 +85,9 @@ go_library( deps = [ "//engine/status:status", "//engine/visitor:visitor", - "//engine/visitor/api:constants_go_proto", "//engine/fsm:schedule", "//server/fsm:chase", + "//engine/fsm/api:constants_go_proto", ], ) @@ -122,8 +119,8 @@ go_library( "//engine/gamestate:dirty", "//engine/status:status", "//engine/visitor:visitor", - "//engine/visitor/api:constants_go_proto", "//server/fsm:attack", "//server/fsm:commonstate", + "//engine/fsm/api:constants_go_proto", ], ) diff --git a/server/visitor/attack.go b/server/visitor/attack.go index 0361f68..471ca63 100644 --- a/server/visitor/attack.go +++ b/server/visitor/attack.go @@ -7,15 +7,15 @@ import ( "github.com/downflux/game/server/fsm/attack" "github.com/downflux/game/server/fsm/commonstate" - vcpb "github.com/downflux/game/engine/visitor/api/constants_go_proto" + fcpb "github.com/downflux/game/engine/fsm/api/constants_go_proto" ) const ( - visitorType = vcpb.VisitorType_VISITOR_TYPE_ATTACK + fsmType = fcpb.FSMType_FSM_TYPE_ATTACK ) type Visitor struct { - visitor.BaseVisitor + visitor.Base status status.ReadOnlyStatus dirty *dirty.List @@ -23,9 +23,9 @@ type Visitor struct { func New(dfStatus status.ReadOnlyStatus, dirties *dirty.List) *Visitor { return &Visitor{ - BaseVisitor: *visitor.NewBaseVisitor(visitorType), - status: dfStatus, - dirty: dirties, + Base: *visitor.New(fsmType), + status: dfStatus, + dirty: dirties, } } @@ -42,7 +42,7 @@ func (v *Visitor) visitFSM(node *attack.Action) error { // recording targets, ENTITY_PROPERTY_ATTACK_TARGET. dirtyCurves := []dirty.Curve{ {node.Source().ID(), node.Source().AttackTimerCurve().Property()}, - {node.Target().ID(), node.Target().HealthCurve().Property()}, + {node.Target().ID(), node.Target().TargetHealthCurve().Property()}, } for _, c := range dirtyCurves { if err := v.dirty.AddCurve(c); err != nil { @@ -53,7 +53,7 @@ func (v *Visitor) visitFSM(node *attack.Action) error { if err := node.Source().AttackTimerCurve().Add(tick, true); err != nil { return err } - return node.Target().HealthCurve().Add(tick, -1*node.Source().Strength()) + return node.Target().TargetHealthCurve().Add(tick, -1*node.Source().AttackStrength()) } return nil } diff --git a/server/visitor/chase.go b/server/visitor/chase.go index d9866d2..352335e 100644 --- a/server/visitor/chase.go +++ b/server/visitor/chase.go @@ -6,15 +6,15 @@ import ( "github.com/downflux/game/engine/visitor/visitor" "github.com/downflux/game/server/fsm/chase" - vcpb "github.com/downflux/game/engine/visitor/api/constants_go_proto" + fcpb "github.com/downflux/game/engine/fsm/api/constants_go_proto" ) const ( - visitorType = vcpb.VisitorType_VISITOR_TYPE_CHASE + fsmType = fcpb.FSMType_FSM_TYPE_CHASE ) type Visitor struct { - visitor.BaseVisitor + visitor.Base schedule *schedule.Schedule status status.ReadOnlyStatus @@ -22,9 +22,9 @@ type Visitor struct { func New(dfStatus status.ReadOnlyStatus, schedule *schedule.Schedule) *Visitor { return &Visitor{ - BaseVisitor: *visitor.NewBaseVisitor(visitorType), - schedule: schedule, - status: dfStatus, + Base: *visitor.New(fsmType), + schedule: schedule, + status: dfStatus, } } diff --git a/server/visitor/move.go b/server/visitor/move.go index a521048..b30ac44 100644 --- a/server/visitor/move.go +++ b/server/visitor/move.go @@ -16,13 +16,13 @@ import ( "github.com/downflux/game/server/fsm/move" gdpb "github.com/downflux/game/api/data_go_proto" - vcpb "github.com/downflux/game/engine/visitor/api/constants_go_proto" + fcpb "github.com/downflux/game/engine/fsm/api/constants_go_proto" tile "github.com/downflux/game/map/map" ) const ( - // visitorType is the registered VisitorType of the move visitor. - visitorType = vcpb.VisitorType_VISITOR_TYPE_MOVE + // fsmType is the registered FSMType of the move visitor. + fsmType = fcpb.FSMType_FSM_TYPE_MOVE ) // coordinate transforms a gdpb.Position instance into a gdpb.Coordinate @@ -45,7 +45,7 @@ func position(c *gdpb.Coordinate) *gdpb.Position { } type Visitor struct { - visitor.BaseVisitor + visitor.Base // mux guarantees we're running only one tile.Map astar at a time. // TODO(minkezhang): Make this concurrent. @@ -83,7 +83,7 @@ func New( dirties *dirty.List, minPathLength int) *Visitor { return &Visitor{ - BaseVisitor: *visitor.NewBaseVisitor(visitorType), + Base: *visitor.New(fsmType), tileMap: tileMap, abstractGraph: abstractGraph, status: dfStatus, @@ -112,7 +112,7 @@ func (v *Visitor) visitFSM(node *move.Action) error { } ticksPerSecond := float64(time.Second / v.status.TickDuration()) - ticksPerTile := id.Tick(ticksPerSecond / e.Velocity()) + ticksPerTile := id.Tick(ticksPerSecond / e.MoveVelocity()) p, _, err := astar.Path( v.tileMap, diff --git a/server/visitor/move_test.go b/server/visitor/move_test.go index 39c9868..0f94611 100644 --- a/server/visitor/move_test.go +++ b/server/visitor/move_test.go @@ -69,7 +69,8 @@ func newVisitor(t *testing.T) *Visitor { } func newTank(t *testing.T, eid id.EntityID, tick id.Tick, p *gdpb.Position) *tank.Entity { - tankEntity, err := tank.New(eid, tick, p) + cid := id.ClientID("client-id") + tankEntity, err := tank.New(eid, tick, p, cid) if err != nil { t.Fatalf("New() = %v, want = nil", err) } diff --git a/server/visitor/produce.go b/server/visitor/produce.go index 2e78ae6..a19c22b 100644 --- a/server/visitor/produce.go +++ b/server/visitor/produce.go @@ -13,8 +13,8 @@ import ( "google.golang.org/grpc/status" gcpb "github.com/downflux/game/api/constants_go_proto" + fcpb "github.com/downflux/game/engine/fsm/api/constants_go_proto" serverstatus "github.com/downflux/game/engine/status/status" - vcpb "github.com/downflux/game/engine/visitor/api/constants_go_proto" ) const ( @@ -22,8 +22,8 @@ const ( // Entity objects. entityIDLen = 8 - // visitorType is the registered VisitorType of the produce visitor. - visitorType = vcpb.VisitorType_VISITOR_TYPE_PRODUCE + // fsmType is the registered FSMType of the produce visitor. + fsmType = fcpb.FSMType_FSM_TYPE_PRODUCE ) // unsupportedEntityType creates an appropriate error to return when a given @@ -35,7 +35,7 @@ func unsupportedEntityType(t gcpb.EntityType) error { // Visitor adds a new Entity to the global state. This struct implements the // visitor.Visitor interface. type Visitor struct { - visitor.BaseVisitor + visitor.Base entities *list.List @@ -50,10 +50,10 @@ type Visitor struct { // New creates a new instance of the Visitor struct. func New(dfStatus serverstatus.ReadOnlyStatus, entities *list.List, dirties *dirty.List) *Visitor { return &Visitor{ - BaseVisitor: *visitor.NewBaseVisitor(visitorType), - entities: entities, - dirties: dirties, - status: dfStatus, + Base: *visitor.New(fsmType), + entities: entities, + dirties: dirties, + status: dfStatus, } } @@ -80,7 +80,7 @@ func (v *Visitor) visitFSM(node *produce.Action) error { var ne entity.Entity switch entityType := node.EntityType(); entityType { case gcpb.EntityType_ENTITY_TYPE_TANK: - ne, err := tank.New(eid, tick, node.SpawnPosition()) + ne, err := tank.New(eid, tick, node.SpawnPosition(), node.SpawnClientID()) if err != nil { return err }