From 018e37cd2a505336e81985bc268c09756b2c38b3 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 20 Jul 2023 10:59:48 +0200 Subject: [PATCH] Minor graphic tweaks --- client/demo.js | 35 ++++++++++++++++++++++++++++++- client/src/constants/constants.ts | 1 - client/src/map/map.ts | 18 +++++++++++++--- client/src/units/dataextractor.ts | 8 +++++-- client/src/units/unit.ts | 15 +++++++------ client/src/units/unitsmanager.ts | 6 +++--- 6 files changed, 65 insertions(+), 18 deletions(-) diff --git a/client/demo.js b/client/demo.js index a92efcd6..04522530 100644 --- a/client/demo.js +++ b/client/demo.js @@ -14,7 +14,7 @@ const DEMO_UNIT_DATA = { TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 }, radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 }, generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false }, - ammo: [{ quantity: 2, name: "A cool missile", guidance: 0, category: 0, missileCategory: 0 } ], + ammo: [{ quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } ], contacts: [{ID: 2, detectionMethod: 1}, {ID: 3, detectionMethod: 4}], activePath: [{lat: 38, lng: -115, alt: 0}, {lat: 38, lng: -114, alt: 0}] }, @@ -63,6 +63,38 @@ const DEMO_UNIT_DATA = { ammo: [{ quantity: 2, name: "A cool missile", guidance: 0, category: 0, missileCategory: 0 } ], contacts: [{ID: 1, detectionMethod: 16}], activePath: [ ] + }, ["5"]:{ category: "GroundUnit", alive: true, human: false, controlled: true, coalition: 1, country: 0, name: "Gepard", unitName: "Cool guy 2-1", groupName: "Cool group 4", state: 1, task: "Being cool", + hasTask: false, position: { lat: 37.2, lng: -116.1, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isTanker: false, isAWACS: false, onOff: true, followRoads: false, fuel: 50, + desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0, + formationOffset: { x: 0, y: 0, z: 0 }, + targetID: 0, + targetPosition: { lat: 0, lng: 0, alt: 0 }, + ROE: 2, + reactionToThreat: 1, + emissionsCountermeasures: 1, + TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 }, + radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 }, + generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false }, + ammo: [{ quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } ], + contacts: [{ID: 1, detectionMethod: 16}], + activePath: [ ], + isLeader: true + }, ["6"]:{ category: "GroundUnit", alive: true, human: false, controlled: true, coalition: 1, country: 0, name: "Gepard", unitName: "Cool guy 2-2", groupName: "Cool group 4", state: 1, task: "Being cool", + hasTask: false, position: { lat: 37.21, lng: -116.1, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isTanker: false, isAWACS: false, onOff: true, followRoads: false, fuel: 50, + desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0, + formationOffset: { x: 0, y: 0, z: 0 }, + targetID: 0, + targetPosition: { lat: 0, lng: 0, alt: 0 }, + ROE: 2, + reactionToThreat: 1, + emissionsCountermeasures: 1, + TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 }, + radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 }, + generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false }, + ammo: [{ quantity: 2, name: "A cool missile", guidance: 0, category: 0, missileCategory: 0 } ], + contacts: [{ID: 1, detectionMethod: 16}], + activePath: [ ], + isLeader: false } } @@ -128,6 +160,7 @@ class DemoDataGenerator { array = this.appendAmmo(array, unit.ammo, 35); array = this.appendContacts(array, unit.contacts, 36); array = this.appendActivePath(array, unit.activePath, 37); + array = this.appendUint8(array, unit.isLeader, 38); array = this.concat(array, this.uint8ToByteArray(255)); } res.end(Buffer.from(array, 'binary')); diff --git a/client/src/constants/constants.ts b/client/src/constants/constants.ts index 7e47dff6..54e2f760 100644 --- a/client/src/constants/constants.ts +++ b/client/src/constants/constants.ts @@ -1,6 +1,5 @@ import { LatLng, LatLngBounds } from "leaflet"; -export const HIDE_ALL = "Hide all"; export const GAME_MASTER = "Game master"; export const BLUE_COMMANDER = "Blue commander"; export const RED_COMMANDER = "Red commander"; diff --git a/client/src/map/map.ts b/client/src/map/map.ts index 88758a00..8bad025d 100644 --- a/client/src/map/map.ts +++ b/client/src/map/map.ts @@ -46,6 +46,7 @@ export class Map extends L.Map { #miniMapLayerGroup: L.LayerGroup; #temporaryMarkers: TemporaryUnitMarker[] = []; #selecting: boolean = false; + #isZooming: boolean = false; #destinationGroupRotation: number = 0; #computeDestinationRotation: boolean = false; @@ -67,7 +68,7 @@ export class Map extends L.Map { constructor(ID: string) { /* Init the leaflet map */ //@ts-ignore Needed because the boxSelect option is non-standard - super(ID, { preferCanvas: true, doubleClickZoom: false, zoomControl: false, boxZoom: false, boxSelect: true, zoomAnimation: true, maxBoundsViscosity: 1.0, minZoom: 7, keyboard: true, keyboardPanDelta: 0 }); + super(ID, { zoomSnap: 0, zoomDelta: 0.25, preferCanvas: true, doubleClickZoom: false, zoomControl: false, boxZoom: false, boxSelect: true, zoomAnimation: true, maxBoundsViscosity: 1.0, minZoom: 7, keyboard: true, keyboardPanDelta: 0 }); this.setView([37.23, -115.8], 10); this.#ID = ID; @@ -93,7 +94,8 @@ export class Map extends L.Map { /* Register event handles */ this.on("click", (e: any) => this.#onClick(e)); this.on("dblclick", (e: any) => this.#onDoubleClick(e)); - this.on("zoomstart", (e: any) => this.#onZoom(e)); + this.on("zoomstart", (e: any) => this.#onZoomStart(e)); + this.on("zoomend", (e: any) => this.#onZoomEnd(e)); this.on("drag", (e: any) => this.centerOnUnit(null)); this.on("contextmenu", (e: any) => this.#onContextMenu(e)); this.on('selectionstart', (e: any) => this.#onSelectionStart(e)); @@ -270,6 +272,10 @@ export class Map extends L.Map { this.#coalitionAreaContextMenu.hide(); } + isZooming() { + return this.#isZooming; + } + /* Mouse coordinates */ getMousePosition() { return this.#lastMousePosition; @@ -544,11 +550,17 @@ export class Map extends L.Map { this.#updateDestinationCursors(); } - #onZoom(e: any) { + #onZoomStart(e: any) { if (this.#centerUnit != null) this.#panToUnit(this.#centerUnit); + this.#isZooming = true; } + #onZoomEnd(e: any) { + this.#isZooming = false; + } + + #panToUnit(unit: Unit) { var unitPosition = new L.LatLng(unit.getPosition().lat, unit.getPosition().lng); this.setView(unitPosition, this.getZoom(), { animate: false }); diff --git a/client/src/units/dataextractor.ts b/client/src/units/dataextractor.ts index 9390be62..278d4a72 100644 --- a/client/src/units/dataextractor.ts +++ b/client/src/units/dataextractor.ts @@ -64,9 +64,13 @@ export class DataExtractor { extractString(length?: number) { if (length === undefined) length = this.extractUInt16() - const value = this.#decoder.decode(this.#buffer.slice(this.#seekPosition, this.#seekPosition + length)); + var stringBuffer = this.#buffer.slice(this.#seekPosition, this.#seekPosition + length); + var view = new Int8Array(stringBuffer); + var stringLength = length; + view.forEach((value: number, idx: number) => { if (value === 0) stringLength = idx; }); + const value = this.#decoder.decode(stringBuffer); this.#seekPosition += length; - return value; + return value.substring(0, stringLength).trim(); } extractChar() { diff --git a/client/src/units/unit.ts b/client/src/units/unit.ts index efaa85ab..7f7ded20 100644 --- a/client/src/units/unit.ts +++ b/client/src/units/unit.ts @@ -6,7 +6,7 @@ import { CustomMarker } from '../map/custommarker'; import { SVGInjector } from '@tanem/svg-injector'; import { UnitDatabase } from './unitdatabase'; import { TargetMarker } from '../map/targetmarker'; -import { BLUE_COMMANDER, BOMBING, CARPET_BOMBING, DLINK, DataIndexes, FIRE_AT_AREA, GAME_MASTER, HIDE_ALL, IDLE, IRST, MOVE_UNIT, OPTIC, RADAR, RED_COMMANDER, ROEs, RWR, VISUAL, emissionsCountermeasures, reactionsToThreat, states } from '../constants/constants'; +import { BLUE_COMMANDER, BOMBING, CARPET_BOMBING, DLINK, DataIndexes, FIRE_AT_AREA, GAME_MASTER, IDLE, IRST, MOVE_UNIT, OPTIC, RADAR, RED_COMMANDER, ROEs, RWR, VISUAL, emissionsCountermeasures, reactionsToThreat, states } from '../constants/constants'; import { Ammo, Contact, GeneralSettings, Offset, Radio, TACAN, UnitIconOptions } from '../@types/unit'; import { DataExtractor } from './dataextractor'; import { groundUnitDatabase } from './groundunitdatabase'; @@ -157,6 +157,7 @@ export class Unit extends CustomMarker { this.on('contextmenu', (e) => this.#onContextMenu(e)); this.on('mouseover', () => { this.setHighlighted(true); }) this.on('mouseout', () => { this.setHighlighted(false); }) + getMap().on("zoomend", () => {this.#onZoom();}) /* Deselect units if they are hidden */ document.addEventListener("toggleCoalitionVisibility", (ev: CustomEventInit) => { @@ -165,9 +166,7 @@ export class Unit extends CustomMarker { document.addEventListener("toggleUnitVisibility", (ev: CustomEventInit) => { window.setTimeout(() => { this.setSelected(this.getSelected() && !this.getHidden()) }, 300); - }); - - getMap().on("zoomend", () => {this.#onZoom();}) + }); } getCategory() { @@ -379,8 +378,6 @@ export class Unit extends CustomMarker { } belongsToCommandedCoalition() { - if (getUnitsManager().getCommandMode() === HIDE_ALL) - return false; if (getUnitsManager().getCommandMode() === BLUE_COMMANDER && this.#coalition !== "blue") return false; if (getUnitsManager().getCommandMode() === RED_COMMANDER && this.#coalition !== "red") @@ -499,7 +496,6 @@ export class Unit extends CustomMarker { (this.#controlled == false && hiddenUnits.includes("dcs")) || (hiddenUnits.includes(this.getMarkerCategory())) || (hiddenUnits.includes(this.#coalition)) || - (getUnitsManager().getCommandMode() === HIDE_ALL) || (!this.belongsToCommandedCoalition() && this.#detectionMethods.length == 0) || (!this.#isLeader && this.getCategory() == "GroundUnit" && getMap().getZoom() < 13)) && !(this.getSelected()); @@ -512,7 +508,10 @@ export class Unit extends CustomMarker { /* Add the marker if not present */ if (!getMap().hasLayer(this) && !this.getHidden()) { - this.addTo(getMap()); + if (getMap().isZooming()) + this.once("zoomend", () => {this.addTo(getMap())}) + else + this.addTo(getMap()); } /* Hide the marker if necessary*/ diff --git a/client/src/units/unitsmanager.ts b/client/src/units/unitsmanager.ts index 6288918e..ce50335b 100644 --- a/client/src/units/unitsmanager.ts +++ b/client/src/units/unitsmanager.ts @@ -5,7 +5,7 @@ import { cloneUnit, deleteUnit, spawnAircrafts, spawnGroundUnits } from "../serv import { bearingAndDistanceToLatLng, deg2rad, keyEventWasInInput, latLngToMercator, mToFt, mercatorToLatLng, msToKnots, polyContains, polygonArea, randomPointInPoly, randomUnitBlueprint } from "../other/utils"; import { CoalitionArea } from "../map/coalitionarea"; import { groundUnitDatabase } from "./groundunitdatabase"; -import { DataIndexes, HIDE_ALL, IADSDensities, IDLE, MOVE_UNIT } from "../constants/constants"; +import { DataIndexes, GAME_MASTER, IADSDensities, IDLE, MOVE_UNIT } from "../constants/constants"; import { DataExtractor } from "./dataextractor"; import { Contact } from "../@types/unit"; import { citiesDatabase } from "./citiesdatabase"; @@ -16,7 +16,7 @@ export class UnitsManager { #selectionEventDisabled: boolean = false; #pasteDisabled: boolean = false; #hiddenTypes: string[] = []; - #commandMode: string = HIDE_ALL; + #commandMode: string = GAME_MASTER; #requestDetectionUpdate: boolean = false; constructor() { @@ -93,7 +93,7 @@ export class UnitsManager { this.#units[ID]?.setData(dataExtractor); } - if (this.#requestDetectionUpdate) { + if (this.#requestDetectionUpdate && this.getCommandMode() != GAME_MASTER) { for (let ID in this.#units) { var unit = this.#units[ID]; if (!unit.belongsToCommandedCoalition())