Compare commits

...

16 Commits

Author SHA1 Message Date
Dmitry Popov
27b5694885 chore: release version v1.66.15 2025-06-08 11:03:13 +02:00
Dmitry Popov
4093f28cee chore: release version v1.66.15 2025-06-08 10:45:41 +02:00
Dmitry Popov
08aaf2f2dd chore: release version v1.66.15 2025-06-08 10:19:25 +02:00
Dmitry Popov
df955ff8b0 chore: release version v1.66.15 2025-06-07 13:57:25 +02:00
CI
4dc74022b4 chore: release version v1.66.15 2025-06-07 09:01:44 +00:00
Dmitry Popov
c2b7d07208 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 10:58:35 +02:00
Dmitry Popov
21e76a6f05 fix(Core): Added back arm docker image build 2025-06-07 10:58:24 +02:00
CI
89c0d6fad6 chore: release version v1.66.14 2025-06-07 08:48:05 +00:00
Dmitry Popov
b74d15b1ee Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 10:47:31 +02:00
Dmitry Popov
10313438bf fix(Core): fixed online updates 2025-06-07 10:47:28 +02:00
CI
a764217948 chore: release version v1.66.13 2025-06-07 07:49:31 +00:00
Dmitry Popov
d81d6fb937 Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 09:48:56 +02:00
Dmitry Popov
4c0f7ab7f9 fix(Core): fixed location tracking issues 2025-06-07 09:48:53 +02:00
CI
1c48945a96 chore: release version v1.66.12
Some checks failed
Build / 🛠 Build (1.17, 18.x, 27) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/amd64) (push) Has been cancelled
Build / 🛠 Build Docker Images (linux/arm64) (push) Has been cancelled
Build / merge (push) Has been cancelled
Build / 🏷 Create Release (push) Has been cancelled
2025-06-06 23:58:04 +00:00
Dmitry Popov
850901f62f Merge branch 'main' of github.com:wanderer-industries/wanderer 2025-06-07 01:57:37 +02:00
Dmitry Popov
4822854e30 chore: release version v1.66.10 2025-06-07 01:57:32 +02:00
17 changed files with 317 additions and 116 deletions

View File

@@ -116,6 +116,7 @@ jobs:
matrix:
platform:
- linux/amd64
- linux/arm64
steps:
- name: Prepare
run: |

View File

@@ -2,6 +2,38 @@
<!-- changelog -->
## [v1.66.15](https://github.com/wanderer-industries/wanderer/compare/v1.66.14...v1.66.15) (2025-06-07)
### Bug Fixes:
* Core: Added back arm docker image build
## [v1.66.14](https://github.com/wanderer-industries/wanderer/compare/v1.66.13...v1.66.14) (2025-06-07)
### Bug Fixes:
* Core: fixed online updates
## [v1.66.13](https://github.com/wanderer-industries/wanderer/compare/v1.66.12...v1.66.13) (2025-06-07)
### Bug Fixes:
* Core: fixed location tracking issues
## [v1.66.12](https://github.com/wanderer-industries/wanderer/compare/v1.66.11...v1.66.12) (2025-06-06)
## [v1.66.11](https://github.com/wanderer-industries/wanderer/compare/v1.66.10...v1.66.11) (2025-06-06)

View File

