Compare commits

..

No commits in common. "master" and "v4.4" have entirely different histories.
master ... v4.4

99 changed files with 5360 additions and 5107 deletions

View File

@ -4,6 +4,4 @@
.gitignore
Dockerfile
.dockerignore
docker-build.sh
.vs/
.idea/

View File

@ -21,7 +21,7 @@ resharper_indent_text = ZeroIndent
csharp_style_expression_bodied_methods = true
# namespaces
csharp_style_namespace_declarations = file_scoped
csharp_style_namespace_declarations = block_scoped
# braces
csharp_prefer_braces = when_multiline

45
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,45 @@
name: dotnet build
on:
push:
paths-ignore:
- '**.md'
- 'Dockerfile'
jobs:
build:
runs-on: windows-latest
env:
DOTNET_CLI_TELEMETRY_OPTOUT: 'true'
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
steps:
- uses: actions/checkout@v3
with:
submodules: true
- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.0
- name: Download Dalamud
run: |
Invoke-WebRequest -Uri https://goatcorp.github.io/dalamud-distrib/latest.zip -OutFile latest.zip
Expand-Archive -Force latest.zip "$env:AppData\XIVLauncher\addon\Hooks\dev\"
- id: cache-dependencies
uses: actions/cache@v3
with:
path: ${{ github.workspace }}/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
restore-keys: |
${{ runner.os }}-nuget-
- name: Install dependencies
run: dotnet restore
- name: Build
run: dotnet build --configuration Release --no-restore
- name: Test
run: dotnet test --no-restore --verbosity normal
timeout-minutes: 10

31
.github/workflows/server.yml vendored Normal file
View File

@ -0,0 +1,31 @@
name: docker build
on:
push:
branches:
- master
paths:
- '.github/workflows/server.yml'
- 'Pal.Common/**'
- 'Pal.Server/**'
- 'Dockerfile'
workflow_dispatch: { }
permissions:
packages: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Login to GitHub Package Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
with:
push: true
tags: ghcr.io/${{ github.repository_owner }}/palace-pal:latest

24
.github/workflows/upload-crowdin.yml vendored Normal file
View File

@ -0,0 +1,24 @@
name: Upload to Crowdin
on:
push:
branches:
- master
paths:
- 'Pal.Client/Properties/*.resx'
- 'crowdin.yml'
workflow_dispatch: { }
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Crowdin Action
uses: crowdin/github-action@1.4.9
with:
upload_sources: true
upload_translations: true
download_translations: false
crowdin_branch_name: ${{ github.ref_name }}
env:
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}

6
.gitmodules vendored
View File

@ -1,9 +1,3 @@
[submodule "vendor/ECommons"]
path = vendor/ECommons
url = https://github.com/NightmareXIV/ECommons
[submodule "vendor/LLib"]
path = vendor/LLib
url = https://git.carvel.li/liza/LLib.git
[submodule "Server"]
path = Server
url = https://git.carvel.li/liza/PalacePal.Server.git

View File

@ -1,19 +1,13 @@
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env
ARG TARGETARCH
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env
WORKDIR /build
COPY Pal.Common/Pal.Common.csproj Pal.Common/
COPY Server/Server/Pal.Server.csproj Server/Server/
RUN dotnet restore Server/Server/Pal.Server.csproj -a $TARGETARCH
COPY Pal.Server/Pal.Server.csproj Pal.Server/
RUN dotnet restore Pal.Server/Pal.Server.csproj
COPY . ./
RUN dotnet publish Server/Server/Pal.Server.csproj -a $TARGETARCH --no-restore -o /dist
FROM mcr.microsoft.com/dotnet/aspnet:8.0
# fix later
ENV DOTNET_ROLL_FORWARD=Major
ENV DOTNET_ROLL_FORWARD_PRE_RELEASE=1
RUN dotnet publish Pal.Server/Pal.Server.csproj --configuration Release --no-restore -o /dist
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS runtime
EXPOSE 5415
ENV DOTNET_ENVIRONMENT=Production
ENV ASPNETCORE_URLS=

View File

@ -1,9 +1,10 @@
using System;
using System.Collections.Generic;
namespace Pal.Client.Commands;
namespace Pal.Client.Commands
{
public interface ISubCommand
{
IReadOnlyDictionary<string, Action<string>> GetHandlers();
}
}

View File

@ -3,8 +3,8 @@ using System.Collections.Generic;
using Pal.Client.Configuration;
using Pal.Client.Windows;
namespace Pal.Client.Commands;
namespace Pal.Client.Commands
{
internal class PalConfigCommand : ISubCommand
{
private readonly IPalacePalConfiguration _configuration;
@ -37,3 +37,4 @@ internal class PalConfigCommand : ISubCommand
_configWindow.Toggle();
}
}
}

View File

@ -1,22 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Plugin.Services;
using Dalamud.Game.ClientState;
using Pal.Client.DependencyInjection;
using Pal.Client.Extensions;
using Pal.Client.Floors;
using Pal.Client.Rendering;
namespace Pal.Client.Commands;
namespace Pal.Client.Commands
{
internal sealed class PalNearCommand : ISubCommand
{
private readonly Chat _chat;
private readonly IClientState _clientState;
private readonly ClientState _clientState;
private readonly TerritoryState _territoryState;
private readonly FloorService _floorService;
public PalNearCommand(Chat chat, IClientState clientState, TerritoryState territoryState,
public PalNearCommand(Chat chat, ClientState clientState, TerritoryState territoryState,
FloorService floorService)
{
_chat = chat;
@ -50,7 +50,7 @@ internal sealed class PalNearCommand : ISubCommand
var nearbyMarkers = state.Locations
.Where(m => predicate(m))
.Where(m => m.RenderElement != null && m.RenderElement.Enabled)
.Where(m => m.RenderElement != null && m.RenderElement.Color != RenderData.ColorInvisible)
.Select(m => new { m, distance = (playerPosition.Value - m.Position).Length() })
.OrderBy(m => m.distance)
.Take(5)
@ -60,3 +60,4 @@ internal sealed class PalNearCommand : ISubCommand
$"{nearbyMarker.distance:F2} - {nearbyMarker.m.Type} {nearbyMarker.m.NetworkId?.ToPartialId(length: 8)} - {nearbyMarker.m.Position}");
}
}
}

View File

@ -2,8 +2,8 @@
using System.Collections.Generic;
using Pal.Client.DependencyInjection;
namespace Pal.Client.Commands;
namespace Pal.Client.Commands
{
internal sealed class PalStatsCommand : ISubCommand
{
private readonly StatisticsService _statisticsService;
@ -22,3 +22,4 @@ internal sealed class PalStatsCommand : ISubCommand
private void Execute()
=> _statisticsService.ShowGlobalStatistics();
}
}

View File

@ -3,8 +3,8 @@ using System.Collections.Generic;
using ECommons.Schedulers;
using Pal.Client.Windows;
namespace Pal.Client.Commands;
namespace Pal.Client.Commands
{
internal sealed class PalTestConnectionCommand : ISubCommand
{
private readonly ConfigWindow _configWindow;
@ -27,3 +27,4 @@ internal sealed class PalTestConnectionCommand : ISubCommand
var _ = new TickScheduler(() => _configWindow.TestConnection());
}
}
}

View File

@ -4,12 +4,15 @@ using System.Security.Cryptography;
using System.Text.Json.Serialization;
using Microsoft.Extensions.Logging;
namespace Pal.Client.Configuration;
namespace Pal.Client.Configuration
{
public sealed class AccountConfigurationV7 : IAccountConfiguration
{
private const int DefaultEntropyLength = 16;
private static readonly ILogger _logger =
DependencyInjectionContext.LoggerProvider.CreateLogger<AccountConfigurationV7>();
[JsonConstructor]
public AccountConfigurationV7()
{
@ -72,8 +75,9 @@ public sealed class AccountConfigurationV7 : IAccountConfiguration
byte[] guidBytes = ProtectedData.Unprotect(Convert.FromBase64String(EncryptedId), Entropy, DataProtectionScope.CurrentUser);
return new Guid(guidBytes);
}
catch (Exception)
catch (Exception e)
{
_logger.LogTrace(e, "Could not load account id {Id}", EncryptedId);
return null;
}
}
@ -142,3 +146,4 @@ public sealed class AccountConfigurationV7 : IAccountConfiguration
ProtectedDataUnsupported = 3,
}
}
}

View File

@ -3,17 +3,19 @@ using System.Linq;
using System.Security.Cryptography;
using Microsoft.Extensions.Logging;
namespace Pal.Client.Configuration;
namespace Pal.Client.Configuration
{
internal static class ConfigurationData
{
private static readonly ILogger _logger =
DependencyInjectionContext.LoggerProvider.CreateLogger(typeof(ConfigurationData));
[Obsolete("for V1 import")]
internal static readonly byte[] FixedV1Entropy = { 0x22, 0x4b, 0xe7, 0x21, 0x44, 0x83, 0x69, 0x55, 0x80, 0x38 };
public const string ConfigFileName = "palace-pal.config.json";
private static bool? _supportsDpapi;
private static bool? _supportsDpapi = null;
public static bool SupportsDpapi
{
get
@ -32,9 +34,11 @@ internal static class ConfigurationData
{
_supportsDpapi = false;
}
}
_logger.LogTrace("DPAPI support: {Supported}", _supportsDpapi);
}
return _supportsDpapi.Value;
}
}
}
}

View File

@ -13,17 +13,17 @@ using Pal.Client.Configuration.Legacy;
using Pal.Client.Database;
using NJson = Newtonsoft.Json;
namespace Pal.Client.Configuration;
namespace Pal.Client.Configuration
{
internal sealed class ConfigurationManager
{
private readonly ILogger<ConfigurationManager> _logger;
private readonly IDalamudPluginInterface _pluginInterface;
private readonly DalamudPluginInterface _pluginInterface;
private readonly IServiceProvider _serviceProvider;
public event EventHandler<IPalacePalConfiguration>? Saved;
public ConfigurationManager(ILogger<ConfigurationManager> logger, IDalamudPluginInterface pluginInterface,
public ConfigurationManager(ILogger<ConfigurationManager> logger, DalamudPluginInterface pluginInterface,
IServiceProvider serviceProvider)
{
_logger = logger;
@ -87,9 +87,7 @@ internal sealed class ConfigurationManager
dbContext.Imports.Add(new ImportHistory
{
Id = importHistory.Id,
RemoteUrl = importHistory.RemoteUrl
?.Replace(".μ.tv", ".liza.sh")
.Replace("pal.liza.sh", "connect.palacepal.com"),
RemoteUrl = importHistory.RemoteUrl?.Replace(".μ.tv", ".liza.sh"),
ExportedAt = importHistory.ExportedAt,
ImportedAt = importHistory.ImportedAt
});
@ -100,17 +98,6 @@ internal sealed class ConfigurationManager
File.Move(_pluginInterface.ConfigFile.FullName, _pluginInterface.ConfigFile.FullName + ".old", true);
}
IPalacePalConfiguration? currentConfig = Load();
IAccountConfiguration? legacyAccount = currentConfig?.FindAccount("https://pal.liza.sh");
if (currentConfig != null && legacyAccount != null)
{
IAccountConfiguration newAccount = currentConfig.CreateAccount("https://connect.palacepal.com", legacyAccount.AccountId);
newAccount.CachedRoles = legacyAccount.CachedRoles;
currentConfig.RemoveAccount(legacyAccount.Server);
Save(currentConfig, false);
}
}
private ConfigurationV7 MigrateToV7(ConfigurationV1 v1)
@ -154,9 +141,7 @@ internal sealed class ConfigurationManager
if (string.IsNullOrEmpty(accountId))
continue;
string serverName = server
.Replace(".μ.tv", ".liza.sh")
.Replace("pal.liza.sh", "connect.palacepal.com");
string serverName = server.Replace(".μ.tv", ".liza.sh");
IAccountConfiguration newAccount = v7.CreateAccount(serverName, accountId);
newAccount.CachedRoles = oldAccount.CachedRoles.ToList();
}
@ -168,3 +153,4 @@ internal sealed class ConfigurationManager
#pragma warning restore CS0618
#pragma warning restore CS0612
}
}

View File

@ -2,8 +2,8 @@
using System.Collections.Generic;
using System.Linq;
namespace Pal.Client.Configuration;
namespace Pal.Client.Configuration
{
public sealed class ConfigurationV7 : IPalacePalConfiguration, IConfigurationInConfigDirectory
{
public int Version { get; set; } = 7;
@ -51,3 +51,4 @@ public sealed class ConfigurationV7 : IPalacePalConfiguration, IConfigurationInC
return account == null || account.CachedRoles.Contains(role);
}
}
}

View File

@ -1,5 +1,5 @@
namespace Pal.Client.Configuration;
namespace Pal.Client.Configuration
{
public enum EMode
{
/// <summary>
@ -12,3 +12,4 @@ public enum EMode
/// </summary>
Offline = 2,
}
}

View File

@ -1,5 +1,5 @@
namespace Pal.Client.Configuration;
namespace Pal.Client.Configuration
{
public enum ERenderer
{
/// <see cref="Rendering.SimpleRenderer"/>
@ -8,3 +8,4 @@ public enum ERenderer
/// <see cref="Rendering.SplatoonRenderer"/>
Splatoon = 1,
}
}

View File

@ -4,8 +4,8 @@ using System.Numerics;
using ImGuiNET;
using Newtonsoft.Json;
namespace Pal.Client.Configuration;
namespace Pal.Client.Configuration
{
public interface IVersioned
{
int Version { get; set; }
@ -108,3 +108,4 @@ public class BackupConfiguration
public int MinimumBackupsToKeep { get; set; } = 3;
public int DaysToDeleteAfter { get; set; } = 21;
}
}

View File

