/// <summary> /// Constructs an entity object /// </summary> /// <param name="guid">Entity GUID</param> /// <param name="entityType">Entity type</param> /// <param name="gameColor">Game color</param> /// <param name="isSpectating">Is spectating</param> /// <param name="position">Position</param> /// <param name="rotation">Rotation</param> /// <param name="velocity">Velocity</param> /// <param name="angularVelocity">Angular velocity</param> /// <param name="actions">Game actions</param> /// <param name="isResyncRequested">Is resynchronization requested</param> public Entity(Guid guid, string entityType, EGameColor gameColor, bool isSpectating, Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 angularVelocity, IEnumerable <string> actions, bool isResyncRequested) { if (guid == Guid.Empty) { throw new ArgumentException("Entity GUID can't be empty.", nameof(guid)); } if (string.IsNullOrWhiteSpace(entityType)) { throw new ArgumentNullException(nameof(entityType)); } if (gameColor == EGameColor.Invalid) { throw new ArgumentException("Game color can't be invalid.", nameof(gameColor)); } if (actions == null) { throw new ArgumentNullException(nameof(actions)); } if (Protection.IsContained(actions, (action) => action == null)) { throw new ArgumentException($"\"{ nameof(actions) }\" contains invalid game actions.", nameof(guid)); } GUID = guid; EntityType = entityType; GameColor = gameColor; IsSpectating = isSpectating; Position = position; Rotation = rotation; Velocity = velocity; AngularVelocity = angularVelocity; this.actions.UnionWith(actions); IsResyncRequested = isResyncRequested; }
/// <summary> /// Constructs entity data /// </summary> /// <param name="guid">Entity GUID</param> /// <param name="entityType">Current entity type (optional)</param> /// <param name="color">Current game color (optional)</param> /// <param name="isSpectating">Is spectating (optional)</param> /// <param name="position">Current position (optional)</param> /// <param name="rotation">Current rotation (optional)</param> /// <param name="velocity">Current velocity (optional)</param> /// <param name="angularVelocity">Current angular velocity (optional)</param> /// <param name="actions">Current game actions (optional)</param> /// <param name="isResyncRequested">Is resynchronization requested (optional)</param> public EntityData(Guid guid, string entityType, EGameColor?color, bool?isSpectating, Vector3?position, Quaternion?rotation, Vector3?velocity, Vector3?angularVelocity, IEnumerable <string> actions, bool?isResyncRequested) { if (guid == Guid.Empty) { throw new ArgumentException("Entity GUID can't be empty.", nameof(guid)); } if ((entityType != null) && string.IsNullOrWhiteSpace(entityType)) { throw new ArgumentException("Entity type can't be empty.", nameof(entityType)); } if ((color != null) && (color == EGameColor.Invalid)) { throw new ArgumentException("Game color can't be invalid.", nameof(color)); } if ((actions != null) && Protection.IsContained(actions, (action) => action == null)) { throw new ArgumentException($"\"{ nameof(actions) }\" contains invalid game actions"); } GUID = guid; EntityType = entityType; GameColor = color; IsSpectating = isSpectating; Position = (position == null) ? null : (Vector3FloatData)position; Rotation = (rotation == null) ? null : (QuaternionFloatData)rotation; Velocity = (velocity == null) ? null : (Vector3FloatData)velocity; AngularVelocity = (angularVelocity == null) ? null : (Vector3FloatData)angularVelocity; GameColor = color; Actions = (actions == null) ? null : new List <string>(actions ?? throw new ArgumentNullException(nameof(actions))); IsResyncRequested = isResyncRequested; }
/// <summary> /// Constructs a message for creating and joining a new lobby /// </summary> /// <param name="username">Username</param> /// <param name="lobbyName">Lobby name</param> /// <param name="gameMode">Game mode</param> /// <param name="isPrivate">Is lobby private</param> /// <param name="minimalUserCount">Minimal user count</param> /// <param name="maximalUserCount">Maximal user count</param> /// <param name="isStartingGameAutomatically">Is starting game automatically</param> /// <param name="gameModeRules">Game mode rules</param> public CreateAndJoinLobbyMessageData(string username, string lobbyName, string gameMode, bool?isPrivate = null, uint?minimalUserCount = null, uint?maximalUserCount = null, bool?isStartingGameAutomatically = null, IReadOnlyDictionary <string, object> gameModeRules = null) : base(Naming.GetMessageTypeNameFromMessageDataType <CreateAndJoinLobbyMessageData>()) { if (username == null) { throw new ArgumentNullException(nameof(username)); } string new_username = username.Trim(); if ((new_username.Length < Defaults.minimalUsernameLength) || (new_username.Length > Defaults.maximalUsernameLength)) { throw new ArgumentException($"Username must be between { Defaults.minimalUsernameLength } and { Defaults.maximalUsernameLength } characters long.", nameof(username)); } if (lobbyName == null) { throw new ArgumentNullException(nameof(lobbyName)); } string new_lobby_name = lobbyName.Trim(); if ((new_lobby_name.Length < Defaults.minimalLobbyNameLength) || (new_lobby_name.Length > Defaults.maximalLobbyNameLength)) { throw new ArgumentException($"Lobby name must be between { Defaults.minimalLobbyNameLength } and { Defaults.maximalLobbyNameLength } characters long.", nameof(lobbyName)); } if (string.IsNullOrWhiteSpace(gameMode)) { throw new ArgumentNullException(nameof(gameMode)); } if ((minimalUserCount != null) && (maximalUserCount != null) && (minimalUserCount > maximalUserCount)) { throw new ArgumentException("Minimal user count can't be greater than maximal user count.", nameof(minimalUserCount)); } if ((gameModeRules != null) && Protection.IsContained(gameModeRules.Values, (value) => value == null)) { throw new ArgumentException("Game mode rules contains null.", nameof(gameModeRules)); } Username = new_username; LobbyName = new_lobby_name; GameMode = gameMode; IsPrivate = isPrivate; MinimalUserCount = minimalUserCount; MaximalUserCount = maximalUserCount; IsStartingGameAutomatically = isStartingGameAutomatically; if (gameModeRules != null) { GameModeRules = new Dictionary <string, object>(); foreach (KeyValuePair <string, object> game_mode_rule in gameModeRules) { GameModeRules.Add(game_mode_rule.Key, game_mode_rule.Value); } } }
/// <summary> /// Sets the game actions internally /// </summary> /// <param name="actions">Game actions</param> /// <returns>Number of actions added</returns> public uint SetActionsInternally(IEnumerable <string> actions) { if (actions == null) { throw new ArgumentNullException(nameof(actions)); } if (Protection.IsContained(actions, (action) => action == null)) { throw new ArgumentException("Game actions contain null."); } uint ret = 0U; this.actions.Clear(); foreach (string action in actions) { ret += this.actions.Add(action) ? 1U : 0U; } return(ret); }
/// <summary> /// Tries to get entity delta from the specified entities /// </summary> /// <param name="baseEntity">Base entity</param> /// <param name="patchEntity">Patch entity</param> /// <param name="entityDelta">Entity data</param> /// <returns>"true" if differences between base and patch entities exist, otherwise "false"</returns> public static bool TryGetDelta(IEntity baseEntity, IEntity patchEntity, out IEntityDelta entityDelta) { if (baseEntity == null) { throw new ArgumentNullException(nameof(baseEntity)); } if (!baseEntity.IsValid) { throw new ArgumentException("Base entity is not valid.", nameof(baseEntity)); } if (patchEntity == null) { throw new ArgumentNullException(nameof(patchEntity)); } if (!patchEntity.IsValid) { throw new ArgumentException("Patch entity is not valid.", nameof(patchEntity)); } if (baseEntity.GUID != patchEntity.GUID) { throw new ArgumentException($"Base entity GUID \"{ baseEntity.GUID }\" does not match patch entity GUID \"{ patchEntity.GUID }\".", nameof(patchEntity)); } bool ret = false; string entity_type = null; EGameColor? game_color = null; bool? is_spectating = null; Vector3? position = null; Quaternion? rotation = null; Vector3? velocity = null; Vector3? angular_velocity = null; IEnumerable <string> actions = null; bool? is_resync_requested = null; if (baseEntity != patchEntity) { if (baseEntity.EntityType != patchEntity.EntityType) { ret = true; entity_type = patchEntity.EntityType; } if (baseEntity.EntityType != patchEntity.EntityType) { ret = true; entity_type = patchEntity.EntityType; } if (baseEntity.GameColor != patchEntity.GameColor) { ret = true; game_color = patchEntity.GameColor; } if (baseEntity.IsSpectating != patchEntity.IsSpectating) { ret = true; is_spectating = patchEntity.IsSpectating; } if (baseEntity.Position != patchEntity.Position) { ret = true; position = patchEntity.Position; } if (baseEntity.Rotation != patchEntity.Rotation) { ret = true; rotation = patchEntity.Rotation; } if (baseEntity.Velocity != patchEntity.Velocity) { ret = true; velocity = patchEntity.Velocity; } if (baseEntity.AngularVelocity != patchEntity.AngularVelocity) { ret = true; angular_velocity = patchEntity.AngularVelocity; } foreach (string action in baseEntity.Actions) { if (!Protection.IsContained(patchEntity.Actions, (patch_entity_action) => patch_entity_action == action)) { actions = patchEntity.Actions; break; } } if (baseEntity.IsResyncRequested != patchEntity.IsResyncRequested) { ret = true; is_resync_requested = patchEntity.IsResyncRequested; } if (actions == null) { foreach (string action in patchEntity.Actions) { if (!Protection.IsContained(baseEntity.Actions, (base_entity_action) => base_entity_action == action)) { actions = patchEntity.Actions; break; } } } } entityDelta = ret ? (IEntityDelta) new EntityDelta(baseEntity.GUID, entity_type, game_color, is_spectating, position, rotation, velocity, angular_velocity, actions, is_resync_requested) : null; return(ret); }