@@ -1,14 +1,13 @@
import { useCallback } from 'react';
import clsx from 'clsx';
import { useAutoAnimate } from '@formkit/auto-animate/react';
import { Commands } from '@/hooks/Mapper/types/mapHandlers.ts';
import { CharacterTypeRaw } from '@/hooks/Mapper/types';
import { emitMapEvent } from '@/hooks/Mapper/events';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import classes from './Characters.module.scss';
import { isDocked } from '@/hooks/Mapper/helpers/isDocked.ts';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { CharacterTypeRaw } from '@/hooks/Mapper/types';
import { Commands, OutCommand } from '@/hooks/Mapper/types/mapHandlers.ts';
import { useAutoAnimate } from '@formkit/auto-animate/react';
import clsx from 'clsx';
import { PrimeIcons } from 'primereact/api';
import { useCallback } from 'react';
import classes from './Characters.module.scss';
interface CharactersProps {
data: CharacterTypeRaw[];
}
@@ -17,13 +16,22 @@ export const Characters = ({ data }: CharactersProps) => {
const [parent] = useAutoAnimate();
const {
outCommand,
data: { mainCharacterEveId, followingCharacterEveId },
} = useMapRootState();
const handleSelect = useCallback((character: CharacterTypeRaw) => {
const handleSelect = useCallback(async (character: CharacterTypeRaw) => {
if (!character) {
return;
}
await outCommand({
type: OutCommand.startTracking,
data: { character_eve_id: character.eve_id },
});
emitMapEvent({
name: Commands.centerSystem,
data: character?.location?.solar_system_id?.toString(),
data: character.location?.solar_system_id?.toString(),
});
}, []);
@@ -37,14 +45,26 @@ export const Characters = ({ data }: CharactersProps) => {
className={clsx(
'overflow-hidden relative',
'flex w-[35px] h-[35px] rounded-[4px] border-[1px] border-solid bg-transparent cursor-pointer',
'transition-colors duration-250',
'transition-colors duration-250 hover:bg-stone-300/90',
{
['border-stone-800/90']: !character.online,
['border-lime-600/70']: character.online,
},
)}
title={character.name}
title={character.tracking_paused ? `${character.name} - Tracking Paused (click to resume)` : character.name}
>
{character.tracking_paused && (
<>
<span
className={clsx(
'absolute top-[2px] left-[2px] w-[9px] h-[9px]',
'text-yellow-500 text-[9px] rounded-[1px] z-10 hover:hidden',
'pi',
PrimeIcons.PAUSE,
)}
/>
</>
)}
{mainCharacterEveId === character.eve_id && (
<span
className={clsx(
@@ -55,6 +75,7 @@ export const Characters = ({ data }: CharactersProps) => {
)}
/>
)}
{followingCharacterEveId === character.eve_id && (
<span
className={clsx(

View File

@@ -1,5 +1,4 @@
import { useMapState } from '@/hooks/Mapper/components/map/MapProvider.tsx';
import { useCallback, useRef } from 'react';
import {
CommandCharacterAdded,
CommandCharacterRemoved,
@@ -7,6 +6,7 @@ import {
CommandCharacterUpdated,
CommandPresentCharacters,
} from '@/hooks/Mapper/types';
import { useCallback, useRef } from 'react';
export const useCommandsCharacters = () => {
const { update } = useMapState();

View File

@@ -1,8 +1,8 @@
import { useReactFlow } from 'reactflow';
import { useCallback, useRef } from 'react';
import { CommandInit } from '@/hooks/Mapper/types/mapHandlers.ts';
import { convertConnection2Edge, convertSystem2Node } from '../../helpers';
import { MapData, useMapState } from '@/hooks/Mapper/components/map/MapProvider.tsx';
import { CommandInit } from '@/hooks/Mapper/types/mapHandlers.ts';
import { useCallback, useRef } from 'react';
import { useReactFlow } from 'reactflow';
import { convertConnection2Edge, convertSystem2Node } from '../../helpers';
export const useMapInit = () => {
const rf = useReactFlow();

View File

@@ -1,14 +1,13 @@
import { Characters } from '../characters/Characters';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { useMemo } from 'react';
import clsx from 'clsx';
import { sortOnlineFunc } from '@/hooks/Mapper/components/hooks/useGetOwnOnlineCharacters.ts';
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
import { WithChildren } from '@/hooks/Mapper/types/common.ts';
import { Button } from 'primereact/button';
import clsx from 'clsx';
import { useMemo } from 'react';
import { Characters } from '../characters/Characters';
const Topbar = ({ children }: WithChildren) => {
const {
data: { characters, userCharacters, pings },
data: { characters, userCharacters },
} = useMapRootState();
const charsToShow = useMemo(() => {

View File

@@ -33,6 +33,7 @@ export type CharacterTypeRaw = {
corporation_id: number;
corporation_name: string;
corporation_ticker: string;
tracking_paused: boolean;
};
export interface TrackingCharacter {

View File

@@ -1,10 +1,10 @@
import { SolarSystemRawType, SolarSystemStaticInfoRaw } from '@/hooks/Mapper/types/system.ts';
import { SolarSystemConnection } from '@/hooks/Mapper/types/connection.ts';
import { WormholeDataRaw } from '@/hooks/Mapper/types/wormholes.ts';
import { ActivitySummary, CharacterTypeRaw, TrackingCharacter } from '@/hooks/Mapper/types/character.ts';
import { RoutesList } from '@/hooks/Mapper/types/routes.ts';
import { DetailedKill, Kill } from '@/hooks/Mapper/types/kills.ts';
import { CommentType, PingData, SystemSignature, UserPermissions } from '@/hooks/Mapper/types';
import { ActivitySummary, CharacterTypeRaw, TrackingCharacter } from '@/hooks/Mapper/types/character.ts';
import { SolarSystemConnection } from '@/hooks/Mapper/types/connection.ts';
import { DetailedKill, Kill } from '@/hooks/Mapper/types/kills.ts';
import { RoutesList } from '@/hooks/Mapper/types/routes.ts';
import { SolarSystemRawType, SolarSystemStaticInfoRaw } from '@/hooks/Mapper/types/system.ts';
import { WormholeDataRaw } from '@/hooks/Mapper/types/wormholes.ts';
export enum Commands {
init = 'init',
@@ -260,6 +260,7 @@ export enum OutCommand {
updateMainCharacter = 'updateMainCharacter',
addPing = 'add_ping',
cancelPing = 'cancel_ping',
startTracking = 'startTracking',
// Only UI commands
openSettings = 'open_settings',

View File

@@ -251,13 +251,22 @@ defmodule WandererApp.Character do
end
end
defp maybe_merge_map_character_settings(character, map_id, true), do: character
defp maybe_merge_map_character_settings(%{id: character_id} = character, map_id, true) do
{:ok, tracking_paused} =
WandererApp.Cache.lookup("character:#{character_id}:tracking_paused", false)
character
|> Map.merge(%{tracking_paused: tracking_paused})
end
defp maybe_merge_map_character_settings(
%{id: character_id} = character,
map_id,
_character_is_present
) do
{:ok, tracking_paused} =
WandererApp.Cache.lookup("character:#{character_id}:tracking_paused", false)
WandererApp.MapCharacterSettingsRepo.get(map_id, character_id)
|> case do
{:ok, settings} when not is_nil(settings) ->
@@ -270,6 +279,7 @@ defmodule WandererApp.Character do
|> Map.put(:online, false)
|> Map.merge(@default_character_tracking_data)
end
|> Map.merge(%{tracking_paused: tracking_paused})
end
defp prepare_search_results(result) do

View File

@@ -33,12 +33,16 @@ defmodule WandererApp.Character.Tracker do
status: binary()
}
@pause_tracking_timeout :timer.minutes(10)
@online_error_timeout :timer.minutes(1)
@pause_tracking_timeout :timer.minutes(60 * 24)
@offline_timeout :timer.minutes(5)
@online_error_timeout :timer.minutes(2)
@ship_error_timeout :timer.minutes(2)
@location_error_timeout :timer.minutes(2)
@online_forbidden_ttl :timer.seconds(7)
@online_limit_ttl :timer.seconds(7)
@forbidden_ttl :timer.seconds(5)
@limit_ttl :timer.seconds(5)
@location_limit_ttl :timer.seconds(1)
@pubsub_client Application.compile_env(:wanderer_app, :pubsub_client)
def new(), do: __struct__()
@@ -53,8 +57,37 @@ defmodule WandererApp.Character.Tracker do
|> new()
end
def check_online_errors(character_id) do
WandererApp.Cache.lookup!("character:#{character_id}:online_error_time")
def check_offline(character_id) do
WandererApp.Cache.lookup!("character:#{character_id}:last_online_time")
|> case do
nil ->
pause_tracking(character_id)
:ok
last_online_time ->
duration = DateTime.diff(DateTime.utc_now(), last_online_time, :millisecond)
if duration >= @offline_timeout do
pause_tracking(character_id)
:ok
else
:skip
end
end
end
def check_online_errors(character_id),
do: check_tracking_errors(character_id, "online", @online_error_timeout)
def check_ship_errors(character_id),
do: check_tracking_errors(character_id, "ship", @ship_error_timeout)
def check_location_errors(character_id),
do: check_tracking_errors(character_id, "location", @location_error_timeout)
defp check_tracking_errors(character_id, type, timeout) do
WandererApp.Cache.lookup!("character:#{character_id}:#{type}_error_time")
|> case do
nil ->
:skip
@@ -62,34 +95,8 @@ defmodule WandererApp.Character.Tracker do
error_time ->
duration = DateTime.diff(DateTime.utc_now(), error_time, :millisecond)
if duration >= @online_error_timeout do
WandererApp.Cache.delete("character:#{character_id}:online_forbidden")
WandererApp.Cache.delete("character:#{character_id}:online_error_time")
WandererApp.Character.update_character(character_id, %{online: false})
WandererApp.Character.update_character_state(character_id, %{
is_online: false
})
WandererApp.Cache.put(
"character:#{character_id}:tracking_paused",
true,
ttl: @pause_tracking_timeout
)
{:ok, %{solar_system_id: solar_system_id}} =
WandererApp.Character.get_character(character_id)
{:ok, %{active_maps: active_maps}} =
WandererApp.Character.get_character_state(character_id)
active_maps
|> Enum.each(fn map_id ->
WandererApp.Cache.put(
"map:#{map_id}:character:#{character_id}:start_solar_system_id",
solar_system_id
)
end)
if duration >= timeout do
pause_tracking(character_id)
:ok
else
@@ -98,6 +105,42 @@ defmodule WandererApp.Character.Tracker do
end
end
defp pause_tracking(character_id) do
if not WandererApp.Cache.has_key?("character:#{character_id}:tracking_paused") do
WandererApp.Cache.delete("character:#{character_id}:online_forbidden")
WandererApp.Cache.delete("character:#{character_id}:online_error_time")
WandererApp.Cache.delete("character:#{character_id}:ship_error_time")
WandererApp.Cache.delete("character:#{character_id}:location_error_time")
WandererApp.Character.update_character(character_id, %{online: false})
WandererApp.Character.update_character_state(character_id, %{
is_online: false
})
Logger.warning("[CharacterTracker] paused for #{character_id}")
WandererApp.Cache.put(
"character:#{character_id}:tracking_paused",
true,
ttl: @pause_tracking_timeout
)
{:ok, %{solar_system_id: solar_system_id}} =
WandererApp.Character.get_character(character_id)
{:ok, %{active_maps: active_maps}} =
WandererApp.Character.get_character_state(character_id)
active_maps
|> Enum.each(fn map_id ->
WandererApp.Cache.put(
"map:#{map_id}:character:#{character_id}:start_solar_system_id",
solar_system_id
)
end)
end
end
def update_settings(character_id, track_settings) do
{:ok, character_state} = WandererApp.Character.get_character_state(character_id)
@@ -134,18 +177,19 @@ defmodule WandererApp.Character.Tracker do
{:ok, online} ->
online = get_online(online)
WandererApp.Cache.delete("character:#{character_id}:online_forbidden")
if is_nil(
WandererApp.Cache.lookup!("character:#{character_id}:online_error_time")
) do
if online.online == true do
WandererApp.Cache.insert(
"character:#{character_id}:online_error_time",
"character:#{character_id}:last_online_time",
DateTime.utc_now()
)
else
WandererApp.Cache.delete("character:#{character_id}:last_online_time")
end
# WandererApp.Cache.delete("character:#{character_id}:online_error_time")
WandererApp.Cache.delete("character:#{character_id}:online_forbidden")
WandererApp.Cache.delete("character:#{character_id}:online_error_time")
WandererApp.Cache.delete("character:#{character_id}:ship_error_time")
WandererApp.Cache.delete("character:#{character_id}:location_error_time")
WandererApp.Cache.delete("character:#{character_id}:info_forbidden")
WandererApp.Cache.delete("character:#{character_id}:ship_forbidden")
WandererApp.Cache.delete("character:#{character_id}:location_forbidden")
@@ -196,15 +240,6 @@ defmodule WandererApp.Character.Tracker do
ttl: reset_timeout
)
if is_nil(
WandererApp.Cache.lookup!("character:#{character_id}:online_error_time")
) do
WandererApp.Cache.insert(
"character:#{character_id}:online_error_time",
DateTime.utc_now()
)
end
{:error, :skipped}
{:error, error} ->
@@ -239,11 +274,16 @@ defmodule WandererApp.Character.Tracker do
def update_online(_), do: {:error, :skipped}
defp get_reset_timeout(%{"x-esi-error-limit-reset" => [reset_seconds]})
defp get_reset_timeout(_headers, _default_timeout \\ @limit_ttl)
defp get_reset_timeout(
%{"x-esi-error-limit-remain" => ["0"], "x-esi-error-limit-reset" => [reset_seconds]},
_default_timeout
)
when is_binary(reset_seconds),
do: :timer.seconds((reset_seconds |> String.to_integer()) + 1)
defp get_reset_timeout(_headers), do: @limit_ttl
defp get_reset_timeout(_headers, default_timeout), do: default_timeout
def update_info(character_id) do
(WandererApp.Cache.has_key?("character:#{character_id}:online_forbidden") ||
@@ -346,6 +386,13 @@ defmodule WandererApp.Character.Tracker do
ttl: @forbidden_ttl
)
if is_nil(WandererApp.Cache.lookup!("character:#{character_id}:ship_error_time")) do
WandererApp.Cache.insert(
"character:#{character_id}:ship_error_time",
DateTime.utc_now()
)
end
{:error, error}
{:error, :error_limited, headers} ->
@@ -370,6 +417,13 @@ defmodule WandererApp.Character.Tracker do
ttl: @forbidden_ttl
)
if is_nil(WandererApp.Cache.lookup!("character:#{character_id}:ship_error_time")) do
WandererApp.Cache.insert(
"character:#{character_id}:ship_error_time",
DateTime.utc_now()
)
end
{:error, error}
_ ->
@@ -381,6 +435,13 @@ defmodule WandererApp.Character.Tracker do
ttl: @forbidden_ttl
)
if is_nil(WandererApp.Cache.lookup!("character:#{character_id}:ship_error_time")) do
WandererApp.Cache.insert(
"character:#{character_id}:ship_error_time",
DateTime.utc_now()
)
end
{:error, :skipped}
end
end
@@ -403,8 +464,7 @@ defmodule WandererApp.Character.Tracker do
) do
case WandererApp.Character.get_character(character_id) do
{:ok, %{eve_id: eve_id, access_token: access_token}} when not is_nil(access_token) ->
(WandererApp.Cache.has_key?("character:#{character_id}:online_forbidden") ||
WandererApp.Cache.has_key?("character:#{character_id}:location_forbidden") ||
(WandererApp.Cache.has_key?("character:#{character_id}:location_forbidden") ||
WandererApp.Cache.has_key?("character:#{character_id}:tracking_paused"))
|> case do
true ->
@@ -424,21 +484,24 @@ defmodule WandererApp.Character.Tracker do
{:error, error} when error in [:forbidden, :not_found, :timeout] ->
Logger.warning("#{__MODULE__} failed to update_location: #{inspect(error)}")
WandererApp.Cache.put(
"character:#{character_id}:location_forbidden",
true,
ttl: @forbidden_ttl
)
if is_nil(
WandererApp.Cache.lookup!("character:#{character_id}:location_error_time")
) do
WandererApp.Cache.insert(
"character:#{character_id}:location_error_time",
DateTime.utc_now()
)
end
{:error, error}
{:error, :skipped}
{:error, :error_limited, headers} ->
reset_timeout = get_reset_timeout(headers)
Logger.warning(
"#{__MODULE__} failed to update_location: #{inspect(:error_limited)}"
)
reset_timeout = get_reset_timeout(headers, @location_limit_ttl)
WandererApp.Cache.put(
"character:#{character_id}:location_forbidden",
true,
@@ -450,22 +513,28 @@ defmodule WandererApp.Character.Tracker do
{:error, error} ->
Logger.error("#{__MODULE__} failed to update_location: #{inspect(error)}")
WandererApp.Cache.put(
"character:#{character_id}:location_forbidden",
true,
ttl: @forbidden_ttl
)
if is_nil(
WandererApp.Cache.lookup!("character:#{character_id}:location_error_time")
) do
WandererApp.Cache.insert(
"character:#{character_id}:location_error_time",
DateTime.utc_now()
)
end
{:error, error}
{:error, :skipped}
_ ->
Logger.error("#{__MODULE__} failed to update_location: wrong response")
WandererApp.Cache.put(
"character:#{character_id}:location_forbidden",
true,
ttl: @forbidden_ttl
)
if is_nil(
WandererApp.Cache.lookup!("character:#{character_id}:location_error_time")
) do
WandererApp.Cache.insert(
"character:#{character_id}:location_error_time",
DateTime.utc_now()
)
end
{:error, :skipped}
end

View File

@@ -119,7 +119,6 @@ defmodule WandererApp.Character.TrackerManager.Impl do
{:ok, character_state} =
WandererApp.Character.Tracker.update_settings(character_id, track_settings)
WandererApp.Cache.delete("character:#{character_id}:tracking_paused")
WandererApp.Character.update_character_state(character_id, character_state)
else
WandererApp.Cache.insert_or_update(

View File

@@ -16,7 +16,7 @@ defmodule WandererApp.Character.TrackerPool do
@registry :tracker_pool_registry
@unique_registry :unique_tracker_pool_registry
@update_location_interval :timer.seconds(2)
@update_location_interval :timer.seconds(1)
@update_online_interval :timer.seconds(5)
@check_online_errors_interval :timer.seconds(30)
@update_ship_interval :timer.seconds(2)
@@ -24,6 +24,8 @@ defmodule WandererApp.Character.TrackerPool do
@update_wallet_interval :timer.minutes(1)
@inactive_character_timeout :timer.minutes(5)
@pause_tracking_timeout :timer.minutes(60 * 24)
@logger Application.compile_env(:wanderer_app, :logger)
def new(), do: __struct__()
@@ -50,6 +52,12 @@ defmodule WandererApp.Character.TrackerPool do
tracked_ids
|> Enum.each(fn id ->
# WandererApp.Cache.put(
# "character:#{id}:tracking_paused",
# true,
# ttl: @pause_tracking_timeout
# )
Cachex.put(@cache, id, uuid)
end)
@@ -77,6 +85,12 @@ defmodule WandererApp.Character.TrackerPool do
[tracked_id | r_tracked_ids]
end)
# WandererApp.Cache.put(
# "character:#{tracked_id}:tracking_paused",
# true,
# ttl: @pause_tracking_timeout
# )
# Cachex.get_and_update(@cache, :tracked_characters, fn ids ->
# {:commit, ids ++ [tracked_id]}
# end)

View File

@@ -7,7 +7,7 @@ defmodule WandererApp.Character.TrackerPoolDynamicSupervisor do
@cache :tracked_characters
@registry :tracker_pool_registry
@unique_registry :unique_tracker_pool_registry
@tracker_pool_limit 100
@tracker_pool_limit 50
@name __MODULE__

View File

@@ -219,10 +219,12 @@ defmodule WandererApp.Map.Server.CharactersImpl do
Task.start_link(fn ->
character_updates =
maybe_update_online(map_id, character_id) ++
maybe_update_location(map_id, character_id) ++
maybe_update_ship(map_id, character_id) ++
maybe_update_alliance(map_id, character_id) ++
maybe_update_corporation(map_id, character_id)
maybe_update_tracking_status(map_id, character_id)
maybe_update_location(map_id, character_id) ++
maybe_update_ship(map_id, character_id) ++
maybe_update_alliance(map_id, character_id) ++
maybe_update_corporation(map_id, character_id)
character_updates
|> Enum.filter(fn update -> update != :skip end)
@@ -245,6 +247,9 @@ defmodule WandererApp.Map.Server.CharactersImpl do
{:character_online, _info} ->
:broadcast
{:character_tracking, _info} ->
:broadcast
{:character_alliance, _info} ->
WandererApp.Cache.insert_or_update(
"map_#{map_id}:invalidate_character_ids",
@@ -388,6 +393,33 @@ defmodule WandererApp.Map.Server.CharactersImpl do
end
end
defp maybe_update_tracking_status(map_id, character_id) do
with {:ok, old_tracking_paused} <-
WandererApp.Cache.lookup(
"map:#{map_id}:character:#{character_id}:tracking_paused",
false
),
{:ok, tracking_paused} <-
WandererApp.Cache.lookup("character:#{character_id}:tracking_paused", false) do
case old_tracking_paused != tracking_paused do
true ->
WandererApp.Cache.insert(
"map:#{map_id}:character:#{character_id}:tracking_paused",
tracking_paused
)
[{:character_tracking, %{tracking_paused: tracking_paused}}]
_ ->
[:skip]
end
else
error ->
Logger.error("Failed to update character_tracking: #{inspect(error, pretty: true)}")
[:skip]
end
end
defp maybe_update_ship(map_id, character_id) do
with {:ok, old_ship_type_id} <-
WandererApp.Cache.lookup("map:#{map_id}:character:#{character_id}:ship_type_id"),

View File

@@ -32,16 +32,18 @@ defmodule WandererAppWeb.MapCharactersEventHandler do
)
end
def handle_server_event(%{event: :untrack_character, payload: character_id}, %{
assigns: %{
map_id: map_id
}
} = socket) do
def handle_server_event(
%{event: :untrack_character, payload: character_id},
%{
assigns: %{
map_id: map_id
}
} = socket
) do
:ok = WandererApp.Character.TrackingUtils.untrack([%{id: character_id}], map_id, self())
socket
end
def handle_server_event(
%{event: :characters_updated},
%{
@@ -276,6 +278,24 @@ defmodule WandererAppWeb.MapCharactersEventHandler do
)}
end
def handle_ui_event(
"startTracking",
%{"character_eve_id" => character_eve_id},
%{
assigns: %{
map_id: map_id,
current_user: %{id: current_user_id}
}
} = socket
)
when not is_nil(character_eve_id) do
{:ok, character} = WandererApp.Character.get_by_eve_id("#{character_eve_id}")
WandererApp.Cache.delete("character:#{character.id}:tracking_paused")
{:noreply, socket}
end
def handle_ui_event(event, body, socket),
do: MapCoreEventHandler.handle_ui_event(event, body, socket)
@@ -295,6 +315,7 @@ defmodule WandererAppWeb.MapCharactersEventHandler do
|> Map.put(:alliance_ticker, Map.get(character, :alliance_ticker, ""))
|> Map.put_new(:ship, WandererApp.Character.get_ship(character))
|> Map.put_new(:location, get_location(character))
|> Map.put_new(:tracking_paused, character |> Map.get(:tracking_paused, false))
defp get_location(character),
do: %{

View File

@@ -33,7 +33,8 @@ defmodule WandererAppWeb.MapEventHandler do
"getCharactersTrackingInfo",
"updateCharacterTracking",
"updateFollowingCharacter",
"updateMainCharacter"
"updateMainCharacter",
"startTracking"
]
@map_system_events [

View File

@@ -3,7 +3,7 @@ defmodule WandererApp.MixProject do
@source_url "https://github.com/wanderer-industries/wanderer"
@version "1.66.11"
@version "1.66.15"
def project do
[