diff --git a/CHANGELOG.md b/CHANGELOG.md index be50302b..2f5cbbd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Response returns `dcs.common.v0.Target[]` for consistent object union across services. - Lua implementation unwraps grpcui oneof wrapper (`volume.shape`) and supports both wrapped and flattened shapes. +### Changed +- Changed `weapon` and `unknown` object exporters to return the `id_` (runtime ID) property. For `unknown` objects it is a fall-back condition used in cases where the object has no name. +- Changed `dcs.common.v0.Unit`, `dcs.common.v0.Weapon`, and `dcs.common.v0.Static` to set the `type` field as `Optional` as DCS doesn't always enforce this and the resulting log bloat was excessive. +- Changed catch-all for objects whose category could not be determined to no longer include `getID` in log message as not all object types implement the method. +- Changed `GRPC.onDCSEvent` to protect against an empty initiator for `S_EVENT_HIT`. +- Changed `handler.onPlayerChangeSlot` callback to protect against a nil return from `net.get_player_info`. +- Changed the `Unit` exporter to protect against `Group` being nil. + ## [0.8.1] 2024-11-05 ### Added diff --git a/lua/DCS-gRPC/exporters/object.lua b/lua/DCS-gRPC/exporters/object.lua index cc791e45..d1b5f5ce 100644 --- a/lua/DCS-gRPC/exporters/object.lua +++ b/lua/DCS-gRPC/exporters/object.lua @@ -17,6 +17,10 @@ GRPC.exporters.position = function(pos) end GRPC.exporters.unit = function(unit) + local locgroup = Unit.getGroup(unit) + if locgroup then + locgroup = GRPC.exporters.group(locgroup) + end return { id = tonumber(unit:getID()), name = unit:getName(), @@ -24,7 +28,7 @@ GRPC.exporters.unit = function(unit) coalition = unit:getCoalition() + 1, -- Increment for non zero-indexed gRPC enum type = unit:getTypeName(), playerName = Unit.getPlayerName(unit), - group = GRPC.exporters.group(Unit.getGroup(unit)), + group = locgroup, numberInGroup = unit:getNumber(), rawTransform = GRPC.exporters.rawTransform(unit), } @@ -55,7 +59,7 @@ end GRPC.exporters.weapon = function(weapon) return { - id = tonumber(weapon:getName()), + id = weapon.id_, type = weapon:getTypeName(), rawTransform = GRPC.exporters.rawTransform(weapon), } @@ -105,6 +109,11 @@ end -- in the base object of the hierarchy -- https://wiki.hoggitworld.com/view/DCS_Class_Object GRPC.exporters.unknown = function(object) + if not object.getName then + return { + name = tostring(object.id_), + } + end return { name = tostring(object:getName()), } diff --git a/lua/DCS-gRPC/grpc-hook.lua b/lua/DCS-gRPC/grpc-hook.lua index 419a7f44..8db5775c 100644 --- a/lua/DCS-gRPC/grpc-hook.lua +++ b/lua/DCS-gRPC/grpc-hook.lua @@ -86,14 +86,20 @@ end function handler.onPlayerChangeSlot(playerId) local playerInfo = net.get_player_info(playerId) + local coalition, slot + + if playerInfo ~= nil then + coalition = playerInfo.side + 1 -- offsetting for grpc COALITION enum + slot = playerInfo.slot + end grpc.event({ time = DCS.getModelTime(), event = { type = "playerChangeSlot", playerId = playerId, - coalition = playerInfo.side + 1, -- offsetting for grpc COALITION enum - slotId = playerInfo.slot + coalition = coalition, + slotId = slot }, }) end diff --git a/lua/DCS-gRPC/methods/mission.lua b/lua/DCS-gRPC/methods/mission.lua index 9551d044..4b2d40db 100644 --- a/lua/DCS-gRPC/methods/mission.lua +++ b/lua/DCS-gRPC/methods/mission.lua @@ -21,10 +21,7 @@ local function exporter(object) elseif category == Object.Category.Cargo then return GRPC.exporters.cargo(object) else - GRPC.logWarning( - "Could not determine object category of object with ID: " .. object:getID() - .. ", Category: " .. category - ) + GRPC.logWarning("mission:exporter - Could not determine object category") return nil end end @@ -50,10 +47,7 @@ local function typed_exporter(object) elseif category == Object.Category.Cargo then grpcTable.cargo = exporter(object) else - GRPC.logWarning( - "Could not determine object category of object with ID: " .. object:getID() - .. ", Category: " .. category - ) + GRPC.logWarning("mission:typed_exporter - Could not determine object category") grpcTable.unknown = GRPC.exporters.unknown(object) end @@ -75,11 +69,15 @@ GRPC.onDcsEvent = function(event) } elseif event.id == world.event.S_EVENT_HIT then + -- Initiator is optional, but if we have an empty map we get an error + local initiator = {initiator = typed_exporter(event.initiator)} + if initiator.initiator == nil then initiator = nil end + return { time = event.time, event = { type = "hit", - initiator = {initiator = typed_exporter(event.initiator)}, + initiator = initiator, weapon = exporter(event.weapon), target = {target = typed_exporter(event.target)}, weaponName = event.weapon_name, diff --git a/protos/dcs/common/v0/common.proto b/protos/dcs/common/v0/common.proto index c9e13f79..06c21b2d 100644 --- a/protos/dcs/common/v0/common.proto +++ b/protos/dcs/common/v0/common.proto @@ -222,7 +222,7 @@ message Unit { // The coalition the unit belongs to Coalition coalition = 4; // The DCS type-name of the unit. e.g "MiG-29A", "ZSU_57_2" or "Hawk ln" - string type = 5; + optional string type = 5; // The position of the unit Position position = 6; // The orientation of the unit in both 2D and 3D space @@ -271,7 +271,7 @@ message Weapon { uint32 id = 1; // The DCS type-name of the weapon. e.g "Matra_S530D", "HAWK_RAKETA" or // "weapons.shells.53-UOR-281U" - string type = 2; + optional string type = 2; // The position of the Weapon Position position = 3; // The orientation of the unit in both 2D and 3D space @@ -290,7 +290,7 @@ message Static { // The DCS generated ID uint32 id = 1; // The DCS type-name of the static - string type = 2; + optional string type = 2; // The name of the static string name = 3; // The coalition the static belongs to diff --git a/src/authentication.rs b/src/authentication.rs index 5c37db9d..66299b4b 100644 --- a/src/authentication.rs +++ b/src/authentication.rs @@ -26,11 +26,12 @@ impl RequestInterceptor for AuthInterceptor { } } - if client.is_some() { - log::debug!("Authenticated client: {}", client.unwrap()); - Ok(req) - } else { - Err(Status::unauthenticated("Unauthenticated")) + match client { + Some(client_name) => { + log::debug!("Authenticated client: {}", client_name); + Ok(req) + } + _ => Err(Status::unauthenticated("Unauthenticated")), } } _ => Err(Status::unauthenticated("Unauthenticated")), diff --git a/src/rpc/custom.rs b/src/rpc/custom.rs index 336c3a61..1acfe7a2 100644 --- a/src/rpc/custom.rs +++ b/src/rpc/custom.rs @@ -52,6 +52,7 @@ impl CustomService for MissionRpc { Ok(Response::new(custom::v0::EvalResponse { json })) } + #[allow(clippy::result_large_err)] async fn get_magnetic_declination( &self, request: Request, diff --git a/stubs/src/common.rs b/stubs/src/common.rs index 89577558..9361adf0 100644 --- a/stubs/src/common.rs +++ b/stubs/src/common.rs @@ -86,7 +86,7 @@ pub mod v0 { name: String, callsign: String, coalition: i32, - r#type: String, + r#type: Option, player_name: Option, group: Option, number_in_group: u32, @@ -127,7 +127,7 @@ pub mod v0 { #[serde(rename_all = "camelCase")] struct WeaponIntermediate { id: u32, - r#type: String, + r#type: Option, raw_transform: Option, } diff --git a/stubs/src/lib.rs b/stubs/src/lib.rs index 03e65040..d27aa115 100644 --- a/stubs/src/lib.rs +++ b/stubs/src/lib.rs @@ -91,7 +91,7 @@ mod tests { id: 1, name: "Aerial-1-1".to_string(), callsign: "Enfield11".to_string(), - r#type: "FA-18C_hornet".to_string(), + r#type: Some("FA-18C_hornet".to_string()), coalition: Coalition::Blue.into(), player_name: Some("New callsign".to_string()), group: None,