19 Commits

Author SHA1 Message Date
cf2708c7f3 fix 2025-12-12 14:02:50 +09:00
db29524307 fix 2025-12-12 13:49:43 +09:00
e5aeffb621 fix 2025-12-11 12:46:42 +09:00
cbf3c424e3 fix 2025-12-09 17:28:48 +09:00
adf2121a8b fix 2025-12-09 17:22:31 +09:00
5ba0b77154 fix 2025-12-08 18:51:00 +09:00
22fda9cb2d fix 2025-12-08 14:13:15 +09:00
b0ca3f9163 fix 2025-12-04 18:48:42 +09:00
08c4a5cd52 fix 2025-12-04 16:45:04 +09:00
c004905d39 fix 2025-12-04 15:19:46 +09:00
a970bc008f fix 2025-12-04 14:35:17 +09:00
678c238ee7 fix 2025-11-29 07:50:48 +09:00
9f9fabd478 fix 2025-11-22 08:05:30 +09:00
acf9cacda0 fix 2025-11-22 07:31:53 +09:00
a88a61f866 fix 2025-11-22 07:22:07 +09:00
afd95636da fix 2025-11-22 07:14:49 +09:00
62ecab5f04 fix 2025-11-21 22:08:48 +09:00
d46502d177 fix 2025-11-21 22:03:38 +09:00
0d742ca1f2 fix 2025-11-21 21:46:34 +09:00
14 changed files with 305 additions and 10 deletions

View File

@@ -24,7 +24,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '21'
node-version: '25'
- name: Install dependencies
run: |

View File

@@ -13,7 +13,7 @@ $ uname -r
6.12.53-1-lts
```
運用のコツとしては、`linux-lts`を使うこと。`linux-firmware`を入れないこと。`broadcom-wl`を入れること。
運用のコツとしては、`linux-lts`を使うこと。`linux-firmware`を入れないこと。`broadcom-wl-dkms`を入れること。
```sh
$ pacman -S linux-lts
@@ -25,9 +25,11 @@ $ mkinitcpio -P
```
```sh:/etc/pacman.conf
IgnorePkg = linux linux-headers
IgnorePkg = linux linux-headers broadcom-wl-dkms
```
linux-ltsをupdateしたときは、必ず`broadcom-wl-dkms`をreinstallをしないと動きません。
## usbからの実行
```sh

View File

@@ -23,7 +23,8 @@ draft: false
| ドメイン名 | `antigravity.google` |
| リバースドメインネーム | `google.antigravity` |
| アプリケーションID | `google.antigravity` |
| ローカルパス | `~/Library/google.antigravity/` |
| ローカルパス1 | `~/Library/google.antigravity/` |
| ローカルパス2 | `~/Library/google/antigravity/` |
```sh
$ nvm use 25

View File

@@ -7,13 +7,13 @@ language: ["ja", "en"]
draft: false
---
今回は、atmpsphere+three-vrmでキャラクターを表示する方法を紹介。
今回は、atmosphere+three-vrmでキャラクターを表示する方法を紹介。
非常に良いpackageを見つけたので、それを使います。
[https://github.com/takram-design-engineering/three-geospatial](https://github.com/takram-design-engineering/three-geospatial)
![](/img/three_cloud_vrm_0001.png)
<iframe width="100%" height="415" src="https://www.youtube.com/embed/mTuvL_lJDk8?rel=0&showinfo=0&controls=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
## three-vrm+vrmaの最小構成
@@ -138,6 +138,7 @@ export default function App() {
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="referrer" content="strict-origin-when-cross-origin" />
<title>VRM Animation Preview</title>
<style>
html, body, #root { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; }
@@ -365,3 +366,49 @@ export default function App() {
}
```
## google map api
街を表示するには料金がかかります。
`gcp`で`Map Tiles API`だけ有効にすればよいです。
```sh:.env
VITE_GOOGLE_MAP_API_KEY=xxx
```
```js:src/App.jsx
import {
GLTFExtensionsPlugin,
GoogleCloudAuthPlugin,
TileCompressionPlugin,
TilesFadePlugin,
UpdateOnChangePlugin,
} from '3d-tiles-renderer/plugins';
const apiKey = import.meta.env.VITE_GOOGLE_MAP_API_KEY;
```
認証情報は、localhostで使用するものと、webで使用するものを分けて、それぞれ制限をつけましょう。
```md
[test-map]
localhost:4400
[production-map]
example.com
```
これでサイトにapi-keyが埋め込まれていても比較的安全です。また、gh-pagesではなく、`gh-actions + cf-pages`でdeployしたほうがいいかも。
[msg type="warning" content="2つのkeyを用意することで、localhostを削除したり追加する手順を省略できます。keyにlocalhostを許可している状態だと悪用される危険が高まります。"]
[msg type="note" content="gh-pagesは無料プランでprivate-repoを許可していません。そのため、private-repoでgh-actionsからcf-pagesにdeployする方法があります。"]
### ハマったポイント
vrmとの合せ技なので、太陽光を調整するのが難しく、影が大きくなりすぎてしまい見づらかいのでやめました。
```diff
- <AerialPerspective sky sunLight skyLight />
+ <AerialPerspective sky />
```

