アクセス制限の話

どれほど活用されているのか知らないが、サーバにはアクセス制限機能がある。当初はなかったものだが、荒らし行為をする人がいるので追加した機能である。わざわざデュエルオンラインで荒らし行為をする人がいるとはねぇ…
アクセス制限にはその運用上の難しさがあるのだが(どの程度の行為を荒らしとみなし制限をかけていくのか、いつ解除するか等々)、それはおいておいて、ここでは技術的な話だけしておく。
自分のサイトの掲示板とか管理したことのある人は知っていると思うけど、通常、アクセス制限は「IPアドレス」か「ホスト名」で行われる(本質的には同じものということで話を進める)。というか、逆にそれら以外に使える情報がない。しかし、これらによる制限に問題が多いことはわざわざ私が言うまでもないくらい周知のことである。
IPアドレスは一定ではなく、相手の接続が変われれば変わることがある。したがって、特定の相手を制限しようとしてもすり抜けられてしまうことが多い。その対策として、制限したい相手の使っているプロバイダーごと制限してしまうという手があるが、それは無関係の人のアクセスまで制限してしまうという問題がある。これIPアドレスを使う限りどうにもならないことである。このため、掲示板で思うようにアクセス制限をかけるのは難しい。
さて、で、私は考えた。デュエルオンラインのサーバのアクセス制限はどうするか。IPアドレスは当然わかっているので、それで制限することは簡単だが、それでは上記の問題はそのままである。幸い(?)、サーバに接続するクライアントであるデュエルオンラインも私がつくっているソフトである。ということは、何か相手を特定できる情報をデュエルオンラインから送ってやって、それをキーにアクセス制限をかければいいのではないかと考えた。いけそうである。
となると、次の問題は「相手を特定する情報として何を送るか」である。一番最初に思いついたのは「レジストリに何か書いておいて、それを送る」というものである。サーバでシリアル番号のようなものを管理して、それを各パソコンのレジストリに書いておいて、サーバ接続時に送るというわけである。レジストリが空ならサーバから新しいシリアル番号を与えてやればよい。
発想は良さそうだったが大きな問題があった。「サーバは誰でも立てられる」ということである。これではシリアル番号の管理はできない。それとレジストリをいじることに嫌悪感を抱く人がいることも知っていたので、この案ばボツとなった。
次に考えたのは、パソコンの中から、そのパソコンを特定できるような何らかのシリアル番号のようなものを抽出するというものであった。「そういえばWindowsXPアクティベーションでそんな話を聞いた記憶が」と思い、調べてみると使えそうな情報があることがわかった。そして、その中から比較的簡単に取り出せて、変更が難しい2つの情報を取り出してサーバに送ることにした。それが今のバージョンに入っているものである。何を送っているかはあえて秘密ということで(たいしたものは送ってない)。「プライバシーの侵害」ということを言う人もいるかもしれないけど、そういう人は遠慮なく文句を言って欲しい。
「これで完璧!」というわけではない。今の仕掛けでも知識のある人であればアクセス制限をすり抜けることはできる。少なくとも私は(作者であるということを抜きにしても)技術的にできる。あるいは、無関係の人に制限をかけてしまう可能性も0ではない。
ただ、サーバを管理している人がアクセス制限をかけようと思ったときはIPアドレスやホスト名ではなく、サーバのアクセス制限の説明の「謎の文字列」って奴を使った方が精度がいいということは知っておいて欲しい。

カードデータの持ち方