@ -8,8 +8,8 @@ using Dalamud.Plugin;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace Pal.Client.Configuration.Legacy;
namespace Pal.Client.Configuration.Legacy
{
[Obsolete]
public sealed class ConfigurationV1
{
@ -50,7 +50,7 @@ public sealed class ConfigurationV1
public string BetaKey { get; set; } = "";
#endregion
public void Migrate(IDalamudPluginInterface pluginInterface, ILogger<ConfigurationV1> logger)
public void Migrate(DalamudPluginInterface pluginInterface, ILogger<ConfigurationV1> logger)
{
if (Version == 1)
{
@ -137,7 +137,7 @@ public sealed class ConfigurationV1
}
}
public void Save(IDalamudPluginInterface pluginInterface)
public void Save(DalamudPluginInterface pluginInterface)
{
File.WriteAllText(pluginInterface.ConfigFile.FullName, JsonConvert.SerializeObject(this, Formatting.Indented, new JsonSerializerSettings
{
@ -164,3 +164,4 @@ public sealed class ConfigurationV1
public DateTime ImportedAt { get; set; }
}
}
}

View File

@ -7,8 +7,8 @@ using System.Text.Json;
using Pal.Client.Extensions;
using Pal.Common;
namespace Pal.Client.Configuration.Legacy;
namespace Pal.Client.Configuration.Legacy
{
/// <summary>
/// Legacy JSON file for marker locations.
/// </summary>
@ -20,6 +20,9 @@ public sealed class JsonFloorState
private static string _pluginConfigDirectory = null!;
// might not be true, but this is 'less strict filtering' for migrations
private static readonly EMode _mode = EMode.Online;
internal static void SetContextProperties(string pluginConfigDirectory)
{
_pluginConfigDirectory = pluginConfigDirectory;
@ -35,6 +38,11 @@ public sealed class JsonFloorState
private void ApplyFilters()
{
if (_mode == EMode.Offline)
Markers = new ConcurrentBag<JsonMarker>(Markers.Where(x => x.Seen || (x.WasImported && x.Imports.Count > 0)));
else
// ensure old import markers are removed if they are no longer part of a "current" import
// this MAY remove markers the server sent you (and that you haven't seen), but this should be fixed the next time you enter the zone
Markers = new ConcurrentBag<JsonMarker>(Markers.Where(x => x.Seen || !x.WasImported || x.Imports.Count > 0));
}
@ -159,3 +167,4 @@ public sealed class JsonFloorState
public HashSet<JsonMarker> Markers { get; set; } = new();
}
}
}

View File

@ -2,8 +2,8 @@
using System.Collections.Generic;
using System.Numerics;
namespace Pal.Client.Configuration.Legacy;
namespace Pal.Client.Configuration.Legacy
{
[Obsolete]
public class JsonMarker
{
@ -23,3 +23,4 @@ public class JsonMarker
Debug = 3,
}
}
}

View File

@ -12,8 +12,8 @@ using Microsoft.Extensions.Logging;
using Pal.Client.Database;
using Pal.Common;
namespace Pal.Client.Configuration.Legacy;
namespace Pal.Client.Configuration.Legacy
{
/// <summary>
/// Imports legacy territoryType.json files into the database if it exists, and no markers for that territory exist.
/// </summary>
@ -21,10 +21,10 @@ internal sealed class JsonMigration
{
private readonly ILogger<JsonMigration> _logger;
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly IDalamudPluginInterface _pluginInterface;
private readonly DalamudPluginInterface _pluginInterface;
public JsonMigration(ILogger<JsonMigration> logger, IServiceScopeFactory serviceScopeFactory,
IDalamudPluginInterface pluginInterface)
DalamudPluginInterface pluginInterface)
{
_logger = logger;
_serviceScopeFactory = serviceScopeFactory;
@ -144,3 +144,4 @@ internal sealed class JsonMigration
}
#pragma warning restore CS0612
}
}

View File

@ -6,8 +6,8 @@ using Microsoft.Extensions.Logging;
using Pal.Client.Configuration;
using Pal.Common;
namespace Pal.Client.Database;
namespace Pal.Client.Database
{
internal sealed class Cleanup
{
private readonly ILogger<Cleanup> _logger;
@ -64,3 +64,4 @@ internal sealed class Cleanup
return o => o.Source != ClientLocation.ESource.Download;
}
}
}

View File

@ -1,8 +1,8 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Pal.Client.Database;
namespace Pal.Client.Database
{
internal sealed class ClientLocation
{
[Key] public int LocalId { get; set; }
@ -56,3 +56,4 @@ internal sealed class ClientLocation
Download = 4,
}
}
}

View File

@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
namespace Pal.Client.Database;
namespace Pal.Client.Database
{
internal sealed class ImportHistory
{
public Guid Id { get; set; }
@ -12,3 +12,4 @@ internal sealed class ImportHistory
public List<ClientLocation> ImportedLocations { get; set; } = new();
}
}

View File

@ -1,7 +1,7 @@
using Microsoft.EntityFrameworkCore;
namespace Pal.Client.Database;
namespace Pal.Client.Database
{
internal class PalClientContext : DbContext
{
public DbSet<ClientLocation> Locations { get; set; } = null!;
@ -21,3 +21,4 @@ internal class PalClientContext : DbContext
.UsingEntity(o => o.ToTable("LocationImports"));
}
}
}

View File

@ -2,8 +2,8 @@
using Pal.Client.Extensions;
using Pal.Client.Net;
namespace Pal.Client.Database;
namespace Pal.Client.Database
{
/// <summary>
/// To avoid sending too many requests to the server, we cache which locations have been seen
/// locally. These never expire, and locations which have been seen with a specific account
@ -38,3 +38,4 @@ internal sealed class RemoteEncounter
AccountId = accountId.ToPartialId();
}
}
}

View File

@ -19,8 +19,8 @@ using Pal.Client.DependencyInjection;
using Pal.Client.Floors;
using Pal.Client.Windows;
namespace Pal.Client;
namespace Pal.Client
{
/// <summary>
/// Takes care of async plugin init - this is mostly everything that requires either the config or the database to
/// be available.
@ -84,7 +84,7 @@ internal sealed class DependencyContextInitializer
private async Task RemoveOldBackups()
{
await using var scope = _serviceProvider.CreateAsyncScope();
var pluginInterface = scope.ServiceProvider.GetRequiredService<IDalamudPluginInterface>();
var pluginInterface = scope.ServiceProvider.GetRequiredService<DalamudPluginInterface>();
var configuration = scope.ServiceProvider.GetRequiredService<IPalacePalConfiguration>();
var paths = Directory.GetFiles(pluginInterface.GetPluginConfigDirectory(), "backup-*.data.sqlite3",
@ -136,7 +136,7 @@ internal sealed class DependencyContextInitializer
{
await using var scope = _serviceProvider.CreateAsyncScope();
var pluginInterface = scope.ServiceProvider.GetRequiredService<IDalamudPluginInterface>();
var pluginInterface = scope.ServiceProvider.GetRequiredService<DalamudPluginInterface>();
string backupPath = Path.Join(pluginInterface.GetPluginConfigDirectory(),
$"backup-{DateTime.Now.ToUniversalTime():yyyy-MM-dd}.data.sqlite3");
string sourcePath = Path.Join(pluginInterface.GetPluginConfigDirectory(),
@ -193,3 +193,4 @@ internal sealed class DependencyContextInitializer
await dbContext.SaveChangesAsync();
}
}
}

View File

@ -1,16 +1,15 @@
using Dalamud.Game.Text;
using Dalamud.Game.Gui;
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Plugin.Services;
using ECommons.DalamudServices.Legacy;
using Pal.Client.Properties;
namespace Pal.Client.DependencyInjection;
namespace Pal.Client.DependencyInjection
{
internal sealed class Chat
{
private readonly IChatGui _chatGui;
private readonly ChatGui _chatGui;
public Chat(IChatGui chatGui)
public Chat(ChatGui chatGui)
{
_chatGui = chatGui;
}
@ -36,3 +35,4 @@ internal sealed class Chat
public void UnformattedMessage(string message)
=> _chatGui.Print(message);
}
}

View File

@ -1,25 +1,25 @@
using System;
using System.Text;
using System.Text.RegularExpressions;
using Dalamud.Data;
using Dalamud.Game.Gui;
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Plugin.Services;
using Lumina.Excel.GeneratedSheets;
using Pal.Client.Configuration;
using Pal.Client.Floors;
namespace Pal.Client.DependencyInjection;
namespace Pal.Client.DependencyInjection
{
internal sealed class ChatService : IDisposable
{
private readonly IChatGui _chatGui;
private readonly ChatGui _chatGui;
private readonly TerritoryState _territoryState;
private readonly IPalacePalConfiguration _configuration;
private readonly IDataManager _dataManager;
private readonly DataManager _dataManager;
private readonly LocalizedChatMessages _localizedChatMessages;
public ChatService(IChatGui chatGui, TerritoryState territoryState, IPalacePalConfiguration configuration,
IDataManager dataManager)
public ChatService(ChatGui chatGui, TerritoryState territoryState, IPalacePalConfiguration configuration,
DataManager dataManager)
{
_chatGui = chatGui;
_territoryState = territoryState;
@ -34,7 +34,7 @@ internal sealed class ChatService : IDisposable
public void Dispose()
=> _chatGui.ChatMessage -= OnChatMessage;
private void OnChatMessage(XivChatType type, int senderId, ref SeString sender, ref SeString seMessage,
private void OnChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString seMessage,
ref bool isHandled)
{
if (_configuration.FirstUse)
@ -82,21 +82,14 @@ internal sealed class ChatService : IDisposable
HoardNotOnCurrentFloor = GetLocalizedString(7273),
HoardCofferOpened = GetLocalizedString(7274),
FloorChanged =
new Regex("^" + GetLocalizedString(7270, true).Replace("\u0002 \u0003\ufffd\u0002\u0003", @"(\d+)") +
new Regex("^" + GetLocalizedString(7270).Replace("\u0002 \u0003\ufffd\u0002\u0003", @"(\d+)") +
"$"),
};
}
private string GetLocalizedString(uint id, bool asRawData = false)
private string GetLocalizedString(uint id)
{
var text = _dataManager.GetExcelSheet<LogMessage>()?.GetRow(id)?.Text;
if (text == null)
return "Unknown";
if (asRawData)
return Encoding.UTF8.GetString(text.RawData);
else
return text.ToString();
return _dataManager.GetExcelSheet<LogMessage>()?.GetRow(id)?.Text?.ToString() ?? "Unknown";
}
private sealed class LocalizedChatMessages
@ -114,3 +107,4 @@ internal sealed class ChatService : IDisposable
new(@"This isn't a game message, but will be replaced"); // new Regex(@"^Floor (\d+)$");
}
}
}

View File

@ -1,7 +1,7 @@
using System;
namespace Pal.Client.DependencyInjection;
namespace Pal.Client.DependencyInjection
{
internal sealed class DebugState
{
public string? DebugMessage { get; set; }
@ -12,3 +12,4 @@ internal sealed class DebugState
public void Reset()
=> DebugMessage = null;
}
}

View File

@ -4,17 +4,16 @@ using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Hooking;
using Dalamud.Memory;
using Dalamud.Plugin.Services;
using Dalamud.Utility.Signatures;
using Microsoft.Extensions.Logging;
using Pal.Client.Floors;
namespace Pal.Client.DependencyInjection;
namespace Pal.Client.DependencyInjection
{
internal sealed unsafe class GameHooks : IDisposable
{
private readonly ILogger<GameHooks> _logger;
private readonly IObjectTable _objectTable;
private readonly ObjectTable _objectTable;
private readonly TerritoryState _territoryState;
private readonly FrameworkService _frameworkService;
@ -25,7 +24,7 @@ internal sealed unsafe class GameHooks : IDisposable
private Hook<ActorVfxCreateDelegate> ActorVfxCreateHook { get; init; } = null!;
#pragma warning restore CS0649
public GameHooks(ILogger<GameHooks> logger, IObjectTable objectTable, TerritoryState territoryState, FrameworkService frameworkService, IGameInteropProvider gameInteropProvider)
public GameHooks(ILogger<GameHooks> logger, ObjectTable objectTable, TerritoryState territoryState, FrameworkService frameworkService)
{
_logger = logger;
_objectTable = objectTable;
@ -33,7 +32,7 @@ internal sealed unsafe class GameHooks : IDisposable
_frameworkService = frameworkService;
_logger.LogDebug("Initializing game hooks");
gameInteropProvider.InitializeFromAttributes(this);
SignatureHelper.Initialise(this);
ActorVfxCreateHook.Enable();
_logger.LogDebug("Game hooks initialized");
@ -81,7 +80,7 @@ internal sealed unsafe class GameHooks : IDisposable
_chat.PalPrint($"{vfxPath} on {obj}");
*/
if (obj is IBattleChara bc && (bc.NameId == /* potd */ 5042 || bc.NameId == /* hoh */ 7395))
if (obj is BattleChara bc && (bc.NameId == /* potd */ 5042 || bc.NameId == /* hoh */ 7395))
{
if (vfxPath == "vfx/common/eff/dk05th_stdn0t.avfx" || vfxPath == "vfx/common/eff/dk05ht_ipws0t.avfx")
{
@ -104,3 +103,4 @@ internal sealed unsafe class GameHooks : IDisposable
ActorVfxCreateHook.Dispose();
}
}
}

View File

@ -12,8 +12,8 @@ using Pal.Client.Floors;
using Pal.Client.Floors.Tasks;
using Pal.Common;
namespace Pal.Client.DependencyInjection;
namespace Pal.Client.DependencyInjection
{
internal sealed class ImportService
{
private readonly IServiceProvider _serviceProvider;
@ -163,3 +163,4 @@ internal sealed class ImportService
}
}
}
}

View File

@ -6,17 +6,19 @@ using Microsoft.Extensions.Logging;
using Pal.Client.Extensions;
using Pal.Client.Properties;
namespace Pal.Client.DependencyInjection;
namespace Pal.Client.DependencyInjection
{
internal sealed class RepoVerification
{
public RepoVerification(ILogger<RepoVerification> logger, IDalamudPluginInterface pluginInterface, Chat chat)
public RepoVerification(ILogger<RepoVerification> logger, DalamudPluginInterface pluginInterface, Chat chat)
{
logger.LogInformation("Install source: {Repo}", pluginInterface.SourceRepository);
if (!pluginInterface.IsDev && pluginInterface.SourceRepository.TrimEnd('/') != "https://plugins.carvel.li")
if (!pluginInterface.IsDev
&& !pluginInterface.SourceRepository.StartsWith("https://raw.githubusercontent.com/carvelli/")
&& !pluginInterface.SourceRepository.StartsWith("https://github.com/carvelli/"))
{
chat.Error(string.Format(Localization.Error_WrongRepository,
"https://plugins.carvel.li"));
"https://github.com/carvelli/Dalamud-Plugins"));
throw new RepoVerificationFailedException();
}
}
@ -25,3 +27,4 @@ internal sealed class RepoVerification
{
}
}
}

View File

@ -9,8 +9,8 @@ using Pal.Client.Net;
using Pal.Client.Properties;
using Pal.Client.Windows;
namespace Pal.Client.DependencyInjection;
namespace Pal.Client.DependencyInjection
{
internal sealed class StatisticsService
{
private readonly IPalacePalConfiguration _configuration;
@ -72,3 +72,4 @@ internal sealed class StatisticsService
}
}
}
}

View File