View File

@@ -0,0 +1,17 @@
---
title: "bitwardenからpasswordsへ移行"
slug: "passwords"
date: "2025-11-29"
tags: ["mac", "ios", "password"]
language: ["ja", "en"]
draft: false
---
今まで、password-managerは、`bitwarden`, `keepass`などを使ってきましたが、今回、mac/ios標準の`passwords`に移行。
bitwardenのsefl-hostは、dockerで簡単に立ち上げられるのですが、定期的なメンテナンスが面倒になってきたこと、また、mac/ios標準のpasswordsがかなり使いやすくなってきたことから移行を決意。google authenticatorの2FAもpasswordsに保存できるようになったのも大きい。
また、初期設定で何も必要ないこと。最初からインストールされているアプリなので、apple accountでloginするだけで使えるようになります(passwordsのicloud共有をonにしていれば)。
`passwords`というアプリは、そこまで使いやすいものでもありませんが、例えば、iphoneには標準で強固な認証システム(指紋認証など)が動作していることもあり、そこに統一することにしました。

View File

@@ -0,0 +1,128 @@
---
title: "atprotoでozoneを動かした"
slug: "atproto"
date: "2025-12-04"
tags: ["atproto"]
language: ["ja", "en"]
draft: false
---
最近は、atprotoとai.card(ios)の連携を作っていました。ozoneが必要そうになったので動かしてみます。
## atprotoをゲームアカウントに
ゲームのアカウントシステムを作る際、atprotoが便利だと思っています。独自にシステムを作るのではなく、既にあるものを使って構築します。
しかし問題もあります。atprotoはユーザーがデータを自由に書き換えられます。もちろん、知識があればですが、そう難しいことではありません。
そのため、ゲームのアカウントシステムとして使う場合、ユーザーがデータを改ざんできないようにする必要があります。これは、rustで書いた独自のシステムと連携し、ユーザーに一部のデータしか操作できないuuidを発行することで解決することにしました。
## ゲームアカウントの仕組み
ゲームアカウントの仕組みは非常にシンプルです。
1. [新規登録] handleを入力すると自動でアカウントが作成される
2. パスワードは自動生成され、dbに保存。ユーザーには表示しない
3. uuidを発行し、それを用いてユーザーはsessionを復元できる
この仕組みをiosアプリに実装することで、ゲームデータの改ざんを防止するゲームアカウントとして利用します。
<iframe width="100%" height="415" src="https://www.youtube.com/embed/jEPkcXtjZ0E?rel=0&showinfo=0&controls=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
## ゲームアカウントの特典
私はゲームデータが改ざんされるとは考えていません。知識を持った大半も、そんな面倒なこと普通しません。ほとんどの人は普通に遊ぶだろうと考えています。
とはいえ、それも楽しみ方の一つとして許容する気持ちもあります。
また、改ざんされたとしてそれで壊れるような仕組みではいけません。ですからそれをされてもいいようゲームを構築しなければいけません。要は前提をどう考えるかです。
私が作っているゲームはai.cardが改ざんできないローカルデータのみを扱い、ai.rseはリモートデータを使うという構造です。したがって、改造もai.rseでしか有効ではありません。
そのため、結果としてより重視されるのはai.cardの方になるだろうと思っています。ai.rseはおまけみたいなものと認識されるのでは。
ai.rseでのデータの扱いは以下のような形になります。
管理者のpdsで作成されたアカウントはゲームデータ改ざんがないものとみなし
1. maxの値を通常アカウントより大きく設定
2. {user}.syu.isのドメイン部分を省略して表示
## ozoneの導入
そうなるとユーザー管理も大変なので、ozoneがあったほうが良いと判断し、ozoneを動かしてみることにします。
[![](/img/atproto_ozone_0001.png)](/img/atproto_ozone_0001.png)
### backend, frontend
ozoneはback, frontの2つがあり、これらを動かす必要があります。
- [https://github.com/bluesky-social/atproto/tree/main/services/ozone](https://github.com/bluesky-social/atproto/tree/main/services/ozone)
- [https://github.com/bluesky-social/ozone](https://github.com/bluesky-social/ozone)
```md
1 ozone /xrpc/* :2585
2 ozone /.well-known/* :2585
3 ozone * :2586
```
このようにすればよいでしょう。
### atproto_pds
注意書きがあり、通常のアカウントは好ましくないようです。
`AtprotoPersonalDataServer`
```diff
diff --git a/lib/identity.ts b/lib/identity.ts
index a8ec3a7..8e4d171 100644
--- a/lib/identity.ts
+++ b/lib/identity.ts
@@ -83,7 +83,7 @@ export function didDocToData(doc: {
const [, id] = s['id'].split('#')
acc[id] = {
type: s['type'],
- serviceEndpoint: s['serviceEndpoint'],
+ endpoint: s['serviceEndpoint'],
}
}
return acc
```
その他のpatchはこちらが参考になります。
- [https://github.com/itaru2622/bluesky-selfhost-env/tree/master/patching](https://github.com/itaru2622/bluesky-selfhost-env/tree/master/patching)
### oauth
これは`atproto`のpatchです。pdsをbuildします。
通常異なるdomain間でoauth認証を行う場合、`fetch-site``cross-site`になります。しかし、今回の構成ではozoneは同一site内で認証が行われるため、`same-site`も許可する必要があります。
```diff
diff --git a/packages/oauth/oauth-provider/src/router/create-authorization-page-middleware.ts b/packages/oauth/oauth-provider/src/router/create-authorization-page-middleware.ts
index f653b0353..45c45fac1 100644
--- a/packages/oauth/oauth-provider/src/router/create-authorization-page-middleware.ts
+++ b/packages/oauth/oauth-provider/src/router/create-authorization-page-middleware.ts
@@ -53,7 +53,7 @@ export function createAuthorizationPageMiddleware<
res.setHeader('Cache-Control', 'no-store')
res.setHeader('Pragma', 'no-cache')
- validateFetchSite(req, ['cross-site', 'none'])
+ validateFetchSite(req, ['cross-site', 'same-site', 'none'])
validateFetchMode(req, ['navigate'])
validateFetchDest(req, ['document'])
validateOrigin(req, issuerOrigin)
```
### user verify
```sh:envs/ozone
OZONE_VERIFIER_URL=https://{PDS}
OZONE_VERIFIER_DID=${ADMIN_DID}
OZONE_VERIFIER_PASSWORD=${APP_PASSWORD}
```

View File

@@ -0,0 +1,51 @@
---
title: "atprotoのsocial-appを作った"
slug: "atproto"
date: "2025-12-07"
tags: ["atproto"]
language: ["ja", "en"]
draft: false
---
blueskyの公式clientがselfhostで動かなくなって数カ月が経ちました。
このままでは不便だと思い、selfhostのpdsでも動くiosアプリを作ることに。
[bluesky-social/social-app](https://github.com/bluesky-social/social-app)をベースに、できる限り最新のコードに追従しやすい形にしています。
1. ライセンスの明示
2. "Bluesky"のロゴや名称を使用しないこと
3. selfhostでも動作すること
4. DM(chat)機能の無効化
<iframe width="100%" height="415" src="https://www.youtube.com/embed/sEv8fNGyM7g?rel=0&showinfo=0&controls=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
## ラインセンス
`social-app`のsrcはMITライセンスで公開されており、カスタマイズしてapple storeに公開することができます。
- [https://github.com/bluesky-social/social-app/blob/main/LICENSE](https://github.com/bluesky-social/social-app/blob/main/LICENSE)
```md
# AIの評価
現在の License.tsx は十分に要件を満たしています。含まれている内容:
1. ✅ 原作者への帰属("based on Bluesky Social App"
2. ✅ 元リポジトリへのリンク
3. ✅ 著作権表示Copyright (c) 2022-2025 Bluesky PBC
4. ✅ MITライセンス全文
5. ✅ 日本語訳(ユーザーフレンドリー)
6. ✅ オリジナルLICENSEファイルへのリンク
```
## アプリ名について
repositoryをai/atから作ったので、`Aiat`になります。
[A]が大文字なのは、iosアプリだからです。ueやiosの名前慣習に合わせています。
## 公開の有無
`bsky.team`の人に聞いてから公開するか決めるか、公開後にアプリを見せるか、どちらかです。
apple reviewが通ればですが。

View File

@@ -0,0 +1,48 @@
---
title: "ue5.7.1のGASPでキャラを切り替える"
slug: "gasp"
date: "2025-12-11"
tags: ["ue"]
language: ["ja", "en"]
draft: false
---
Game Animation Sample Project(通称、GASP)がupdateされています。
今回は非常に良いsampleです。キャラクターのタイプを変更する方法が明確になったためで、個人的にはprojectの方向性を決定づけるのに特に重要でした。
この方法は、暗示はされてはいますが、明確に解説されているわけではありませんので、方法をまとめます。
## GASPのキャラ切り替えが変わった
今回、GASPは2種類の方法を採用しているようで、それが非常に良かった。
具体的には、Typeを入れ替える方法とVisualを入れ替える方法です。
タイプと見た目を入れ替える2つの方法が用意されており、それぞれに[n], [m]keyが設定されています。
<iframe width="100%" height="415" src="https://www.youtube.com/embed/IihZqi5u2AI?rel=0&showinfo=0&controls=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
## 具体的な手順
1. `/Blueprints/GM_Sandbox``Pawn Classes``BP_Walker`を追加します。なお、見た目を変えるのは`Visual Overrides`です。これはほとんど従来の方式と考えてください。
[![](/img/ue_gasp_v571_0001.png)](/img/ue_gasp_v571_0001.png)
2. `/Locomotor/BP_Walker`を開いて、そこに`/Locomotor/PC_Locomotor`の内容を貼り付けます。
[![](/img/ue_gasp_v571_0002.png)](/img/ue_gasp_v571_0002.png)
基本的にキャラ切り替えはこのコマンドで制御されています。初期値は`GM_Sandbox`で設定できたような気がしますが、`PC_Sandbox`のBeginPlayに書いておけばより確実でしょう。
<iframe src="https://blueprintue.com/render/gim70xj1" scrolling="no" allowfullscreen style="width:100%;height:400px"></iframe>
## Dragonの作り方
このDragonは、`Control Rig Sample`にあります。
1. `/ControlRig/Characters/Dragon/SKM_Dragon`を起点としてABP, IK, RTG等色々作ります。
2. `/Locomotor/BP_Walker`を複製し、`BP_Dragon`とします。Meshを`SKM_Dragon`に変更し、ABPを`ABP_Dragon`に変更。
3. 私の場合は、ABPに`DragonIK Plugin`のノードを追加。
4. `BP_Dragon`にあるCameraのLocationを少し調整。

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

View File

@@ -20,6 +20,6 @@
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"@vitejs/plugin-react": "^4.0.0",
"vite": "^5.0.0"
"vite": "^7.2.7"
}
}

View File

@@ -75,7 +75,7 @@ function _server_public() {
function _oauth_build() {
cd $oauth
nvm use 21
nvm use 25
npm i
npm run build
rm -rf $myblog/static/assets
@@ -86,7 +86,7 @@ function _oauth_build() {
function _pds_build() {
cd $pds
nvm use 21
nvm use 25
npm i
npm run build
rm -rf $myblog/static/pds
@@ -95,7 +95,7 @@ function _pds_build() {
function _pds_server() {
cd $pds
nvm use 21
nvm use 25
npm run preview
}

View File

@@ -28,6 +28,7 @@ pub struct OAuthHandler {
}
#[derive(Debug, Serialize, Deserialize)]
#[allow(dead_code)]
pub struct AuthorizationRequest {
pub response_type: String,
pub client_id: String,