mirror of
https://gitea.tendokyu.moe/Kayori/MedusaPluginChargeMachine.git
synced 2026-09-24 23:28:05 +03:00
- GetConfigEaChargeHandler: was declared as Handler<EmptyRequest, T>, which made HandlerService attempt to XML-deserialize an EmptyRequest against the incoming <eacharge> root, crashing on every getconf call. Switched to HandlerWithoutRequest<T>, matching every other parameterless handler (e.g. SppassOpenHandler). - ChargeMachinePlugin.DoesProfileExist: was a synchronous Func<bool>, but PluginService.DoesProfileExistAsync casts the DynamicInvoke result to Task<bool>, throwing InvalidCastException on every card inquire. Now returns Task.FromResult(true) - a PASELI profile always exists once a user is created, so this plugin never needs to report "no profile" here. - EaChargeConfigResponse: dropped the multibills/readagreement fields entirely and fixed articlelist's XML shape. A real getconf response (captured via spice2x's automap against the genuine Konami server) has neither field at all, and wraps articlelist entries in <item> children rather than repeating sibling <articlelist> elements. The denomination-button limitation this was chasing turned out to be an unrelated spice2x bill-validator emulation gap (see spice2x issue #123), not anything server-side. - GetConfigEaChargeHandler: DOCMT_* article types now send an empty articledoc, matching the real server - the disclosure/agreement text is rendered client-side from a bundled asset, not delivered over the wire. Sending real text there produced a solid black screen on a real cabinet instead of the disclosure text. Claude-Session: https://claude.ai/code/session_012FiU5Qe8fbePFxraxWHSd5
74 lines
3.7 KiB
C#
74 lines
3.7 KiB
C#
using Abstractions;
|
|
using MedusaPluginChargeMachine.Entities;
|
|
using MedusaPluginChargeMachine.Services;
|
|
using Microsoft.AspNetCore.Builder;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using System.Text;
|
|
|
|
namespace MedusaPluginChargeMachine;
|
|
|
|
public class ChargeMachinePlugin : IMedusaPlugin
|
|
{
|
|
public string Name => "Charge Machine";
|
|
public string Version => "1.0.0";
|
|
public string Description => "Plugin for the paseli charge machine";
|
|
public string GameCode => "LA9";
|
|
public int? MinVer => null;
|
|
public int? MaxVer => null;
|
|
public Encoding? ForcedEncoding => null;
|
|
public PluginUiManifest? UiManifest => null;
|
|
public Delegate DoesProfileExist => () => Task.FromResult(true);
|
|
|
|
public Task OnBuilderInitialize(WebApplicationBuilder builder) => Task.CompletedTask;
|
|
|
|
public void ConfigurePluginServices(IServiceCollection services)
|
|
{
|
|
services.AddSingleton<ISessionService, SessionService>();
|
|
services.AddDbContext<ChargeMachineDbContext>(o =>
|
|
o.UseSqlite("Data Source=database/ChargeMachine.db;"));
|
|
}
|
|
|
|
public async Task OnAppInitialize(WebApplication app, IServiceProvider pluginServices)
|
|
{
|
|
await using var scope = pluginServices.CreateAsyncScope();
|
|
var db = scope.ServiceProvider.GetRequiredService<ChargeMachineDbContext>();
|
|
await db.Database.MigrateAsync();
|
|
await SeedArticleContentsAsync(db);
|
|
}
|
|
|
|
private static async Task SeedArticleContentsAsync(ChargeMachineDbContext db)
|
|
{
|
|
if (await db.ArticleContents.AnyAsync())
|
|
return;
|
|
|
|
// Order matches the enum table in gamemode.dll (0x2C160-0x2C228).
|
|
// DOCMT_* = document text displayed on screen; URL_* = URLs/QR targets.
|
|
// _A/_B variants = primary/secondary display; only 0001-0004 have both;
|
|
// 0005-0008 exist only as _B (secondary).
|
|
var defaults = new List<ArticleContent>
|
|
{
|
|
new() { ArticleType = ArticleType.DOCMT_0001, ArticleDoc = "PASELI Charge Machine" },
|
|
new() { ArticleType = ArticleType.DOCMT_0002, ArticleDoc = "Top up your PASELI balance to play." },
|
|
new() { ArticleType = ArticleType.DOCMT_0003, ArticleDoc = "Charges are non-refundable. Ensure your card is registered before charging." },
|
|
new() { ArticleType = ArticleType.URL_0001_A, ArticleDoc = "https://localhost:5173/" },
|
|
new() { ArticleType = ArticleType.URL_0001_B, ArticleDoc = "https://localhost:5173/" },
|
|
new() { ArticleType = ArticleType.URL_0002_A, ArticleDoc = "https://localhost:5173/" },
|
|
new() { ArticleType = ArticleType.URL_0002_B, ArticleDoc = "https://localhost:5173/" },
|
|
new() { ArticleType = ArticleType.URL_0003_A, ArticleDoc = "https://localhost:5173/" },
|
|
new() { ArticleType = ArticleType.URL_0003_B, ArticleDoc = "https://localhost:5173/" },
|
|
new() { ArticleType = ArticleType.URL_0004_A, ArticleDoc = "https://localhost:5173/" },
|
|
new() { ArticleType = ArticleType.URL_0004_B, ArticleDoc = "https://localhost:5173/" },
|
|
new() { ArticleType = ArticleType.PASELIUNIT, ArticleDoc = "P" },
|
|
new() { ArticleType = ArticleType.DOCMT_0004, ArticleDoc = "For support, contact your arcade operator." },
|
|
new() { ArticleType = ArticleType.URL_0005_B, ArticleDoc = "https://localhost:5173/" },
|
|
new() { ArticleType = ArticleType.URL_0006_B, ArticleDoc = "https://localhost:5173/" },
|
|
new() { ArticleType = ArticleType.URL_0007_B, ArticleDoc = "https://localhost:5173/" },
|
|
new() { ArticleType = ArticleType.URL_0008_B, ArticleDoc = "https://localhost:5173/" },
|
|
};
|
|
|
|
db.ArticleContents.AddRange(defaults);
|
|
await db.SaveChangesAsync();
|
|
}
|
|
}
|