今日も「なぜ、長きにわたり要望されている機能が実現されていないのか?」という疑問に対しす言い訳をしておきたい(←言い訳なのにえらそうに)。
だいたいどのソフトも最初に考えるべきことはデータをどういう構成で持って、どう管理するかという点である。デュエルオンラインにおけるデータとはもちろんカードデータのことである。
フィールドにどんなカードがどんな状態で出ていて、墓地にはどんなカードがあり、手札、デッキには何が入っていて、除外されたカードは何かというものを正確に管理する必要がある。
一番ややこしいのはフィールド上だ。カードの状態がころころ変わるので、そのデータ管理は面倒だ。でも、逆にその分神経質につくってある。そして、問題となったのは手札とデッキである。
私は大きな勘違いをしていた。ルールや効果にまだ詳しくなかった私は「デッキ、手札、墓地に相手のカードが入ることはない」と勘違いしていた。当時、「相手にコントロール奪われたカードをペンソルで手札に戻すと持ち主の手札に戻る」、「コントロールを奪っている相手カードを破壊すると持ち主である相手の墓地に落ちる」というルールがあることから、墓地や手札に相手のカードが入ることはないし、デッキも同様だと勘違いしたのだ。
そこで、私は手札、デッキ、墓地ではカード名だけ覚えておけばよく、その他の情報は記憶しておく必要はない。そして、手札、デッキ、墓地のカードはすべて自分のカードとして処理すれば良いと考えて設計してしまったのだ。
だから、プログラム的には、カードは手札や墓地からフィールドに出たときにようやく名前だけでなく様々な属性を持ったカードデータになる。攻守の変更もできるし、コントローラの変更もできる。しかし、手札、デッキ、墓地では名前以外ことは記憶していないので、他の属性の操作はできない。
したがって、相手のカードを手札に入れたり、デッキに入れることは今でもできない。これは完全に設計ミスである。私が様々なカードの効果を知らなかったことが原因だ。私は「他人のカードを手札やデッキに入れたら、混ざってしまって後で困ることになる。だからまぜることはないはずだ」と勝手に思っていた。そういう意味では遊戯王のルールは私の理解を越えていた。それがいいことだとはあまり思えないのだが。
というわけで、相手のカードを手札やデッキに入れるのが難しいという状況はどうにもならない。データ構造の変更は変更部分が多過ぎて私もどれくらいの作業になるかわからないのだ。
今の枠組みでうまくやるために、カード名に小細工して区別するようにするというのも検討したのだが、いい案は浮かばなかった。本当に申し訳ないと思っている。私がもっと色々なカードの効果さえ知っていれば…

サーバの開発目的

言うまでもなく、

  1. 対戦の接続を簡単にする
  2. プライベートIP同士の対戦を簡単にする

がサーバの開発目的である。個人的には「軽いチャットが欲しかった」というのもあるけど。
とりあえず、1つ目の目的を最初のバージョンで実装した。最初にリリースしたサーバは1日でつくったと言えば、驚いてくれる人はいるだろうか。チャットを接続の自動化だけなら、正直さほど難しくはなかった。前々から構想はあったので、私の頭の中では設計は終わっていたし。
「接続を簡単にするのは、独自にサーバを立ち上げない限りどうにもならない」という思いは開発当初からあったことで、それを実装しただけだった。IGMなんていうものもあったので、これがもっと使えるものならそれでも良かったんだが。こちらの細かいバージョンアップに対応してもらえるわけじゃなかったのであきらめた。
しかし、サーバの重要性は2つ目の目的こそにあったと思う。今までやりたくでもできなかった人と対戦できるようになったのだから。今でも観戦できないのは問題なんだけど。プログラム的にはさほど難しいことをしているわけではない。サーバ経由で対戦している人をデータで管理しておいて、その間のデータのやり取りをしているに過ぎない。技術的にはたいしたことではない。デュエルオンラインの方は、両方ともクライアントモードで(通常のポートとは違うポートで)サーバに接続しているだけでプログラム的にはほとんど変更なしだし。
もっとも、この「両方クライアントモード」というのが観戦機能の実装を困難にしているのだが。ちょっと解説しておくと、観戦はサーバモードのデュエルオンラインに第3者が接続したときに起動し、サーバモードのデュエルオンラインからデータを送ることで実現している。したがって、両方クライアントモードではデータを送る人がいなくて、また別の観戦モードなるものをつくらないといけないのである。それが結構面倒というわけだ。もちろんいずれは実装したいと思っているのだが。
手前味噌だが、サーバの登場はデュエルオンラインの環境を一変させたと思っている。サーバの無かった時代を思い出すのも難しいくらい。それだけに、私自身がサーバを運営できる環境にないのが残念である。

サーバのバージョンアップをしたところで

頭はサーバモードになっているので、サーバに開発経緯を書いておこうかと思う。開発の順序からいけばかなり後の話なのだが。まあ、通信関係の話の続きとしては悪くないし、何よりあまり気にしないで書きたいことを書くということで。