@ -10,7 +10,6 @@ using Dalamud.Game.Command;
using Dalamud.Game.Gui;
using Dalamud.Interface.Windowing;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
@ -26,40 +25,37 @@ using Pal.Client.Rendering;
using Pal.Client.Scheduled;
using Pal.Client.Windows;
namespace Pal.Client;
namespace Pal.Client
{
/// <summary>
/// DI-aware Plugin.
/// </summary>
internal sealed class DependencyInjectionContext : IDisposable
{
public const string DatabaseFileName = "palace-pal.data.sqlite3";
public static DalamudLoggerProvider LoggerProvider { get; } = new(typeof(Plugin).Assembly);
/// <summary>
/// Initialized as temporary logger, will be overriden once context is ready with a logger that supports scopes.
/// </summary>
private ILogger _logger;
private ILogger _logger = LoggerProvider.CreateLogger<DependencyInjectionContext>();
private readonly string _sqliteConnectionString;
private readonly ServiceCollection _serviceCollection = new();
private ServiceProvider? _serviceProvider;
public DependencyInjectionContext(
IDalamudPluginInterface pluginInterface,
IClientState clientState,
IGameGui gameGui,
IChatGui chatGui,
IObjectTable objectTable,
IFramework framework,
ICondition condition,
ICommandManager commandManager,
IDataManager dataManager,
IGameInteropProvider gameInteropProvider,
IPluginLog pluginLog,
DalamudPluginInterface pluginInterface,
ClientState clientState,
GameGui gameGui,
ChatGui chatGui,
ObjectTable objectTable,
Framework framework,
Condition condition,
CommandManager commandManager,
DataManager dataManager,
Plugin plugin)
{
var loggerProvider = new DalamudLoggerProvider(pluginLog);
_logger = loggerProvider.CreateLogger<DependencyInjectionContext>();
_logger.LogInformation("Building dalamud service container for {Assembly}",
typeof(DependencyInjectionContext).Assembly.FullName);
@ -74,7 +70,7 @@ internal sealed class DependencyInjectionContext : IDisposable
.AddFilter("Microsoft.EntityFrameworkCore.Database", LogLevel.Warning)
.AddFilter("Grpc", LogLevel.Debug)
.ClearProviders()
.AddDalamudLogger(pluginLog));
.AddDalamudLogger(plugin));
// dalamud
_serviceCollection.AddSingleton<IDalamudPlugin>(plugin);
@ -88,7 +84,6 @@ internal sealed class DependencyInjectionContext : IDisposable
_serviceCollection.AddSingleton(condition);
_serviceCollection.AddSingleton(commandManager);
_serviceCollection.AddSingleton(dataManager);
_serviceCollection.AddSingleton(gameInteropProvider);
_serviceCollection.AddSingleton(new WindowSystem(typeof(DependencyInjectionContext).AssemblyQualifiedName));
_sqliteConnectionString =
@ -192,3 +187,4 @@ internal sealed class DependencyInjectionContext : IDisposable
SqliteConnection.ClearPool(sqliteConnection);
}
}
}

View File

@ -1,7 +1,7 @@
using System;
namespace Pal.Client.Extensions;
namespace Pal.Client.Extensions
{
public static class GuidExtensions
{
public static string ToPartialId(this Guid g, int length = 13)
@ -10,3 +10,4 @@ public static class GuidExtensions
public static string ToPartialId(this string s, int length = 13)
=> s.PadRight(length + 1).Substring(0, length);
}
}

View File

@ -3,8 +3,8 @@ using System.Runtime.InteropServices;
using System.Text;
using ImGuiNET;
namespace Pal.Client.Extensions;
namespace Pal.Client.Extensions
{
internal static class PalImGui
{
/// <summary>
@ -33,3 +33,4 @@ internal static class PalImGui
choice = value;
}
}
}

View File

@ -1,7 +1,7 @@
using System;
namespace Pal.Client.Floors;
namespace Pal.Client.Floors
{
/// <summary>
/// This is a currently-visible marker.
/// </summary>
@ -26,3 +26,4 @@ internal sealed class EphemeralLocation : MemoryLocation
return $"EphemeralLocation(Position={Position}, Type={Type})";
}
}
}

View File

@ -10,8 +10,8 @@ using Pal.Client.Floors.Tasks;
using Pal.Client.Net;
using Pal.Common;
namespace Pal.Client.Floors;
namespace Pal.Client.Floors
{
internal sealed class FloorService
{
private readonly IPalacePalConfiguration _configuration;
@ -160,3 +160,4 @@ internal sealed class FloorService
}
}
}
}

View File

@ -4,8 +4,10 @@ using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Dalamud.Game;
using Dalamud.Game.ClientState;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Plugin.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Pal.Client.Configuration;
@ -16,21 +18,21 @@ using Pal.Client.Rendering;
using Pal.Client.Scheduled;
using Pal.Common;
namespace Pal.Client.Floors;
namespace Pal.Client.Floors
{
internal sealed class FrameworkService : IDisposable
{
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<FrameworkService> _logger;
private readonly IFramework _framework;
private readonly Framework _framework;
private readonly ConfigurationManager _configurationManager;
private readonly IPalacePalConfiguration _configuration;
private readonly IClientState _clientState;
private readonly ClientState _clientState;
private readonly TerritoryState _territoryState;
private readonly FloorService _floorService;
private readonly DebugState _debugState;
private readonly RenderAdapter _renderAdapter;
private readonly IObjectTable _objectTable;
private readonly ObjectTable _objectTable;
private readonly RemoteApi _remoteApi;
internal Queue<IQueueOnFrameworkThread> EarlyEventQueue { get; } = new();
@ -40,15 +42,15 @@ internal sealed class FrameworkService : IDisposable
public FrameworkService(
IServiceProvider serviceProvider,
ILogger<FrameworkService> logger,
IFramework framework,
Framework framework,
ConfigurationManager configurationManager,
IPalacePalConfiguration configuration,
IClientState clientState,
ClientState clientState,
TerritoryState territoryState,
FloorService floorService,
DebugState debugState,
RenderAdapter renderAdapter,
IObjectTable objectTable,
ObjectTable objectTable,
RemoteApi remoteApi)
{
_serviceProvider = serviceProvider;
@ -77,7 +79,7 @@ internal sealed class FrameworkService : IDisposable
private void OnSaved(object? sender, IPalacePalConfiguration? config)
=> EarlyEventQueue.Enqueue(new QueuedConfigUpdate());
private void OnUpdate(IFramework framework)
private void OnUpdate(Framework framework)
{
if (_configuration.FirstUse)
return;
@ -175,20 +177,12 @@ internal sealed class FrameworkService : IDisposable
{
foreach (var location in memoryTerritory.Locations)
{
bool isEnabled = DetermineVisibility(location, visibleLocations);
if (location.RenderElement == null)
{
if (isEnabled)
return true;
else
continue;
}
if (!location.RenderElement.IsValid)
uint desiredColor = DetermineColor(location, visibleLocations);
if (location.RenderElement == null || !location.RenderElement.IsValid)
return true;
if (location.RenderElement.Enabled != isEnabled)
location.RenderElement.Enabled = isEnabled;
if (location.RenderElement.Color != desiredColor)
location.RenderElement.Color = desiredColor;
}
}
catch (Exception e)
@ -233,12 +227,12 @@ internal sealed class FrameworkService : IDisposable
{
if (location.Type == MemoryLocation.EType.Trap)
{
CreateRenderElement(location, elements, DetermineVisibility(location, visibleMarkers),
CreateRenderElement(location, elements, DetermineColor(location, visibleMarkers),
_configuration.DeepDungeons.Traps);
}
else if (location.Type == MemoryLocation.EType.Hoard)
{
CreateRenderElement(location, elements, DetermineVisibility(location, visibleMarkers),
CreateRenderElement(location, elements, DetermineColor(location, visibleMarkers),
_configuration.DeepDungeons.HoardCoffers);
}
}
@ -259,12 +253,14 @@ internal sealed class FrameworkService : IDisposable
if (location.Type == MemoryLocation.EType.SilverCoffer &&
_configuration.DeepDungeons.SilverCoffers.Show)
{
CreateRenderElement(location, elements, true, _configuration.DeepDungeons.SilverCoffers);
CreateRenderElement(location, elements, DetermineColor(location),
_configuration.DeepDungeons.SilverCoffers);
}
else if (location.Type == MemoryLocation.EType.GoldCoffer &&
_configuration.DeepDungeons.GoldCoffers.Show)
{
CreateRenderElement(location, elements, true, _configuration.DeepDungeons.GoldCoffers);
CreateRenderElement(location, elements, DetermineColor(location),
_configuration.DeepDungeons.GoldCoffers);
}
}
@ -274,7 +270,7 @@ internal sealed class FrameworkService : IDisposable
_renderAdapter.SetLayer(ELayer.RegularCoffers, elements);
}
private bool DetermineVisibility(PersistentLocation location, IReadOnlyList<PersistentLocation> visibleLocations)
private uint DetermineColor(PersistentLocation location, IReadOnlyList<PersistentLocation> visibleLocations)
{
switch (location.Type)
{
@ -282,28 +278,34 @@ internal sealed class FrameworkService : IDisposable
when _territoryState.PomanderOfSight == PomanderState.Inactive ||
!_configuration.DeepDungeons.Traps.OnlyVisibleAfterPomander ||
visibleLocations.Any(x => x == location):
return true;
return _configuration.DeepDungeons.Traps.Color;
case MemoryLocation.EType.Hoard
when _territoryState.PomanderOfIntuition == PomanderState.Inactive ||
!_configuration.DeepDungeons.HoardCoffers.OnlyVisibleAfterPomander ||
visibleLocations.Any(x => x == location):
return true;
return _configuration.DeepDungeons.HoardCoffers.Color;
default:
return false;
return RenderData.ColorInvisible;
}
}
private void CreateRenderElement(MemoryLocation location, List<IRenderElement> elements, bool enabled,
private uint DetermineColor(EphemeralLocation location)
{
return location.Type switch
{
MemoryLocation.EType.SilverCoffer => _configuration.DeepDungeons.SilverCoffers.Color,
MemoryLocation.EType.GoldCoffer => _configuration.DeepDungeons.GoldCoffers.Color,
_ => RenderData.ColorInvisible
};
}
private void CreateRenderElement(MemoryLocation location, List<IRenderElement> elements, uint color,
MarkerConfiguration config)
{
if (!config.Show)
{
location.RenderElement = null;
return;
}
var element =
_renderAdapter.CreateElement(location.Type, location.Position, enabled, config.Color, config.Fill);
var element = _renderAdapter.CreateElement(location.Type, location.Position, color, config.Fill);
location.RenderElement = element;
elements.Add(element);
}
@ -383,7 +385,7 @@ internal sealed class FrameworkService : IDisposable
List<EphemeralLocation> ephemeralLocations = new();
for (int i = 246; i < _objectTable.Length; i++)
{
IGameObject? obj = _objectTable[i];
GameObject? obj = _objectTable[i];
if (obj == null)
continue;
@ -447,6 +449,7 @@ internal sealed class FrameworkService : IDisposable
Position = obj.Position,
Seen = true,
Source = ClientLocation.ESource.ExplodedLocally,
});
}
}
@ -462,3 +465,4 @@ internal sealed class FrameworkService : IDisposable
handler.RunIfCompatible(queued, ref recreateLayout);
}
}
}

View File

@ -5,8 +5,8 @@ using Pal.Client.Rendering;
using Pal.Common;
using Palace;
namespace Pal.Client.Floors;
namespace Pal.Client.Floors
{
/// <summary>
/// Base class for <see cref="MemoryLocation"/> and <see cref="EphemeralLocation"/>.
/// </summary>
@ -64,3 +64,4 @@ internal static class ETypeExtensions
};
}
}
}

View File

@ -5,8 +5,8 @@ using Pal.Client.Configuration;
using Pal.Client.Scheduled;
using Pal.Common;
namespace Pal.Client.Floors;
namespace Pal.Client.Floors
{
/// <summary>
/// A single set of floors loaded entirely in memory, can be e.g. POTD 51-60.
/// </summary>
@ -60,3 +60,4 @@ internal sealed class MemoryTerritory
Importing,
}
}
}

View File

@ -1,14 +1,16 @@
using System;
using System.Numerics;
using System.Runtime.InteropServices;
using Dalamud.Game.ClientState;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.ClientState.Objects.SubKinds;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Game.Gui;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using ImGuiNET;
namespace Pal.Client.Floors;
namespace Pal.Client.Floors
{
/// <summary>
/// This isn't very useful for running deep dungeons normally, but it is for plugin dev.
///
@ -18,13 +20,12 @@ internal sealed class ObjectTableDebug : IDisposable
{
public const string FeatureName = nameof(ObjectTableDebug);
private readonly IDalamudPluginInterface _pluginInterface;
private readonly IObjectTable _objectTable;
private readonly IGameGui _gameGui;
private readonly IClientState _clientState;
private readonly DalamudPluginInterface _pluginInterface;
private readonly ObjectTable _objectTable;
private readonly GameGui _gameGui;
private readonly ClientState _clientState;
public ObjectTableDebug(IDalamudPluginInterface pluginInterface, IObjectTable objectTable, IGameGui gameGui,
IClientState clientState)
public ObjectTableDebug(DalamudPluginInterface pluginInterface, ObjectTable objectTable, GameGui gameGui, ClientState clientState)
{
_pluginInterface = pluginInterface;
_objectTable = objectTable;
@ -37,9 +38,9 @@ internal sealed class ObjectTableDebug : IDisposable
private void Draw()
{
int index = 0;
foreach (IGameObject obj in _objectTable)
foreach (GameObject obj in _objectTable)
{
if (obj is IEventObj eventObj && string.IsNullOrEmpty(eventObj.Name.ToString()))
if (obj is EventObj eventObj && string.IsNullOrEmpty(eventObj.Name.ToString()))
{
++index;
int model = Marshal.ReadInt32(obj.Address + 128);
@ -51,7 +52,7 @@ internal sealed class ObjectTableDebug : IDisposable
// produce a new viewport, and skip rendering it if so
float distance = DistanceToPlayer(obj.Position);
var objectText =
$"{obj.Address.ToInt64():X}:{obj.EntityId:X}[{index}]\nkind: {obj.ObjectKind} sub: {obj.SubKind}\nmodel: {model}\nname: {obj.Name}\ndata id: {obj.DataId}";
$"{obj.Address.ToInt64():X}:{obj.ObjectId:X}[{index}]\nkind: {obj.ObjectKind} sub: {obj.SubKind}\nmodel: {model}\nname: {obj.Name}\ndata id: {obj.DataId}";
var screenPos = ImGui.GetMainViewport().Pos;
var screenSize = ImGui.GetMainViewport().Size;
@ -97,3 +98,4 @@ internal sealed class ObjectTableDebug : IDisposable
_pluginInterface.UiBuilder.Draw -= Draw;
}
}
}

View File

@ -2,8 +2,8 @@
using System.Collections.Generic;
using Pal.Client.Database;
namespace Pal.Client.Floors;
namespace Pal.Client.Floors
{
/// <summary>
/// A <see cref="ClientLocation"/> loaded in memory, with certain extra attributes as needed.
/// </summary>
@ -52,3 +52,4 @@ internal sealed class PersistentLocation : MemoryLocation
return $"PersistentLocation(Position={Position}, Type={Type})";
}
}
}

View File

@ -4,8 +4,8 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Pal.Client.Database;
namespace Pal.Client.Floors.Tasks;
namespace Pal.Client.Floors.Tasks
{
internal abstract class DbTask<T>
where T : DbTask<T>
{
@ -24,23 +24,18 @@ internal abstract class DbTask<T>
{
using var scope = _serviceScopeFactory.CreateScope();
ILogger<T> logger = scope.ServiceProvider.GetRequiredService<ILogger<T>>();
try
{
using var dbContext = scope.ServiceProvider.GetRequiredService<PalClientContext>();
Run(dbContext, logger);
}
catch (Exception e)
{
logger.LogError(e, "Failed to run DbTask");
}
}
catch (Exception)
{
// nothing we can do here but catch it, if we don't we crash the game
DependencyInjectionContext.LoggerProvider.CreateLogger<DbTask<T>>()
.LogError(e, "Failed to run DbTask");
}
});
}
protected abstract void Run(PalClientContext dbContext, ILogger<T> logger);
}
}

