From f9d6cc960cd708e70d5200496ef472cec445d821 Mon Sep 17 00:00:00 2001
From: Florian <45694132+flo-bit@users.noreply.github.com>
Date: Wed, 6 May 2026 13:18:25 +0200
Subject: [PATCH] add rpg actor card
---
src/lib/cards/index.ts | 4 +-
.../social/RPGActorCard/RPGActorCard.svelte | 152 ++++++++++++++++++
src/lib/cards/social/RPGActorCard/index.ts | 68 ++++++++
3 files changed, 223 insertions(+), 1 deletion(-)
create mode 100644 src/lib/cards/social/RPGActorCard/RPGActorCard.svelte
create mode 100644 src/lib/cards/social/RPGActorCard/index.ts
diff --git a/src/lib/cards/index.ts b/src/lib/cards/index.ts
index 15d875c..6be995c 100644
--- a/src/lib/cards/index.ts
+++ b/src/lib/cards/index.ts
@@ -63,6 +63,7 @@ import { KichRecipeCardDefinition } from './social/KichRecipeCard';
import { KichRecipeCollectionCardDefinition } from './social/KichRecipeCollectionCard';
import { KichCookingLogCardDefinition } from './social/KichCookingLogCard';
import { SecretImageCardDefinition } from './media/SecretImageCard';
+import { RPGActorCardDefinition } from './social/RPGActorCard';
// import { Model3DCardDefinition } from './visual/Model3DCard';
export const AllCardDefinitions = [
@@ -131,7 +132,8 @@ export const AllCardDefinitions = [
KichRecipeCardDefinition,
KichRecipeCollectionCardDefinition,
KichCookingLogCardDefinition,
- SecretImageCardDefinition
+ SecretImageCardDefinition,
+ RPGActorCardDefinition
] as const;
export const CardDefinitionsByType = AllCardDefinitions.reduce(
diff --git a/src/lib/cards/social/RPGActorCard/RPGActorCard.svelte b/src/lib/cards/social/RPGActorCard/RPGActorCard.svelte
new file mode 100644
index 0000000..8d6e4a8
--- /dev/null
+++ b/src/lib/cards/social/RPGActorCard/RPGActorCard.svelte
@@ -0,0 +1,152 @@
+
+
+
+ {#if loaded && actor}
+
+ {:else if loaded && !actor && isEditing}
+
+ {:else if loaded && !actor}
+
+ This person hasn't created a character yet
+
+ {/if}
+
diff --git a/src/lib/cards/social/RPGActorCard/index.ts b/src/lib/cards/social/RPGActorCard/index.ts
new file mode 100644
index 0000000..07b8393
--- /dev/null
+++ b/src/lib/cards/social/RPGActorCard/index.ts
@@ -0,0 +1,68 @@
+import type { CardDefinition } from '../../types';
+import { getRecord, getBlobURL } from '$lib/atproto';
+import RPGActorCard from './RPGActorCard.svelte';
+import type { Did } from '@atcute/lexicons';
+
+export type RpgSpriteRecord = {
+ rows: number;
+ columns: number;
+ frames: number;
+ width: number;
+ height: number;
+ frameWidth: number;
+ frameHeight: number;
+ isCustom?: boolean;
+ createdAt?: string;
+ spriteSheet: {
+ $type: 'blob';
+ ref: { $link: string };
+ mimeType: string;
+ size: number;
+ };
+};
+
+export type RpgActorData = {
+ sprite: RpgSpriteRecord;
+ url: string;
+} | null;
+
+export const RPGActorCardDefinition = {
+ type: 'rpgActor',
+ contentComponent: RPGActorCard,
+
+ createNew: (item) => {
+ item.w = 4;
+ item.h = 2;
+ item.mobileW = 8;
+ item.mobileH = 2;
+ },
+
+ loadData: async (_items, { did }) => {
+ try {
+ const record = await getRecord({
+ did: did as Did,
+ collection: 'actor.rpg.sprite',
+ rkey: 'self'
+ });
+ const value = record?.value as RpgSpriteRecord | undefined;
+ if (!value?.spriteSheet) return null;
+ const url = await getBlobURL({
+ did: did as Did,
+ blob: value.spriteSheet
+ });
+ return { sprite: value, url } satisfies RpgActorData;
+ } catch {
+ return null;
+ }
+ },
+ cacheLoadData: true,
+
+ minW: 2,
+ minH: 1,
+
+ name: 'RPG Character',
+ keywords: ['rpg', 'sprite', 'character', 'actor', 'avatar', 'pixel', 'game'],
+ groups: ['Social'],
+ canHaveLabel: true,
+ icon: ``
+} as CardDefinition & { type: 'rpgActor' };