View File

@ -7,8 +7,8 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Pal.Client.Database;
namespace Pal.Client.Floors.Tasks;
namespace Pal.Client.Floors.Tasks
{
internal sealed class LoadTerritory : DbTask<LoadTerritory>
{
private readonly Cleanup _cleanup;
@ -76,3 +76,4 @@ internal sealed class LoadTerritory : DbTask<LoadTerritory>
};
}
}
}

View File

@ -5,8 +5,8 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Pal.Client.Database;
namespace Pal.Client.Floors.Tasks;
namespace Pal.Client.Floors.Tasks
{
internal sealed class MarkLocalSeen : DbTask<MarkLocalSeen>
{
private readonly MemoryTerritory _territory;
@ -24,8 +24,7 @@ internal sealed class MarkLocalSeen : DbTask<MarkLocalSeen>
{
lock (_territory.LockObj)
{
logger.LogInformation("Marking {Count} locations as seen locally in territory {Territory}",
_locations.Count,
logger.LogInformation("Marking {Count} locations as seen locally in territory {Territory}", _locations.Count,
_territory.TerritoryType);
List<int> localIds = _locations.Select(l => l.LocalId).Where(x => x != null).Cast<int>().ToList();
dbContext.Locations
@ -35,3 +34,4 @@ internal sealed class MarkLocalSeen : DbTask<MarkLocalSeen>
}
}
}
}

View File

@ -5,8 +5,8 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Pal.Client.Database;
namespace Pal.Client.Floors.Tasks;
namespace Pal.Client.Floors.Tasks
{
internal sealed class MarkRemoteSeen : DbTask<MarkRemoteSeen>
{
private readonly MemoryTerritory _territory;
@ -48,3 +48,4 @@ internal sealed class MarkRemoteSeen : DbTask<MarkRemoteSeen>
}
}
}
}

View File

@ -6,8 +6,8 @@ using Microsoft.Extensions.Logging;
using Pal.Client.Database;
using Pal.Common;
namespace Pal.Client.Floors.Tasks;
namespace Pal.Client.Floors.Tasks
{
internal sealed class SaveNewLocations : DbTask<SaveNewLocations>
{
private readonly MemoryTerritory _territory;
@ -74,3 +74,4 @@ internal sealed class SaveNewLocations : DbTask<SaveNewLocations>
};
}
}
}

View File

@ -1,15 +1,15 @@
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Plugin.Services;
using Dalamud.Game.ClientState;
using Dalamud.Game.ClientState.Conditions;
using Pal.Common;
namespace Pal.Client.Floors;
namespace Pal.Client.Floors
{
public sealed class TerritoryState
{
private readonly IClientState _clientState;
private readonly ICondition _condition;
private readonly ClientState _clientState;
private readonly Condition _condition;
public TerritoryState(IClientState clientState, ICondition condition)
public TerritoryState(ClientState clientState, Condition condition)
{
_clientState = clientState;
_condition = condition;
@ -23,6 +23,7 @@ public sealed class TerritoryState
_clientState.IsLoggedIn
&& _condition[ConditionFlag.InDeepDungeon]
&& typeof(ETerritoryType).IsEnumDefined(_clientState.TerritoryType);
}
public enum PomanderState
@ -32,3 +33,4 @@ public enum PomanderState
FoundOnCurrentFloor,
PomanderOfSafetyUsed,
}
}

View File

@ -4,9 +4,10 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pal.Client;
namespace Pal.Client
{
internal interface ILanguageChanged
{
void LanguageChanged();
}
}

View File

@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Pal.Client.Net;
namespace Pal.Client.Net
{
internal sealed class JwtClaims
{
[JsonPropertyName("nameid")]
@ -40,8 +42,7 @@ internal sealed class JwtClaims
payload += "=";
string content = Encoding.UTF8.GetString(Convert.FromBase64String(payload));
return JsonSerializer.Deserialize<JwtClaims>(content) ??
throw new InvalidOperationException("token deserialization returned null");
return JsonSerializer.Deserialize<JwtClaims>(content) ?? throw new InvalidOperationException("token deserialization returned null");
}
}
@ -74,6 +75,21 @@ internal sealed class JwtRoleConverter : JsonConverter<List<string>>
throw new JsonException("bad token type");
}
public override void Write(Utf8JsonWriter writer, List<string> value, JsonSerializerOptions options) =>
throw new NotImplementedException();
public override void Write(Utf8JsonWriter writer, List<string> value, JsonSerializerOptions options) => throw new NotImplementedException();
}
public sealed class JwtDateConverter : JsonConverter<DateTimeOffset>
{
static readonly DateTimeOffset Zero = new(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.Number)
throw new JsonException("bad token type");
return Zero.AddSeconds(reader.GetInt64());
}
public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) => throw new NotImplementedException();
}
}

View File

@ -1,21 +0,0 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Pal.Client.Net;
public sealed class JwtDateConverter : JsonConverter<DateTimeOffset>
{
static readonly DateTimeOffset Zero = new(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.Number)
throw new JsonException("bad token type");
return Zero.AddSeconds(reader.GetInt64());
}
public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) =>
throw new NotImplementedException();
}

View File

@ -11,13 +11,11 @@ using Microsoft.Extensions.Logging;
using Pal.Client.Configuration;
using Pal.Client.Extensions;
using Pal.Client.Properties;
using Version = System.Version;
namespace Pal.Client.Net;
namespace Pal.Client.Net
{
internal partial class RemoteApi
{
private static readonly Version PluginVersion = typeof(Plugin).Assembly.GetName().Version!;
private readonly SemaphoreSlim _connectLock = new(1, 1);
private async Task<(bool Success, string Error)> TryConnect(CancellationToken cancellationToken,
@ -75,14 +73,7 @@ internal partial class RemoteApi
if (configuredAccount == null)
{
_logger.LogInformation("No account information saved for {Url}, creating new account", RemoteUrl);
var createAccountReply = await accountClient.CreateAccountAsync(new CreateAccountRequest
{
Version = new()
{
Major = PluginVersion.Major,
Minor = PluginVersion.Minor,
},
},
var createAccountReply = await accountClient.CreateAccountAsync(new CreateAccountRequest(),
headers: UnauthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10),
cancellationToken: cancellationToken);
if (createAccountReply.Success)
@ -124,15 +115,7 @@ internal partial class RemoteApi
_logger.LogInformation("Logging in with account id {AccountId}",
configuredAccount.AccountId.ToPartialId());
LoginReply loginReply = await accountClient.LoginAsync(
new LoginRequest
{
AccountId = configuredAccount.AccountId.ToString(),
Version = new()
{
Major = PluginVersion.Major,
Minor = PluginVersion.Minor,
},
},
new LoginRequest { AccountId = configuredAccount.AccountId.ToString() },
headers: UnauthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10),
cancellationToken: cancellationToken);
@ -246,3 +229,4 @@ internal partial class RemoteApi
public bool IsValid => IsLoggedIn && !IsExpired;
}
}
}

View File

@ -3,8 +3,8 @@ using System.Threading;
using System.Threading.Tasks;
using Export;
namespace Pal.Client.Net;
namespace Pal.Client.Net
{
internal partial class RemoteApi
{
public async Task<(bool, ExportRoot)> DoExport(CancellationToken cancellationToken = default)
@ -16,8 +16,8 @@ internal partial class RemoteApi
var exportReply = await exportClient.ExportAsync(new ExportRequest
{
ServerUrl = RemoteUrl,
}, headers: AuthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(120),
cancellationToken: cancellationToken);
}, headers: AuthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(120), cancellationToken: cancellationToken);
return (exportReply.Success, exportReply.Data);
}
}
}

View File

@ -8,25 +8,21 @@ using Pal.Client.Database;
using Pal.Client.Floors;
using Palace;
namespace Pal.Client.Net;
namespace Pal.Client.Net
{
internal partial class RemoteApi
{
public async Task<(bool, List<PersistentLocation>)> DownloadRemoteMarkers(ushort territoryId,
CancellationToken cancellationToken = default)
public async Task<(bool, List<PersistentLocation>)> DownloadRemoteMarkers(ushort territoryId, CancellationToken cancellationToken = default)
{
if (!await Connect(cancellationToken))
return (false, new());
var palaceClient = new PalaceService.PalaceServiceClient(_channel);
var downloadReply = await palaceClient.DownloadFloorsAsync(
new DownloadFloorsRequest { TerritoryType = territoryId }, headers: AuthorizedHeaders(),
cancellationToken: cancellationToken);
var downloadReply = await palaceClient.DownloadFloorsAsync(new DownloadFloorsRequest { TerritoryType = territoryId }, headers: AuthorizedHeaders(), cancellationToken: cancellationToken);
return (downloadReply.Success, downloadReply.Objects.Select(CreateLocationFromNetworkObject).ToList());
}
public async Task<(bool, List<PersistentLocation>)> UploadLocations(ushort territoryType,
IReadOnlyList<PersistentLocation> locations, CancellationToken cancellationToken = default)
public async Task<(bool, List<PersistentLocation>)> UploadLocations(ushort territoryType, IReadOnlyList<PersistentLocation> locations, CancellationToken cancellationToken = default)
{
if (locations.Count == 0)
return (true, new());
@ -46,13 +42,11 @@ internal partial class RemoteApi
Y = m.Position.Y,
Z = m.Position.Z
}));
var uploadReply = await palaceClient.UploadFloorsAsync(uploadRequest, headers: AuthorizedHeaders(),
cancellationToken: cancellationToken);
var uploadReply = await palaceClient.UploadFloorsAsync(uploadRequest, headers: AuthorizedHeaders(), cancellationToken: cancellationToken);
return (uploadReply.Success, uploadReply.Objects.Select(CreateLocationFromNetworkObject).ToList());
}
public async Task<bool> MarkAsSeen(ushort territoryType, IReadOnlyList<PersistentLocation> locations,
CancellationToken cancellationToken = default)
public async Task<bool> MarkAsSeen(ushort territoryType, IReadOnlyList<PersistentLocation> locations, CancellationToken cancellationToken = default)
{
if (locations.Count == 0)
return true;
@ -65,8 +59,7 @@ internal partial class RemoteApi
foreach (var marker in locations)
seenRequest.NetworkIds.Add(marker.NetworkId.ToString());
var seenReply = await palaceClient.MarkObjectsSeenAsync(seenRequest, headers: AuthorizedHeaders(),
deadline: DateTime.UtcNow.AddSeconds(10), cancellationToken: cancellationToken);
var seenReply = await palaceClient.MarkObjectsSeenAsync(seenRequest, headers: AuthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10), cancellationToken: cancellationToken);
return seenReply.Success;
}
@ -87,9 +80,8 @@ internal partial class RemoteApi
return new(false, new List<FloorStatistics>());
var palaceClient = new PalaceService.PalaceServiceClient(_channel);
var statisticsReply = await palaceClient.FetchStatisticsAsync(new StatisticsRequest(),
headers: AuthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(30),
cancellationToken: cancellationToken);
var statisticsReply = await palaceClient.FetchStatisticsAsync(new StatisticsRequest(), headers: AuthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(30), cancellationToken: cancellationToken);
return (statisticsReply.Success, statisticsReply.FloorStatistics.ToList());
}
}
}

View File

@ -5,8 +5,8 @@ using Dalamud.Logging;
using Grpc.Core;
using Microsoft.Extensions.Logging;
namespace Pal.Client.Net;
namespace Pal.Client.Net
{
internal partial class RemoteApi
{
private Metadata UnauthorizedHeaders() => new()
@ -55,3 +55,4 @@ internal partial class RemoteApi
#endif
}
}
}

View File

@ -6,14 +6,14 @@ using Microsoft.Extensions.Logging;
using Pal.Client.Configuration;
using Pal.Client.DependencyInjection;
namespace Pal.Client.Net;
namespace Pal.Client.Net
{
internal sealed partial class RemoteApi : IDisposable
{
#if DEBUG
public const string RemoteUrl = "http://localhost:5415";
#else
public const string RemoteUrl = "https://connect.palacepal.com";
public const string RemoteUrl = "https://pal.liza.sh";
#endif
private readonly string _userAgent =
$"{typeof(RemoteApi).Assembly.GetName().Name?.Replace(" ", "")}/{typeof(RemoteApi).Assembly.GetName().Version?.ToString(2)}";
@ -49,3 +49,4 @@ internal sealed partial class RemoteApi : IDisposable
_channel = null;
}
}
}

View File

@ -1,14 +1,28 @@
<Project Sdk="Dalamud.NET.Sdk/9.0.2">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Version>6.0</Version>
<AssemblyName>Palace Pal</AssemblyName>
<PlatformTarget>x64</PlatformTarget>
<TargetFramework>net7.0-windows</TargetFramework>
<LangVersion>11.0</LangVersion>
<Nullable>enable</Nullable>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<Import Project="..\vendor\LLib\LLib.targets"/>
<Import Project="..\vendor\LLib\RenameZip.targets"/>
<PropertyGroup>
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
<PlatformTarget>x64</PlatformTarget>
<AssemblyName>Palace Pal</AssemblyName>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DebugType>portable</DebugType>
<PathMap Condition="$(SolutionDir) != ''">$(SolutionDir)=X:\</PathMap>
<GitVersion>false</GitVersion>
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
<GenerateAssemblyInformationalVersionAttribute>false</GenerateAssemblyInformationalVersionAttribute>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<OutputPath>dist</OutputPath>
@ -23,26 +37,29 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Dalamud.Extensions.MicrosoftLogging" Version="4.0.1"/>
<PackageReference Include="Google.Protobuf" Version="3.27.2" />
<PackageReference Include="Grpc.Net.Client" Version="2.63.0"/>
<PackageReference Include="Grpc.Tools" Version="2.64.0">
<PackageReference Include="DalamudPackager" Version="2.1.11"/>
<PackageReference Include="Dalamud.Extensions.MicrosoftLogging" Version="1.0.0"/>
<PackageReference Include="Google.Protobuf" Version="3.22.1"/>
<PackageReference Include="Grpc.Net.Client" Version="2.52.0"/>
<PackageReference Include="GitInfo" Version="2.3.0">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Grpc.Tools" Version="2.53.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.6" Condition="'$(Configuration)' == 'EF'">
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.4"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0"/>
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="8.0.0"/>
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0"/>
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="7.0.1"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Pal.Common\Pal.Common.csproj"/>
<ProjectReference Include="..\vendor\ECommons\ECommons\ECommons.csproj"/>
<ProjectReference Include="..\vendor\LLib\LLib.csproj" />
</ItemGroup>
<ItemGroup>
@ -51,6 +68,42 @@
<Protobuf Include="..\Pal.Common\Protos\export.proto" Link="Protos\export.proto" GrpcServices="Client" Access="Internal"/>
</ItemGroup>
<ItemGroup>
<!--You may need to adjust these paths yourself. These point to a Dalamud assembly in AppData.-->
<Reference Include="Dalamud">
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Dalamud.dll</HintPath>
<Private Condition="'$(Configuration)' != 'EF'">false</Private>
</Reference>
<Reference Include="ImGui.NET">
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\ImGui.NET.dll</HintPath>
<Private Condition="'$(Configuration)' != 'EF'">false</Private>
</Reference>
<Reference Include="ImGuiScene">
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\ImGuiScene.dll</HintPath>
<Private Condition="'$(Configuration)' != 'EF'">false</Private>
</Reference>
<Reference Include="Lumina">
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Lumina.dll</HintPath>
<Private Condition="'$(Configuration)' != 'EF'">false</Private>
</Reference>
<Reference Include="Lumina.Excel">
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Lumina.Excel.dll</HintPath>
<Private Condition="'$(Configuration)' != 'EF'">false</Private>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Newtonsoft.Json.dll</HintPath>
<Private Condition="'$(Configuration)' != 'EF'">false</Private>
</Reference>
<Reference Include="FFXIVClientStructs">
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\FFXIVClientStructs.dll</HintPath>
<Private Condition="'$(Configuration)' != 'EF'">false</Private>
</Reference>
<Reference Include="Serilog">
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Serilog.dll</HintPath>
<Private Condition="'$(Configuration)' != 'EF'">false</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Localization.resx">
<Generator>ResXFileCodeGenerator</Generator>
@ -63,6 +116,17 @@
</Compile>
</ItemGroup>
<Target Name="PopulateInfo" DependsOnTargets="GitVersion" BeforeTargets="GetAssemblyVersion;GenerateNuspec;GetPackageContents">
<PropertyGroup>
<Version>$(GitSemVerMajor).$(GitSemVerMinor)</Version>
<PackageVersion>$(Version)</PackageVersion>
</PropertyGroup>
</Target>
<Target Name="RenameLatestZip" AfterTargets="PackagePlugin" Condition="'$(Configuration)' == 'Release'">
<Exec Command="rename &quot;$(OutDir)$(AssemblyName)\latest.zip&quot; &quot;$(AssemblyName)-$(Version).zip&quot;"/>
</Target>
<Target Name="Clean">
<RemoveDir Directories="dist"/>
</Target>

View File

@ -3,8 +3,8 @@
"Author": "Liza Carvelli",
"Punchline": "Shows possible trap & hoard coffer locations in Palace of the Dead & Heaven on High.",
"Description": "Shows possible trap & hoard coffer locations in Palace of the Dead & Heaven on High.\n\nThe default configuration requires Splatoon to be installed. If you do not wish to install Splatoon, you can switch to the experimental 'Simple' renderer in the configuration.",
"RepoUrl": "https://git.carvel.li/liza/PalacePal",
"IconUrl": "https://plugins.carvel.li/icons/PalacePal.png",
"RepoUrl": "https://github.com/carvelli/PalacePal",
"IconUrl": "https://raw.githubusercontent.com/carvelli/Dalamud-Plugins/master/dist/Palace Pal.png",
"Tags": [
"potd",
"palace",

View File

@ -5,11 +5,12 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Dalamud.Extensions.MicrosoftLogging;
using Dalamud.Game;
using Dalamud.Game.ClientState;
using Dalamud.Game.Command;
using Dalamud.Game.Gui;
using Dalamud.Interface.Windowing;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using ECommons;
using ECommons.DalamudServices;
using Microsoft.Extensions.DependencyInjection;
@ -20,8 +21,8 @@ using Pal.Client.DependencyInjection;
using Pal.Client.Properties;
using Pal.Client.Rendering;
namespace Pal.Client;
namespace Pal.Client
{
/// <summary>
/// With all DI logic elsewhere, this plugin shell really only takes care of a few things around events that
/// need to be sent to different receivers depending on priority or configuration .
@ -31,35 +32,33 @@ internal sealed class Plugin : IDalamudPlugin
{
private readonly CancellationTokenSource _initCts = new();
private readonly IDalamudPluginInterface _pluginInterface;
private readonly ICommandManager _commandManager;
private readonly IClientState _clientState;
private readonly IChatGui _chatGui;
private readonly IFramework _framework;
private readonly DalamudPluginInterface _pluginInterface;
private readonly CommandManager _commandManager;
private readonly ClientState _clientState;
private readonly ChatGui _chatGui;
private readonly Framework _framework;
private readonly TaskCompletionSource<IServiceScope> _rootScopeCompletionSource = new();
private ELoadState _loadState = ELoadState.Initializing;
private DependencyInjectionContext? _dependencyInjectionContext;
private ILogger _logger;
private ILogger _logger = DependencyInjectionContext.LoggerProvider.CreateLogger<Plugin>();
private WindowSystem? _windowSystem;
private IServiceScope? _rootScope;
private Action? _loginAction;
public Plugin(
IDalamudPluginInterface pluginInterface,
ICommandManager commandManager,
IClientState clientState,
IChatGui chatGui,
IFramework framework,
IPluginLog pluginLog)
DalamudPluginInterface pluginInterface,
CommandManager commandManager,
ClientState clientState,
ChatGui chatGui,
Framework framework)
{
_pluginInterface = pluginInterface;
_commandManager = commandManager;
_clientState = clientState;
_chatGui = chatGui;
_framework = framework;
_logger = new DalamudLoggerProvider(pluginLog).CreateLogger<Plugin>();
// set up the current UI language before creating anything
Localization.Culture = new CultureInfo(_pluginInterface.UiLanguage);
@ -76,6 +75,8 @@ internal sealed class Plugin : IDalamudPlugin
Task.Run(async () => await CreateDependencyContext());
}
public string Name => Localization.Palace_Pal;
private async Task CreateDependencyContext()
{
try
@ -133,7 +134,7 @@ internal sealed class Plugin : IDalamudPlugin
_loginAction = loginAction;
}
private void Login()
private void Login(object? sender, EventArgs eventArgs)
{
_loginAction?.Invoke();
_loginAction = null;
@ -233,3 +234,4 @@ internal sealed class Plugin : IDalamudPlugin
Error
}
}
}

View File

@ -0,0 +1,8 @@
using System.Reflection;
[assembly: AssemblyVersion(ThisAssembly.Git.SemVer.Major + "." + ThisAssembly.Git.SemVer.Minor)]
[assembly: AssemblyFileVersion(ThisAssembly.Git.SemVer.Major + "." + ThisAssembly.Git.SemVer.Minor)]
[assembly: AssemblyInformationalVersion(
ThisAssembly.Git.SemVer.Major + "." +
ThisAssembly.Git.SemVer.Minor + "+" +
ThisAssembly.Git.Commit)]

View File

@ -15,7 +15,6 @@ dotnet ef migrations add MigrationName --configuration EF
```
To rebuild the compiled model:
```shell
dotnet ef dbcontext optimize --output-dir Database/Compiled --namespace Pal.Client.Database.Compiled --configuration EF
```

View File

@ -1,8 +1,9 @@
namespace Pal.Client.Rendering;
namespace Pal.Client.Rendering
{
internal enum ELayer
{
TrapHoard,
RegularCoffers,
Test,
}
}

View File

@ -1,8 +1,9 @@
namespace Pal.Client.Rendering;
namespace Pal.Client.Rendering
{
public interface IRenderElement
{
bool IsValid { get; }
bool Enabled { get; set; }
uint Color { get; set; }
}
}

View File

@ -3,8 +3,8 @@ using System.Numerics;
using Pal.Client.Configuration;
using Pal.Client.Floors;
namespace Pal.Client.Rendering;
namespace Pal.Client.Rendering
{
internal interface IRenderer
{
ERenderer GetConfigValue();
@ -13,7 +13,8 @@ internal interface IRenderer
void ResetLayer(ELayer layer);
IRenderElement CreateElement(MemoryLocation.EType type, Vector3 pos, bool enabled, uint color, bool fill = false);
IRenderElement CreateElement(MemoryLocation.EType type, Vector3 pos, uint color, bool fill = false);
void DrawDebugItems(uint trapColor, uint hoardColor);
}
}

View File

@ -1,8 +1,8 @@
using System.Collections.Generic;
using Pal.Client.Floors;
namespace Pal.Client.Rendering;
namespace Pal.Client.Rendering
{
internal sealed class MarkerConfig
{
private static readonly MarkerConfig EmptyConfig = new();
@ -21,3 +21,4 @@ internal sealed class MarkerConfig
public static MarkerConfig ForType(MemoryLocation.EType type) =>
MarkerConfigs.GetValueOrDefault(type, EmptyConfig);
}
}

View File

@ -6,8 +6,8 @@ using Microsoft.Extensions.Logging;
using Pal.Client.Configuration;
using Pal.Client.Floors;
namespace Pal.Client.Rendering;
namespace Pal.Client.Rendering
{
internal sealed class RenderAdapter : IRenderer, IDisposable
{
private readonly IServiceScopeFactory _serviceScopeFactory;
@ -60,9 +60,8 @@ internal sealed class RenderAdapter : IRenderer, IDisposable
public void ResetLayer(ELayer layer)
=> _implementation.ResetLayer(layer);
public IRenderElement CreateElement(MemoryLocation.EType type, Vector3 pos, bool enabled, uint color,
bool fill = false)
=> _implementation.CreateElement(type, pos, enabled, color, fill);
public IRenderElement CreateElement(MemoryLocation.EType type, Vector3 pos, uint color, bool fill = false)
=> _implementation.CreateElement(type, pos, color, fill);
public ERenderer GetConfigValue()
=> throw new NotImplementedException();
@ -76,3 +75,4 @@ internal sealed class RenderAdapter : IRenderer, IDisposable
sr.DrawLayers();
}
}
}

View File

@ -1,6 +1,8 @@
namespace Pal.Client.Rendering;
namespace Pal.Client.Rendering
{
internal static class RenderData
{
public static readonly uint ColorInvisible = 0;
public static readonly long TestLayerTimeout = 10_000;
}
}

View File

@ -3,14 +3,16 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Dalamud.Interface.Utility;
using Dalamud.Plugin.Services;
using Dalamud.Game.ClientState;
using Dalamud.Game.Gui;
using Dalamud.Interface;
using ImGuiNET;
using Pal.Client.Configuration;
using Pal.Client.DependencyInjection;
using Pal.Client.Floors;
namespace Pal.Client.Rendering;
namespace Pal.Client.Rendering
{
/// <summary>
/// Simple renderer that only draws basic stuff.
///
@ -22,13 +24,13 @@ internal sealed class SimpleRenderer : IRenderer, IDisposable
{
private const int SegmentCount = 20;
private readonly IClientState _clientState;
private readonly IGameGui _gameGui;
private readonly ClientState _clientState;
private readonly GameGui _gameGui;
private readonly IPalacePalConfiguration _configuration;
private readonly TerritoryState _territoryState;
private readonly ConcurrentDictionary<ELayer, SimpleLayer> _layers = new();
public SimpleRenderer(IClientState clientState, IGameGui gameGui, IPalacePalConfiguration configuration,
public SimpleRenderer(ClientState clientState, GameGui gameGui, IPalacePalConfiguration configuration,
TerritoryState territoryState)
{
_clientState = clientState;
@ -52,15 +54,13 @@ internal sealed class SimpleRenderer : IRenderer, IDisposable
l.Dispose();
}
public IRenderElement CreateElement(MemoryLocation.EType type, Vector3 pos, bool enabled, uint color,
bool fill = false)
public IRenderElement CreateElement(MemoryLocation.EType type, Vector3 pos, uint color, bool fill = false)
{
var config = MarkerConfig.ForType(type);
return new SimpleElement
{
Type = type,
Position = pos + new Vector3(0, config.OffsetY, 0),
Enabled = enabled,
Color = color,
Radius = config.Radius,
Fill = fill,
@ -77,12 +77,10 @@ internal sealed class SimpleRenderer : IRenderer, IDisposable
(SimpleElement)CreateElement(
MemoryLocation.EType.Trap,
_clientState.LocalPlayer?.Position ?? default,
true,
trapColor),
(SimpleElement)CreateElement(
MemoryLocation.EType.Hoard,
_clientState.LocalPlayer?.Position ?? default,
true,
hoardColor)
},
ExpiresAt = Environment.TickCount64 + RenderData.TestLayerTimeout
@ -122,7 +120,7 @@ internal sealed class SimpleRenderer : IRenderer, IDisposable
private void Draw(SimpleElement e)
{
if (!e.Enabled)
if (e.Color == RenderData.ColorInvisible)
return;
switch (e.Type)
@ -183,7 +181,7 @@ internal sealed class SimpleRenderer : IRenderer, IDisposable
public required IReadOnlyList<SimpleElement> Elements { get; init; }
public long ExpiresAt { get; init; } = long.MaxValue;
public bool IsValid(IClientState clientState) =>
public bool IsValid(ClientState clientState) =>
TerritoryType == clientState.TerritoryType && ExpiresAt >= Environment.TickCount64;
public void Dispose()
@ -198,9 +196,9 @@ internal sealed class SimpleRenderer : IRenderer, IDisposable
public bool IsValid { get; set; } = true;
public required MemoryLocation.EType Type { get; init; }
public required Vector3 Position { get; init; }
public required bool Enabled { get; set; }
public required uint Color { get; set; }
public required float Radius { get; init; }
public required bool Fill { get; init; }
}
}
}

View File

@ -4,8 +4,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Reflection;
using Dalamud.Game.ClientState;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using ECommons;
using ECommons.Reflection;
using ECommons.Schedulers;
@ -15,23 +15,23 @@ using Pal.Client.Configuration;
using Pal.Client.DependencyInjection;
using Pal.Client.Floors;
namespace Pal.Client.Rendering;
namespace Pal.Client.Rendering
{
internal sealed class SplatoonRenderer : IRenderer, IDisposable
{
private const long OnTerritoryChange = -2;
private readonly ILogger<SplatoonRenderer> _logger;
private readonly DebugState _debugState;
private readonly IClientState _clientState;
private readonly ClientState _clientState;
private readonly Chat _chat;
public SplatoonRenderer(
ILogger<SplatoonRenderer> logger,
IDalamudPluginInterface pluginInterface,
DalamudPluginInterface pluginInterface,
IDalamudPlugin dalamudPlugin,
DebugState debugState,
IClientState clientState,
ClientState clientState,
Chat chat)
{
_logger = logger;
@ -80,7 +80,7 @@ internal sealed class SplatoonRenderer : IRenderer, IDisposable
private string ToLayerName(ELayer layer)
=> $"PalacePal.{layer}";
public IRenderElement CreateElement(MemoryLocation.EType type, Vector3 pos, bool enabled, uint color, bool fill = false)
public IRenderElement CreateElement(MemoryLocation.EType type, Vector3 pos, uint color, bool fill = false)
{
MarkerConfig config = MarkerConfig.ForType(type);
Element element = new Element(ElementType.CircleAtFixedCoordinates)
@ -96,7 +96,6 @@ internal sealed class SplatoonRenderer : IRenderer, IDisposable
FillStep = 1,
color = color,
thicc = 2,
Enabled = enabled,
};
return new SplatoonElement(this, element);
}
@ -112,8 +111,8 @@ internal sealed class SplatoonRenderer : IRenderer, IDisposable
var elements = new List<IRenderElement>
{
CreateElement(MemoryLocation.EType.Trap, pos.Value, true, trapColor),
CreateElement(MemoryLocation.EType.Hoard, pos.Value, true, hoardColor),
CreateElement(MemoryLocation.EType.Trap, pos.Value, trapColor),
CreateElement(MemoryLocation.EType.Hoard, pos.Value, hoardColor),
};
if (!Splatoon.AddDynamicElements(ToLayerName(ELayer.Test),
@ -187,10 +186,11 @@ internal sealed class SplatoonRenderer : IRenderer, IDisposable
public bool IsValid => !_renderer.IsDisposed && Delegate.IsValid();
public bool Enabled
public uint Color
{
get => Delegate.Enabled;
set => Delegate.Enabled = value;
get => Delegate.color;
set => Delegate.color = value;
}
}
}
}

View File

@ -2,8 +2,8 @@
using Dalamud.Logging;
using Microsoft.Extensions.Logging;
namespace Pal.Client.Scheduled;
namespace Pal.Client.Scheduled
{
internal interface IQueueOnFrameworkThread
{
internal interface IHandler
@ -37,3 +37,4 @@ internal interface IQueueOnFrameworkThread
}
}
}
}

View File

@ -4,8 +4,8 @@ using Pal.Client.DependencyInjection;
using Pal.Client.Floors;
using Pal.Client.Rendering;
namespace Pal.Client.Scheduled;
namespace Pal.Client.Scheduled
{
internal sealed class QueuedConfigUpdate : IQueueOnFrameworkThread
{
internal sealed class Handler : IQueueOnFrameworkThread.Handler<QueuedConfigUpdate>
@ -26,3 +26,4 @@ internal sealed class QueuedConfigUpdate : IQueueOnFrameworkThread
}
}
}
}

View File

@ -10,8 +10,8 @@ using Pal.Client.Properties;
using Pal.Client.Windows;
using Pal.Common;
namespace Pal.Client.Scheduled;
namespace Pal.Client.Scheduled
{
internal sealed class QueuedImport : IQueueOnFrameworkThread
{
private ExportRoot Export { get; }
@ -120,3 +120,4 @@ internal sealed class QueuedImport : IQueueOnFrameworkThread
}
}
}
}

View File

@ -11,8 +11,8 @@ using Pal.Client.Floors.Tasks;
using Pal.Client.Net;
using Pal.Common;
namespace Pal.Client.Scheduled;
namespace Pal.Client.Scheduled
{
internal sealed class QueuedSyncResponse : IQueueOnFrameworkThread
{
public required SyncType Type { get; init; }
@ -158,3 +158,4 @@ public enum SyncType
Download,
MarkSeen,
}
}

View File

@ -7,8 +7,8 @@ using Pal.Client.Floors;
using Pal.Client.Windows;
using Pal.Common;
namespace Pal.Client.Scheduled;
namespace Pal.Client.Scheduled
{
internal sealed class QueuedUndoImport : IQueueOnFrameworkThread
{
public QueuedUndoImport(Guid exportId)
@ -39,3 +39,4 @@ internal sealed class QueuedUndoImport : IQueueOnFrameworkThread
}
}
}
}

View File

@ -8,8 +8,8 @@ using Pal.Client.Configuration;
using Pal.Client.Extensions;
using Pal.Client.Properties;
namespace Pal.Client.Windows;
namespace Pal.Client.Windows
{
internal sealed class AgreementWindow : Window, IDisposable, ILanguageChanged
{
private const string WindowId = "###PalPalaceAgreement";
@ -99,6 +99,7 @@ internal sealed class AgreementWindow : Window, IDisposable, ILanguageChanged
ImGui.Separator();
if (ImGui.Button(Localization.Agreement_ViewPluginAndServerSourceCode))
GenericHelpers.ShellStart("https://git.carvel.li/liza/PalacePal");
GenericHelpers.ShellStart("https://github.com/carvelli/PalPalace");
}
}
}

View File

@ -12,8 +12,6 @@ using ECommons;
using Export;
using Google.Protobuf;
using ImGuiNET;
using LLib;
using LLib.ImGui;
using Microsoft.Extensions.Logging;
using Pal.Client.Configuration;
using Pal.Client.Database;
@ -25,9 +23,9 @@ using Pal.Client.Properties;
using Pal.Client.Rendering;
using Pal.Client.Scheduled;
namespace Pal.Client.Windows;
internal sealed class ConfigWindow : LWindow, ILanguageChanged, IDisposable
namespace Pal.Client.Windows
{
internal sealed class ConfigWindow : Window, ILanguageChanged, IDisposable
{
private const string WindowId = "###PalPalaceConfig";
@ -99,12 +97,6 @@ internal sealed class ConfigWindow : LWindow, ILanguageChanged, IDisposable
Position = new Vector2(300, 300);
PositionCondition = ImGuiCond.FirstUseEver;
SizeConstraints = new WindowSizeConstraints
{
MinimumSize = new Vector2(300, 300),
MaximumSize = new Vector2(9999, 9999),
};
_importDialog = new FileDialogManager
{ AddedWindowFlags = ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoDocking };
_exportDialog = new FileDialogManager
@ -292,13 +284,11 @@ internal sealed class ConfigWindow : LWindow, ILanguageChanged, IDisposable
ImGui.TextWrapped(Localization.Config_ImportExplanation1);
ImGui.TextWrapped(Localization.Config_ImportExplanation2);
ImGui.TextWrapped(Localization.Config_ImportExplanation3);
/* FIXME
ImGui.Separator();
ImGui.TextWrapped(string.Format(Localization.Config_ImportDownloadLocation,
"https://github.com/carvelli/PalacePal/releases/"));
if (ImGui.Button(Localization.Config_Import_VisitGitHub))
GenericHelpers.ShellStart("https://github.com/carvelli/PalacePal/releases/latest");
*/
ImGui.Separator();
ImGui.Text(Localization.Config_SelectImportFile);
ImGui.SameLine();
@ -586,3 +576,4 @@ internal sealed class ConfigWindow : LWindow, ILanguageChanged, IDisposable
}
}
}
}

View File

@ -8,8 +8,8 @@ using Pal.Client.Properties;
using Pal.Common;
using Palace;
namespace Pal.Client.Windows;
namespace Pal.Client.Windows
{
internal sealed class StatisticsWindow : Window, IDisposable, ILanguageChanged
{
private const string WindowId = "###PalacePalStats";
@ -123,3 +123,4 @@ internal sealed class StatisticsWindow : Window, IDisposable, ILanguageChanged
}
}
}
}

View File

@ -1,302 +1,280 @@
{
"version": 1,
"dependencies": {
"net8.0-windows7.0": {
"net7.0-windows7.0": {
"Dalamud.Extensions.MicrosoftLogging": {
"type": "Direct",
"requested": "[4.0.1, )",
"resolved": "4.0.1",
"contentHash": "fMEL2ajtF/30SBBku7vMyG0yye5eHN/A9fgT//1CEjUth/Wz2CYco5Ehye21T8KN1IuAPwoqJuu49rB71j+8ug==",
"requested": "[1.0.0, )",
"resolved": "1.0.0",
"contentHash": "nPjMrT9n9GJ+TYF1lyVhlvhmFyN4ajMX2ccclgyMc8MNpOGZwxrJ4VEtrUUk7UkuX2wAhtnNsjrcf5sER3/CbA==",
"dependencies": {
"Microsoft.Extensions.Logging": "8.0.0"
"Microsoft.Extensions.Logging": "7.0.0"
}
},
"DalamudPackager": {
"type": "Direct",
"requested": "[2.1.13, )",
"resolved": "2.1.13",
"contentHash": "rMN1omGe8536f4xLMvx9NwfvpAc9YFFfeXJ1t4P4PE6Gu8WCIoFliR1sh07hM+bfODmesk/dvMbji7vNI+B/pQ=="
"requested": "[2.1.11, )",
"resolved": "2.1.11",
"contentHash": "9qlAWoRRTiL/geAvuwR/g6Bcbrd/bJJgVnB/RurBiyKs6srsP0bvpoo8IK+Eg8EA6jWeM6/YJWs66w4FIAzqPw=="
},
"DotNet.ReproducibleBuilds": {
"GitInfo": {
"type": "Direct",
"requested": "[1.1.1, )",
"resolved": "1.1.1",
"contentHash": "+H2t/t34h6mhEoUvHi8yGXyuZ2GjSovcGYehJrS2MDm2XgmPfZL2Sdxg+uL2lKgZ4M6tTwKHIlxOob2bgh0NRQ==",
"dependencies": {
"Microsoft.SourceLink.AzureRepos.Git": "1.1.1",
"Microsoft.SourceLink.Bitbucket.Git": "1.1.1",
"Microsoft.SourceLink.GitHub": "1.1.1",
"Microsoft.SourceLink.GitLab": "1.1.1"
}
"requested": "[2.3.0, )",
"resolved": "2.3.0",
"contentHash": "LdnsKNdwQvdDvpPYQuoGjXML75dY7NybKRe+qlkPPQaTY4dE5Fy8VCrD8YBhXO0fH/5xnmvKeSq4yztzg5KY0Q=="
},
"Google.Protobuf": {
"type": "Direct",
"requested": "[3.27.2, )",
"resolved": "3.27.2",
"contentHash": "0wdgA3LO9mBS477jieBFs4pU1sWhVtwv/P+i9nAEiFDQyUA7PPHDBbJL1CeqYtV18jLiq9og4n7wSVCO171OBg=="
"requested": "[3.22.1, )",
"resolved": "3.22.1",
"contentHash": "Ul4gVJWLya83Z8/n3+O4QKhD8ukCCwNLDyoWpUdJSnmzxRe8o3pWiuCzzvN2z/LVH60nozlKpTzhJo3ctI+G4Q=="
},
"Grpc.Net.Client": {
"type": "Direct",
"requested": "[2.63.0, )",
"resolved": "2.63.0",
"contentHash": "847zG24daOP1242OpbnjhbKtplH/EfV/76QReQA3cbS5SL78uIXsWMe9IN9JlIb4+kT3eE4fjMCXTn8BAQ91Ng==",
"requested": "[2.52.0, )",
"resolved": "2.52.0",
"contentHash": "hWVH9g/Nnjz40ni//2S8UIOyEmhueQREoZIkD0zKHEPqLxXcNlbp4eebXIOicZtkwDSx0TFz9NpkbecEDn6rBw==",
"dependencies": {
"Grpc.Net.Common": "2.63.0",
"Microsoft.Extensions.Logging.Abstractions": "6.0.0"
"Grpc.Net.Common": "2.52.0",
"Microsoft.Extensions.Logging.Abstractions": "3.0.3"
}
},
"Grpc.Tools": {
"type": "Direct",
"requested": "[2.64.0, )",
"resolved": "2.64.0",
"contentHash": "W5RrhDFHUhioASktxfuDs5fTjWUxwegljZAig9zFL8nWNskeyQA6OXN2choWKYxGrljer25VqCJCMbWz7XHvqg=="
"requested": "[2.53.0, )",
"resolved": "2.53.0",
"contentHash": "vm8iRSAF/4PN9g555iYZwhCQptSE4cZ8xk5W1TQ+JcHwaHSrBhD+P6H4l0+SqqfzuX7sGpjjOMQJXHSyrERTgw=="
},
"Microsoft.EntityFrameworkCore.Sqlite": {
"type": "Direct",
"requested": "[8.0.6, )",
"resolved": "8.0.6",
"contentHash": "nC4cZN4zReTb22qd9WDU0eDmlXvkyf2g2pqQ3VIHJbkpJcdWSY/PDgwGpbpShsVcAjXbkjGiUcv9aGwa61xQPw==",
"requested": "[7.0.4, )",
"resolved": "7.0.4",
"contentHash": "d1cIR5upwzTZmzycqWEoxfso5b3qD0G43IeECtfeMSPoG8JD4OJHHtbun0wS9RzwAORMa/4Zb3vuogTYY3mtaQ==",
"dependencies": {
"Microsoft.EntityFrameworkCore.Sqlite.Core": "8.0.6",
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.6"
"Microsoft.EntityFrameworkCore.Sqlite.Core": "7.0.4",
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
}
},
"Microsoft.EntityFrameworkCore.Tools": {
"type": "Direct",
"requested": "[7.0.4, )",
"resolved": "7.0.4",
"contentHash": "58hDB+ENGisuSjJBl1RBHL9qzFJTukFSQFl/wCU8/3ApcOH/rPrRG4PWThiJTmfHRmh8H8HExdYbtkv7wa7BLg==",
"dependencies": {
"Microsoft.EntityFrameworkCore.Design": "7.0.4"
}
},
"Microsoft.Extensions.Logging": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "tvRkov9tAJ3xP51LCv3FJ2zINmv1P8Hi8lhhtcKGqM+ImiTCC84uOPEI4z8Cdq2C3o9e+Aa0Gw0rmrsJD77W+w==",
"requested": "[7.0.0, )",
"resolved": "7.0.0",
"contentHash": "Nw2muoNrOG5U5qa2ZekXwudUn2BJcD41e65zwmDHb1fQegTX66UokLWZkJRpqSSHXDOWZ5V0iqhbxOEky91atA==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "8.0.0",
"Microsoft.Extensions.Logging.Abstractions": "8.0.0",
"Microsoft.Extensions.Options": "8.0.0"
}
},
"Microsoft.SourceLink.Gitea": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "KOBodmDnlWGIqZt2hT47Q69TIoGhIApDVLCyyj9TT5ct8ju16AbHYcB4XeknoHX562wO1pMS/1DfBIZK+V+sxg==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "8.0.0",
"Microsoft.SourceLink.Common": "8.0.0"
"Microsoft.Extensions.DependencyInjection": "7.0.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0",
"Microsoft.Extensions.Logging.Abstractions": "7.0.0",
"Microsoft.Extensions.Options": "7.0.0"
}
},
"System.Security.Cryptography.ProtectedData": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "+TUFINV2q2ifyXauQXRwy4CiBhqvDEDZeVJU7qfxya4aRYOKzVBpN+4acx25VcPB9ywUN6C0n8drWl110PhZEg=="
"requested": "[7.0.1, )",
"resolved": "7.0.1",
"contentHash": "3evI3sBfKqwYSwuBcYgShbmEgtXcg8N5Qu+jExLdkBXPty2yGDXq5m1/4sx9Exb8dqdeMPUs/d9DQ0wy/9Adwg=="
},
"Grpc.Core.Api": {
"type": "Transitive",
"resolved": "2.63.0",
"contentHash": "t3+/MF8AxIqKq5UmPB9EWAnM9C/+lXOB8TRFfeVMDntf6dekfJmjpKDebaT4t2bbuwVwwvthxxox9BuGr59kYA=="
"resolved": "2.52.0",
"contentHash": "SQiPyBczG4vKPmI6Fd+O58GcxxDSFr6nfRAJuBDUNj+PgdokhjWJvZE/La1c09AkL2FVm/jrDloG89nkzmVF7A==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"Grpc.Net.Common": {
"type": "Transitive",
"resolved": "2.63.0",
"contentHash": "RLt6p31ZMsXRcHNeu1dQuIFLYZvnwP6LUzoDPlV3KoR4w9btmwrXIvz9Jbp1SOmxW7nXw9zShAeIt5LsqFAx5w==",
"resolved": "2.52.0",
"contentHash": "di9qzpdx525IxumZdYmu6sG2y/gXJyYeZ1ruFUzB9BJ1nj4kU1/dTAioNCMt1VLRvNVDqh8S8B1oBdKhHJ4xRg==",
"dependencies": {
"Grpc.Core.Api": "2.63.0"
"Grpc.Core.Api": "2.52.0"
}
},
"Microsoft.Build.Tasks.Git": {
"Humanizer.Core": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
"resolved": "2.14.1",
"contentHash": "lQKvtaTDOXnoVJ20ibTuSIOf2i0uO0MPbDhd1jm238I+U/2ZnRENj0cktKZhtchBMtCUSRQ5v4xBCUbKNmyVMw=="
},
"Microsoft.Data.Sqlite.Core": {
"type": "Transitive",
"resolved": "8.0.6",
"contentHash": "umhZ0ZF2RI81rGFTnYmCxI+Euj4Aqe/6Y4+8CxN9OVJNGDNIqB5laJ3wxQTU8zXCcm2k9F7FL+/6RVoOT4z1Fw==",
"resolved": "7.0.4",
"contentHash": "AUBM1KZ7EvmkYhC/ECXL4cjx+q55DJ3lmSf0NwAyRNArubNPRdroGono5uN6aW7Kqp+IUZwEK0Ywd1Gh7FDM2A==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.6"
"SQLitePCLRaw.core": "2.1.4"
}
},
"Microsoft.EntityFrameworkCore": {
"type": "Transitive",
"resolved": "8.0.6",
"contentHash": "Ms5e5QuBAjVIuQsGumeLvkgMiOpnj6wxPvwBIoe1NfTkseWK4NZYztnhgDlpkCPkrUmJEXLv69kl349Ours30Q==",
"resolved": "7.0.4",
"contentHash": "eNcsY3rft5ERJJcen80Jyg57EScjWZmvhwmFLYXmEOTdVqHG+wQZiMOXnO1b5RH3u2qTQq+Tpci7KGfLAG5Gtg==",
"dependencies": {
"Microsoft.EntityFrameworkCore.Abstractions": "8.0.6",
"Microsoft.EntityFrameworkCore.Analyzers": "8.0.6",
"Microsoft.Extensions.Caching.Memory": "8.0.0",
"Microsoft.Extensions.Logging": "8.0.0"
"Microsoft.EntityFrameworkCore.Abstractions": "7.0.4",
"Microsoft.EntityFrameworkCore.Analyzers": "7.0.4",
"Microsoft.Extensions.Caching.Memory": "7.0.0",
"Microsoft.Extensions.DependencyInjection": "7.0.0",
"Microsoft.Extensions.Logging": "7.0.0"
}
},
"Microsoft.EntityFrameworkCore.Abstractions": {
"type": "Transitive",
"resolved": "8.0.6",
"contentHash": "X7wSSBNFRuN8j8M9HDYG7rPpEeyhY+PdJZR9rftmgvsZH0eK5+bZ3b3As8iO4rLEpjsBzDnrgSIY6q2F3HQatw=="
"resolved": "7.0.4",
"contentHash": "6GbYvs4L5oFpYpMzwF05kdDgvX09UmMX7MpDtDlGI5ymijFwquwv+yvdijbtodOuu0yLUpc4n71x6eBdJ8v1xQ=="
},
"Microsoft.EntityFrameworkCore.Analyzers": {
"type": "Transitive",
"resolved": "8.0.6",
"contentHash": "fDNtuQ4lAaPaCOlsrwUck/GvnF4QLeDpMmE1L5QtxZpMSmWfnL2/vk8sDL9OVTWcfprooI9V5MNpIx3/Tq5ehg=="
"resolved": "7.0.4",
"contentHash": "YRD4bViuaEPEsaBIL52DzXGzLCt3jYoE3wztYEW1QZYDl89hQ+ca0nvBO2mnMHmCXpU/2wlErrUyDp4x5B/3mg=="
},
"Microsoft.EntityFrameworkCore.Design": {
"type": "Transitive",
"resolved": "7.0.4",
"contentHash": "LI/ML3w17ap5IUmEKOPVnGJYi/XSDJW3Rf42utNF0e1tidmKtSkjwoTqIKLt2hE+jQJrlzeaqu5YiqdoFWVuZw==",
"dependencies": {
"Humanizer.Core": "2.14.1",
"Microsoft.EntityFrameworkCore.Relational": "7.0.4",
"Microsoft.Extensions.DependencyModel": "7.0.0",
"Mono.TextTemplating": "2.2.1"
}
},
"Microsoft.EntityFrameworkCore.Relational": {
"type": "Transitive",
"resolved": "8.0.6",
"contentHash": "chhfmLusCGLGvNYtvMji6KGQlduPDnJsStG/LjS8qJhFWJDDzTZpSr2LHowewcxMrMo/Axc6Jwe+WwSi/vlkTg==",
"resolved": "7.0.4",
"contentHash": "L41+VonK6L0IurFHopoe5yY+m3MD26OMocKLPPR/XKxnazzZUcGPz0IGJpVnwpZyKVPfEIAnD5vmm60meYr1NA==",
"dependencies": {
"Microsoft.EntityFrameworkCore": "8.0.6",
"Microsoft.Extensions.Configuration.Abstractions": "8.0.0"
"Microsoft.EntityFrameworkCore": "7.0.4",
"Microsoft.Extensions.Configuration.Abstractions": "7.0.0"
}
},
"Microsoft.EntityFrameworkCore.Sqlite.Core": {
"type": "Transitive",
"resolved": "8.0.6",
"contentHash": "87xfPtqSouxWWdynYZv/rubd0rOUeiN9+XeoMWQzpZm/5svH1TuvzFODGIY0zKuXS18NiOFyHl9N6///eaEs/Q==",
"resolved": "7.0.4",
"contentHash": "FeuV57+U4A4DO018Jy5Wkv0uYNZhyFVUUdwyVYz8TMghsZAj+3i+fOeFtD/jAWWMzDOFOF7eMni3YqLA+ufu9Q==",
"dependencies": {
"Microsoft.Data.Sqlite.Core": "8.0.6",
"Microsoft.EntityFrameworkCore.Relational": "8.0.6",
"Microsoft.Extensions.DependencyModel": "8.0.0"
"Microsoft.Data.Sqlite.Core": "7.0.4",
"Microsoft.EntityFrameworkCore.Relational": "7.0.4",
"Microsoft.Extensions.DependencyModel": "7.0.0"
}
},
"Microsoft.Extensions.Caching.Abstractions": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "3KuSxeHoNYdxVYfg2IRZCThcrlJ1XJqIXkAWikCsbm5C/bCjv7G0WoKDyuR98Q+T607QT2Zl5GsbGRkENcV2yQ==",
"resolved": "7.0.0",
"contentHash": "IeimUd0TNbhB4ded3AbgBLQv2SnsiVugDyGV1MvspQFVlA07nDC7Zul7kcwH5jWN3JiTcp/ySE83AIJo8yfKjg==",
"dependencies": {
"Microsoft.Extensions.Primitives": "8.0.0"
"Microsoft.Extensions.Primitives": "7.0.0"
}
},
"Microsoft.Extensions.Caching.Memory": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "7pqivmrZDzo1ADPkRwjy+8jtRKWRCPag9qPI+p7sgu7Q4QreWhcvbiWXsbhP+yY8XSiDvZpu2/LWdBv7PnmOpQ==",
"resolved": "7.0.0",
"contentHash": "xpidBs2KCE2gw1JrD0quHE72kvCaI3xFql5/Peb2GRtUuZX+dYPoK/NTdVMiM67Svym0M0Df9A3xyU0FbMQhHw==",
"dependencies": {
"Microsoft.Extensions.Caching.Abstractions": "8.0.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0",
"Microsoft.Extensions.Logging.Abstractions": "8.0.0",
"Microsoft.Extensions.Options": "8.0.0",
"Microsoft.Extensions.Primitives": "8.0.0"
"Microsoft.Extensions.Caching.Abstractions": "7.0.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0",
"Microsoft.Extensions.Logging.Abstractions": "7.0.0",
"Microsoft.Extensions.Options": "7.0.0",
"Microsoft.Extensions.Primitives": "7.0.0"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==",
"resolved": "7.0.0",
"contentHash": "f34u2eaqIjNO9YLHBz8rozVZ+TcFiFs0F3r7nUJd7FRkVSxk8u4OpoK226mi49MwexHOR2ibP9MFvRUaLilcQQ==",
"dependencies": {
"Microsoft.Extensions.Primitives": "8.0.0"
"Microsoft.Extensions.Primitives": "7.0.0"
}
},
"Microsoft.Extensions.DependencyInjection": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==",
"resolved": "7.0.0",
"contentHash": "elNeOmkeX3eDVG6pYVeV82p29hr+UKDaBhrZyWvWLw/EVZSYEkZlQdkp0V39k/Xehs2Qa0mvoCvkVj3eQxNQ1Q==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0"
"Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0"
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg=="
"resolved": "7.0.0",
"contentHash": "h3j/QfmFN4S0w4C2A6X7arXij/M/OVw3uQHSOFxnND4DyAzO1F9eMX7Eti7lU/OkSthEE0WzRsfT/Dmx86jzCw=="
},
"Microsoft.Extensions.DependencyModel": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "NSmDw3K0ozNDgShSIpsZcbFIzBX4w28nDag+TfaQujkXGazBm+lid5onlWoCBy4VsLxqnnKjEBbGSJVWJMf43g==",
"resolved": "7.0.0",
"contentHash": "oONNYd71J3LzkWc4fUHl3SvMfiQMYUCo/mDHDEu76hYYxdhdrPYv6fvGv9nnKVyhE9P0h20AU8RZB5OOWQcAXg==",
"dependencies": {
"System.Text.Encodings.Web": "8.0.0",
"System.Text.Json": "8.0.0"
"System.Text.Encodings.Web": "7.0.0",
"System.Text.Json": "7.0.0"
}
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "arDBqTgFCyS0EvRV7O3MZturChstm50OJ0y9bDJvAcmEPJm0FFpFyjU/JLYyStNGGey081DvnQYlncNX5SJJGA==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0"
}
"resolved": "7.0.0",
"contentHash": "kmn78+LPVMOWeITUjIlfxUPDsI0R6G0RkeAMBmQxAJ7vBJn4q2dTva7pWi65ceN5vPGjJ9q/Uae2WKgvfktJAw=="
},
"Microsoft.Extensions.Options": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "JOVOfqpnqlVLUzINQ2fox8evY2SKLYJ3BV8QDe/Jyp21u1T7r45x/R/5QdteURMR5r01GxeJSBBUOCOyaNXA3g==",
"resolved": "7.0.0",
"contentHash": "lP1yBnTTU42cKpMozuafbvNtQ7QcBjr/CcK3bYOGEMH55Fjt+iecXjT6chR7vbgCMqy3PG3aNQSZgo/EuY/9qQ==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0",
"Microsoft.Extensions.Primitives": "8.0.0"
"Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0",
"Microsoft.Extensions.Primitives": "7.0.0"
}
},
"Microsoft.Extensions.Primitives": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g=="
"resolved": "7.0.0",
"contentHash": "um1KU5kxcRp3CNuI8o/GrZtD4AIOXDk+RLsytjZ9QPok3ttLUelLKpilVPuaFT3TFjOhSibUAso0odbOaCDj3Q=="
},
"Microsoft.SourceLink.AzureRepos.Git": {
"Mono.TextTemplating": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "qB5urvw9LO2bG3eVAkuL+2ughxz2rR7aYgm2iyrB8Rlk9cp2ndvGRCvehk3rNIhRuNtQaeKwctOl1KvWiklv5w==",
"resolved": "2.2.1",
"contentHash": "KZYeKBET/2Z0gY1WlTAK7+RHTl7GSbtvTLDXEZZojUdAPqpQNDL6tHv7VUpqfX5VEOh+uRGKaZXkuD253nEOBQ==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "1.1.1",
"Microsoft.SourceLink.Common": "1.1.1"
}
},
"Microsoft.SourceLink.Bitbucket.Git": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "cDzxXwlyWpLWaH0em4Idj0H3AmVo3L/6xRXKssYemx+7W52iNskj/SQ4FOmfCb8YQt39otTDNMveCZzYtMoucQ==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "1.1.1",
"Microsoft.SourceLink.Common": "1.1.1"
}
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Microsoft.SourceLink.GitHub": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "IaJGnOv/M7UQjRJks7B6p7pbPnOwisYGOIzqCz5ilGFTApZ3ktOR+6zJ12ZRPInulBmdAf1SrGdDG2MU8g6XTw==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "1.1.1",
"Microsoft.SourceLink.Common": "1.1.1"
}
},
"Microsoft.SourceLink.GitLab": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "tvsg47DDLqqedlPeYVE2lmiTpND8F0hkrealQ5hYltSmvruy/Gr5nHAKSsjyw5L3NeM/HLMI5ORv7on/M4qyZw==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "1.1.1",
"Microsoft.SourceLink.Common": "1.1.1"
"System.CodeDom": "4.4.0"
}
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.6",
"contentHash": "BmAf6XWt4TqtowmiWe4/5rRot6GerAeklmOPfviOvwLoF5WwgxcJHAxZtySuyW9r9w+HLILnm8VfJFLCUJYW8A==",
"resolved": "2.1.4",
"contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==",
"dependencies": {
"SQLitePCLRaw.lib.e_sqlite3": "2.1.6",
"SQLitePCLRaw.provider.e_sqlite3": "2.1.6"
"SQLitePCLRaw.lib.e_sqlite3": "2.1.4",
"SQLitePCLRaw.provider.e_sqlite3": "2.1.4"
}
},
"SQLitePCLRaw.core": {
"type": "Transitive",
"resolved": "2.1.6",
"contentHash": "wO6v9GeMx9CUngAet8hbO7xdm+M42p1XeJq47ogyRoYSvNSp0NGLI+MgC0bhrMk9C17MTVFlLiN6ylyExLCc5w==",
"resolved": "2.1.4",
"contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"SQLitePCLRaw.lib.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.6",
"contentHash": "2ObJJLkIUIxRpOUlZNGuD4rICpBnrBR5anjyfUFQep4hMOIeqW+XGQYzrNmHSVz5xSWZ3klSbh7sFR6UyDj68Q=="
"resolved": "2.1.4",
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
},
"SQLitePCLRaw.provider.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.6",
"contentHash": "PQ2Oq3yepLY4P7ll145P3xtx2bX8xF4PzaKPRpw9jZlKvfe4LE/saAV82inND9usn1XRpmxXk7Lal3MTI+6CNg==",
"resolved": "2.1.4",
"contentHash": "CSlb5dUp1FMIkez9Iv5EXzpeq7rHryVNqwJMWnpq87j9zWZexaEMdisDktMsnnrzKM6ahNrsTkjqNodTBPBxtQ==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.6"
"SQLitePCLRaw.core": "2.1.4"
}
},
"System.CodeDom": {
"type": "Transitive",
"resolved": "4.4.0",
"contentHash": "2sCCb7doXEwtYAbqzbF/8UAeDRMNmPaQbU2q50Psg1J9KzumyVVCgKQY8s53WIPTufNT0DpSe9QRvVjOzfDWBA=="
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.3",
@ -304,40 +282,34 @@
},
"System.Text.Encodings.Web": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ=="
"resolved": "7.0.0",
"contentHash": "OP6umVGxc0Z0MvZQBVigj4/U31Pw72ITihDWP9WiWDm+q5aoe0GaJivsfYGq53o6dxH7DcXWiCTl7+0o2CGdmg=="
},
"System.Text.Json": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "OdrZO2WjkiEG6ajEFRABTRCi/wuXQPxeV6g8xvUJqdxMvvuCCEk86zPla8UiIQJz3durtUEbNyY/3lIhS0yZvQ==",
"resolved": "7.0.0",
"contentHash": "DaGSsVqKsn/ia6RG8frjwmJonfos0srquhw09TlT8KRw5I43E+4gs+/bZj4K0vShJ5H9imCuXupb4RmS+dBy3w==",
"dependencies": {
"System.Text.Encodings.Web": "8.0.0"
"System.Text.Encodings.Web": "7.0.0"
}
},
"ecommons": {
"type": "Project"
},
"llib": {
"type": "Project",
"dependencies": {
"DalamudPackager": "[2.1.13, )"
}
},
"pal.common": {
"type": "Project"
}
},
"net8.0-windows7.0/win-x64": {
"net7.0-windows7.0/win-x64": {
"SQLitePCLRaw.lib.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.6",
"contentHash": "2ObJJLkIUIxRpOUlZNGuD4rICpBnrBR5anjyfUFQep4hMOIeqW+XGQYzrNmHSVz5xSWZ3klSbh7sFR6UyDj68Q=="
"resolved": "2.1.4",
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
},
"System.Text.Encodings.Web": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ=="
"resolved": "7.0.0",
"contentHash": "OP6umVGxc0Z0MvZQBVigj4/U31Pw72ITihDWP9WiWDm+q5aoe0GaJivsfYGq53o6dxH7DcXWiCTl7+0o2CGdmg=="
}
}
}

View File

@ -1,8 +1,8 @@
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
namespace Pal.Common;
namespace Pal.Common
{
[SuppressMessage("ReSharper", "UnusedMember.Global")]
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum ETerritoryType : ushort
@ -60,3 +60,4 @@ public enum ETerritoryType : ushort
EurekaOrthos_81_90,
EurekaOrthos_91_100
}
}

View File

@ -1,10 +1,8 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
namespace Pal.Common;
namespace Pal.Common
{
public static class EnumExtensions
{
public static int? GetOrder(this Enum e)
@ -15,3 +13,4 @@ public static class EnumExtensions
return attribute?.Order;
}
}
}

View File

@ -4,9 +4,10 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pal.Common;
namespace Pal.Common
{
public static class ExportConfig
{
public static int ExportVersion => 2;
}
}

View File

@ -1,8 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>12.0</LangVersion>
<TargetFramework>net7.0</TargetFramework>
<LangVersion>11.0</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<DebugType>portable</DebugType>
<PathMap Condition="$(SolutionDir) != ''">$(SolutionDir)=X:\</PathMap>

View File

@ -1,8 +1,7 @@
using System;
using System.Numerics;
namespace Pal.Common;
using System.Numerics;
namespace Pal.Common
{
public class PalaceMath
{
private static readonly Vector3 ScaleFactor = new(5);
@ -20,3 +19,4 @@ public class PalaceMath
return HashCode.Combine((int)v.X, (int)v.Y, (int)v.Z);
}
}
}

View File

@ -18,7 +18,6 @@ service AccountService {
}
message CreateAccountRequest {
Version version = 1;
}
message CreateAccountReply {
@ -36,7 +35,6 @@ enum CreateAccountError {
message LoginRequest {
string accountId = 1;
Version version = 2;
}
message LoginReply {
@ -58,8 +56,3 @@ message VerifyRequest {
message VerifyReply {
}
message Version {
int32 major = 1;
int32 minor = 2;
}

View File

@ -1,6 +1,6 @@
{
"version": 1,
"dependencies": {
"net8.0": {}
"net7.0": {}
}
}

View File

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.22.1"/>
<PackageReference Include="Grpc.Net.Client" Version="2.52.0"/>
<PackageReference Include="Grpc.Tools" Version="2.53.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Pal.Common\Pal.Common.csproj"/>
</ItemGroup>
<ItemGroup>
<Protobuf Include="..\Pal.Common\Protos\account.proto" Link="Protos\account.proto" GrpcServices="Client" Access="Internal"/>
<Protobuf Include="..\Pal.Common\Protos\palace.proto" Link="Protos\palace.proto" GrpcServices="Client" Access="Internal"/>
</ItemGroup>
</Project>

View File

@ -0,0 +1,34 @@
using Grpc.Core;
using Grpc.Net.Client;
using Palace;
namespace Pal.StandaloneClient
{
internal class Program
{
private const string remoteUrl = "http://localhost:5415";
private static readonly Guid accountId = Guid.Parse("ce7b109a-5e29-4b63-ab3e-b6f89eb5e19e"); // manually created account id
static async Task Main(string[] args)
{
GrpcChannel channel = GrpcChannel.ForAddress(remoteUrl);
var accountClient = new Account.AccountService.AccountServiceClient(channel);
var loginReply = await accountClient.LoginAsync(new Account.LoginRequest
{
AccountId = accountId.ToString()
});
if (loginReply == null || !loginReply.Success)
throw new Exception($"Login failed: {loginReply?.Error}");
var headers = new Metadata()
{
{ "Authorization", $"Bearer {loginReply.AuthToken}" }
};
var palaceClient = new Palace.PalaceService.PalaceServiceClient(channel);
var markAsSeenRequest = new MarkObjectsSeenRequest { TerritoryType = 772 };
markAsSeenRequest.NetworkIds.Add("0c635960-0e2e-4ec6-9fb5-443d0e7a3315"); // this is an already existing entry
var markAsSeenReply = await palaceClient.MarkObjectsSeenAsync(markAsSeenRequest, headers: headers);
Console.WriteLine($"Reply = {markAsSeenReply.Success}");
}
}
}

View File

@ -0,0 +1,6 @@
# Palace Pal - Test Client
This is a very simple prototype for a local test client, which is more helpful
in troubleshooting some specific edge cases with the server implementation.
This should eventually be refactored into a test suite.

View File

@ -0,0 +1,58 @@
{
"version": 1,
"dependencies": {
"net7.0": {
"Google.Protobuf": {
"type": "Direct",
"requested": "[3.22.1, )",
"resolved": "3.22.1",
"contentHash": "Ul4gVJWLya83Z8/n3+O4QKhD8ukCCwNLDyoWpUdJSnmzxRe8o3pWiuCzzvN2z/LVH60nozlKpTzhJo3ctI+G4Q=="
},
"Grpc.Net.Client": {
"type": "Direct",
"requested": "[2.52.0, )",
"resolved": "2.52.0",
"contentHash": "hWVH9g/Nnjz40ni//2S8UIOyEmhueQREoZIkD0zKHEPqLxXcNlbp4eebXIOicZtkwDSx0TFz9NpkbecEDn6rBw==",
"dependencies": {
"Grpc.Net.Common": "2.52.0",
"Microsoft.Extensions.Logging.Abstractions": "3.0.3"
}
},
"Grpc.Tools": {
"type": "Direct",
"requested": "[2.53.0, )",
"resolved": "2.53.0",
"contentHash": "vm8iRSAF/4PN9g555iYZwhCQptSE4cZ8xk5W1TQ+JcHwaHSrBhD+P6H4l0+SqqfzuX7sGpjjOMQJXHSyrERTgw=="
},
"Grpc.Core.Api": {
"type": "Transitive",
"resolved": "2.52.0",
"contentHash": "SQiPyBczG4vKPmI6Fd+O58GcxxDSFr6nfRAJuBDUNj+PgdokhjWJvZE/La1c09AkL2FVm/jrDloG89nkzmVF7A==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"Grpc.Net.Common": {
"type": "Transitive",
"resolved": "2.52.0",
"contentHash": "di9qzpdx525IxumZdYmu6sG2y/gXJyYeZ1ruFUzB9BJ1nj4kU1/dTAioNCMt1VLRvNVDqh8S8B1oBdKhHJ4xRg==",
"dependencies": {
"Grpc.Core.Api": "2.52.0"
}
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "Transitive",
"resolved": "3.0.3",
"contentHash": "m2Jyi/MEn043WMI1I6J1ALuCThktZ93rd7eqzYeLmMcA0bdZC+TBVl0LuEbEWM01dWeeBjOoagjNwQTzOi2r6A=="
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.3",
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA=="
},
"pal.common": {
"type": "Project"
}
}
}
}

22
Pal.sln
View File

@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32929.385
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pal.Server", "Server\Server\Pal.Server.csproj", "{AB3E2849-DB06-46F6-8457-9AC1096B4125}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pal.Server", "Pal.Server\Pal.Server.csproj", "{AB3E2849-DB06-46F6-8457-9AC1096B4125}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pal.Client", "Pal.Client\Pal.Client.csproj", "{7F1985B3-D376-4A91-BC9B-46C2A860F9EF}"
EndProject
@ -25,9 +25,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "github-workflows", "github-
.github\workflows\upload-crowdin.yml = .github\workflows\upload-crowdin.yml
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pal.Server.Tests", "Server\Tests\Pal.Server.Tests.csproj", "{AEC052FA-F178-492C-9A09-ED28DBE1EF5E}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pal.StandaloneClient", "Pal.StandaloneClient\Pal.StandaloneClient.csproj", "{EDC1C408-D832-4C09-97A2-61B223A84166}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LLib", "vendor\LLib\LLib.csproj", "{B1321FD5-7BBF-4C9D-83C1-F8D7C394F32A}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pal.Server.Tests", "Pal.Server.Tests\Pal.Server.Tests.csproj", "{AEC052FA-F178-492C-9A09-ED28DBE1EF5E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -69,6 +69,14 @@ Global
{D0B37096-5BC3-41B0-8D81-203CBA3932B0}.Release|Any CPU.Build.0 = Release|x64
{D0B37096-5BC3-41B0-8D81-203CBA3932B0}.Release|x64.ActiveCfg = Release|x64
{D0B37096-5BC3-41B0-8D81-203CBA3932B0}.Release|x64.Build.0 = Release|x64
{EDC1C408-D832-4C09-97A2-61B223A84166}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EDC1C408-D832-4C09-97A2-61B223A84166}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EDC1C408-D832-4C09-97A2-61B223A84166}.Debug|x64.ActiveCfg = Debug|Any CPU
{EDC1C408-D832-4C09-97A2-61B223A84166}.Debug|x64.Build.0 = Debug|Any CPU
{EDC1C408-D832-4C09-97A2-61B223A84166}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EDC1C408-D832-4C09-97A2-61B223A84166}.Release|Any CPU.Build.0 = Release|Any CPU
{EDC1C408-D832-4C09-97A2-61B223A84166}.Release|x64.ActiveCfg = Release|Any CPU
{EDC1C408-D832-4C09-97A2-61B223A84166}.Release|x64.Build.0 = Release|Any CPU
{AEC052FA-F178-492C-9A09-ED28DBE1EF5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AEC052FA-F178-492C-9A09-ED28DBE1EF5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AEC052FA-F178-492C-9A09-ED28DBE1EF5E}.Debug|x64.ActiveCfg = Debug|Any CPU
@ -77,14 +85,6 @@ Global
{AEC052FA-F178-492C-9A09-ED28DBE1EF5E}.Release|Any CPU.Build.0 = Release|Any CPU
{AEC052FA-F178-492C-9A09-ED28DBE1EF5E}.Release|x64.ActiveCfg = Release|Any CPU
{AEC052FA-F178-492C-9A09-ED28DBE1EF5E}.Release|x64.Build.0 = Release|Any CPU
{B1321FD5-7BBF-4C9D-83C1-F8D7C394F32A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B1321FD5-7BBF-4C9D-83C1-F8D7C394F32A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B1321FD5-7BBF-4C9D-83C1-F8D7C394F32A}.Debug|x64.ActiveCfg = Debug|Any CPU
{B1321FD5-7BBF-4C9D-83C1-F8D7C394F32A}.Debug|x64.Build.0 = Debug|Any CPU
{B1321FD5-7BBF-4C9D-83C1-F8D7C394F32A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B1321FD5-7BBF-4C9D-83C1-F8D7C394F32A}.Release|Any CPU.Build.0 = Release|Any CPU
{B1321FD5-7BBF-4C9D-83C1-F8D7C394F32A}.Release|x64.ActiveCfg = Release|Any CPU
{B1321FD5-7BBF-4C9D-83C1-F8D7C394F32A}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -5,7 +5,7 @@ Shows possible trap & hoard coffer locations in Palace of the Dead & Heaven on H
## Installation
To install this plugin from my plugin repository, please check the
[Installation Instructions](https://git.carvel.li/liza/plugin-repo/src/branch/master/README.md).
[Installation Instructions](https://github.com/carvelli/Dalamud-Plugins#installation).
Additionally, you **need to install Splatoon**, which is used to render the visible overlays.
Please check [Splatoon's Installation Instructions](https://github.com/NightmareXIV/MyDalamudPlugins#installation).
@ -15,4 +15,4 @@ Please check [Splatoon's Installation Instructions](https://github.com/Nightmare
Please feel free to help by [translating this plugin into your language](https://crowdin.com/project/palace-pal).
If you want to translate the plugin into a language that is currently not enabled,
[please create a new issue](https://git.carvel.li/liza/PalacePal/issues/new).
[please create a new issue](https://github.com/carvelli/PalacePal/issues/new).

1
Server

@ -1 +0,0 @@
Subproject commit e59583fac353fdd960556ed2fa65220d66db5637

View File

@ -1,4 +0,0 @@
git fetch origin master
git reset --hard origin/master
git submodule update --checkout
docker buildx build -t palacepal-server --platform linux/amd64,linux/arm64 .

2
vendor/ECommons vendored

@ -1 +1 @@
Subproject commit dcd85f8cca504360eda4b2cb5327632cc500a22c
Subproject commit d9dc8c1c6e914cf37ad47703579d85094246f2e5

1
vendor/LLib vendored

@ -1 +0,0 @@
Subproject commit e206782c1106e1a5292a06af61783faef1ac0c42