‘プログラミング’のエントリ

Silverlightで通信ができないというメールが来た。どうやらSilverlight 2 Beta 1からBeta 2になったときに仕様が変わったとのこと。ローカルPCにSilverlightのコンテンツを置いておいてローカルPC上のサーバにアクセスする際にも,クロスドメインポリシーを考慮しなければならなくなったらしい。どこがクロスだよ,って気もするけど。

早速実験してみる。Silverlight Tools Beta 2を入れる場合,Beta 1のアンインストールが必要なのだが,普通にアンインストールしただけではだめで,更新プログラムの一覧からKB949325を直接消さないといけないというのにはまりつつ,インストール完了。微妙にWatermarkedTextBoxが消えてたりするのに困りつつ実験開始。

確かに以前と同じコードでSocket通信すると,AccessDeniedになってしまう。ということでクロスドメインポリシーサーバをたててみる。FlashのSocket通信のときに同じようなことをやってたのでほぼ流用。ポート943で,「<policy-file-request/>」という文字列を受信したら以下のような文字列を送信するサーバをたてればOK。許可ドメインはちゃんと絞り込まないといけないけど。

<?xml version="1.0" encoding ="utf-8"?>
<access-policy>
 <cross-domain-access>
  <policy>
   <allow-from>
    <domain uri="*" />
   </allow-from>
   <grant-to>
    <socket-resource port="4502" protocol="tcp" />
   </grant-to>
  </policy>
 </cross-domain-access>
</access-policy>

結局,Socket通信は以下のような感じになる。

  1. Silverlightクライアントからサーバの943ポートへ,フレームワークが勝手に「<policy-file-request/>」を送信する
  2. サーバの943ポートからSilverlightクライアントへ,クロスドメインポリシーを返信する
  3. Silverlightクライアントからサーバの4502-4532ポートへ通信

ロビーでSJIS以外の文字を使えるようにしていろんな文字が使われていたが,どうも変な文字が入るとGulimフォントなど(Vistaの場合)になってしまう。いろいろ実験してみると,VistaのWordPad(RichEdit 5.0)では,デフォルトのフォントをメイリオにしているとちゃんと変な文字もメイリオになるが,RichEdit 2.0だとGulimフォントなどになってしまってメイリオに変更してもフォントが変わらない。とりあえず致命的なわけでもないのでしばらくはこのままか。


ウェザタイのIPv6実験は成功。今のままでも,例えばVista-Vistaで対戦をするとIPv6アドレスで対戦ができる。これで通信部分を作り直す必要はなくなった。


ロビーに入り浸っていると,どうも対戦中に落ちる現象があるらしい。ちょっと調べてみて怪しい部分を修正。文字コードを変換するとき,変換前にいちいちsetlocaleして変換後にsetlocaleを戻していたのだが,そのあたりで落ちる。前のノートの時は起きてなかった気がするのでマルチコアで起きやすいのかも知れない。とりあえずsetlocaleはデフォルトでは全スレッドに効くので,プロセス起動時に行うようにしたら落ちなくなった。

Weather Typingの開発版をこっそり公開。経緯としては,掲示板に報告があがっている問題の対応が発端。掲示板に挙がっている問題は,NICOLAで高速打鍵が誤入力になってしまうというもので,右親指キーを使った入力から左親指キーを使った入力を高速に行うと,ミスになってしまう。これのせいでNICOLAでの入力が遅くなってしまう方も多いだろうということで急遽開発版を公開することにした。

注意点は以下の通り。

  • 公式版とは違いちゃんとしたテストはしていません。最悪の場合,スコア等が消えてしまう可能性があるので,必ず旧バージョンのWeatherTypingフォルダごとバックアップをとっておいてください。
  • 旧バージョンからバージョンアップする場合,旧バージョンのフォルダに新バージョンのファイルを上書きすることで,旧バージョンの設定を引き継ぎます。
  • 旧バージョンからバージョンアップする場合,既にその日のロビーチャットログがあれば,リネームしておいて下さい。(例:2008/6/8ならchat20080608.logをリネーム)リネームしない場合,バージョンアップした日のチャットログだけ文字化けします。

修正点は以下の通り。

  • ファイルオープンダイアログをXP/Vista標準のものに変更
  • アイコンを変更
  • 対戦開始時のプレイヤー情報表示画面で,IPアドレス表示部分にIPv6のアドレスも表示する
  • 右親指キーを使った入力から左親指キーを使った入力を高速に行うと,ミスになってしまうのを修正
  • スコアファイル名を変更した場合,スコアアップロードとロビーのレベル表示で正しいスコアファイルが使われないのを修正
  • CPU入力方式とPlayerの入力方式が同期しなくなる場合があるのを修正
  • 対戦の接続待ちの際,途中でエラーが発生しても待機し続けていたのをエラーメッセージを表示するように変更
  • ロビー。SJIS以外の文字を使えるようにする。但し旧バージョンのロビークライアントからは見えないので注意
  • ロビー。チャットのログファイルをUnicodeに変更

DirectPlayのヘルプを見ていると,どうもDirectPlayは9からIPv6をサポートしていることが判明。Weather Typingでも今のままでIpv6に対応できている。ような気がする。検証中。

ぱじさんのプロジェクトに対応して,ロビーサーバをほぼ作り直した。ユーザ関連をデータベースを使用するようにしたのと,永久部屋とかもろもろ。大分コードもすっきりした感じ。しばらくテストしたらウェザタイのロビーサーバを更新してみよう。

新プロジェクトのための3Dモデリング修行として,Weather Typingのアイコンを一新。最近はアイコンも3Dモデリングの時代なので,いつまでもXP時代の古くさいアイコンなんか使ってられない。

Metasequoiaでモデリング,Riosでレンダリング,IcoFXでアイコン化することで,割といい感じのができた。すぐにでも公開したいところだが,肝心の本体が完成していない。ロビーも公開待ちの状態なので,早いところ作らないと。

Denasu新規プロジェクトについて,ぱじさんとオフライン会議。いろいろ決まったような,決まらなかったような。完成すれば面白いと思う。

ロビーサーバ復旧完了。


Silverlight。TextBoxのスクロールできないのかな,と調べてみた結果,ScrollView ElementにTextBox Elementを入れればいいことが分かった。これにVerticalScrollBarVisibility="Auto",ScrollView.ScrollToVerticalOffsetを組み合わせれば一通りのことができる感じ。

Silverlight版ロビーサーバをローカルではなくWebサーバ上に置いて実験してみた。でもロビーサーバに接続しようとするとAccessDeniedが返ってくる。Webで検索するとSilverlight 2 beta 1 and Socket Exception: Access Deniedというページに原因が書いてあった。どうもサーバのドメイン名の逆引きができないとダメらしい。まあIPアドレス指定すれば使えるから実験としてはいいか。Silverlightの正式版ではこの辺りの制限は緩くなるっぽいし,何か作って公開するまでには正式版が出てる,かなあ。


第1ロビーサーバが停止している間にロビーサーバの気になっていた箇所を修正している。Unicode正式対応とか英語化とかゲームごとにサーバを分離とか。なので第1サーバ自体が復旧してももうしばらく第2サーバをメインにしておくかも。

ロビーサーバ停止中。HDDが死んだらしい。OS入れ替えて設定して,ロビー動かして,になるので復旧はしばらく先。

Silverlightの実験として,ロビークライアントを作ってみる。Silverlight 2.0からは日本語入力とSocket通信がサポートされたので,なんとなくうまくいった。でも使用できるポートが4502-4532に制限されているので,そのままではウェザタイのロビーサーバには接続できない。まあSilverlightでネット対戦ゲームは作れそうってことで。

以下画面キャプチャ。IEの中でロビークライアントが動いている。ホントはぱじさんのFlashクライアントと同時接続して,JavaのサーバにC++/Flash/Silverlightクライアントから同時利用,というわけのわからない画面が欲しかったんだけどとりあえずここまで。

2008040601


Silverlightの開発環境があまりに混沌としているのでメモ。以下を使えばSilverlight 2.0開発,実行が可能(必須ではないが)。

だいぶ前からウェザタイの通信機能を再設計している。なんせウェザタイが使っているDirect Playは廃止が決まってるしIPv6対応予定もないし。ということで,どうせ互換性がなくなるならリプレイの分割とか途中ワード切り替えとか考えているのだが,いったいいつになるのか。

まあそれはおいておいて本題。P2Pのネット対戦の方式を自分で検討していると,今まで不思議だったDirect Playの挙動がよく分かる。今はもうないようだが,数年前,むなしいさんのウェザタイページに,私も知らないウェザタイの挙動が書いてあった。例えば,プライベートIPアドレスの人は1人なら混じっててもOKとかプライベートIPアドレスの人は2番目に入らないとダメ,とか。当時は理由が分からなかったが,今なら何となく分かる。

#簡単に今の憶測を書くと,4人対戦の場合,実は3人がホストになっていると思われる。というかP2Pの4人対戦だと,必然的に3人がポートを開かないと対戦ができないはず。で,DirectPlayの場合,2番目に入った人だけが本当のクライアント,つまり自分ではポートを開かず,他の人のポートにつなぎにいくだけ,になっているのだろう。つまりウェザタイのマニュアルとかFAQは少しウソが混じっているとも言えるわけだが,まあ今更ですよね。

World Tester 1.3を公開。といっても新機能はほとんどなし。裏でちょこちょこやっていた外部仕様と関係ない修正が中心。Weather Typing もいろいろ修正はやっているのだが,公開できる状態にはなっていない。

昨日書いていたロビーから落とされる現象について。どうもファイルの入出力に時間がかかっていることが分かり,その辺を改善して,しばらく様子見。


様子見がてら,久々にロビーに入り浸ってみる。TOD2(サ・タイピング・オブ・ザ・デッド2)体験版の話題が多いのだが,スペックが足りない人が続出しているっぽい。多分ゲーマーにとっては当たり前のスペックなんだろうし,SEGAも普通のゲームと同じ感覚で作ってるんだと思うが,TOD2に関してはタイピング練習が目的の一般的なユーザも買うわけで,そこにずれが生じそう。製品版はどうなのだろう。

その他既にいろんなところで言われていると思うが,箇条書き。

  • Loadingが長い。家のノート(Core2 Duo 2GHz/NVIDIA GeForce 7950 GTX 512MB)だと37秒。ゲームが始まってしまえば快適なのだが,ドリルが一回終わる度にLoadingが必要なのでめんどくさい。
  • ドリルの途中キャンセルができない
  • 他のノート(Core2 Duo 1GHz/945GMS Express)だとカクカク。まあオンボードだからそれでもいいんだが,スペックが遅いとゲーム内時間も遅くなって,とんでもなくいい結果が出る。これだとネット偏差値とかとっても意味ない気が。

#その後製品版でAlt+F2でドリルキャンセルできるのを確認。体験版はどうだったかなあ。

ロビー。1年くらい前から出ている,ロビーから落とされる現象を調査しているが,未だ原因分からず。とりあえずここにコードを載せてみる。いろいろ省略してるけど,イメージ的にはこんな感じ。ロビーのユーザ名とパスワードを管理するクラス。

public class LobbyTable
{
    Map _users = new HashMap();

    public LobbyTable()
    {
        // ファイルからユーザ名とパスワードを読み込んで_usersを初期化。
        // 実装は省略
        load();
    }

    public synchronized boolean login(String name, String password)
    {
        if(_users.get(name) == null)
        {
            _users.put(name, password);

            // ファイルにユーザ名とパスワードを書き込む
            // 実装は省略
            save();
        }
        else
        {
            if(password.equals((String)_users.get(name)))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

    public synchronized void changePassword(String name, String password)
    {
        _users.put(name, password);

        // ファイルにユーザ名とパスワードを書き込む
        // 実装は省略
        save();
    }
}

で,発生するエラーが以下。

java.lang.NullPointerException
   at Lobby.LobbyTable.changePassword (LobbyTable.java:91)
   …

HashMap.putの引数は2つともNULL可なのでnameとpasswordは関係ない。実際デバッグコードを入れてもNULLにはなっていない。java.util.HashMapのソースコードを見ても特にNullPointerExceptionが発生しそうなところはない。残るのは_usersがNULLの可能性だけだが…。同期処理で失敗して,っていうのが考えられそうだが,それだとsynchronizedMapを使えば解決するのかもしれない。でも原因が分からないまま変えるのも気持ち悪い。

発生確率はかなり低め。ロビーが混んでるときに起こりやすいかも知れない。Javaのすごい人からのツッコミを期待して…。

Visual Studio 2008 英語版を使用しているのだが,いつからか,日本語を入力すると,変換中の文字のフォントが小さくなるようになった。変換が確定すると普通の大きさになる。とりあえずVisual Studio 2008をImmSetCompositionFontでブレークしてみる,どうも本来はMSゴシックが使われるところが,メイリオが使われているっぽい。HKCUレジストリのVisual Studio 2008関連を削除しても直らないので,Vistaの何かの設定を見ているようだが…。原因不明。

スキー場2日目。すごい吹雪。ふと手元を見ると雪の結晶が肉眼で見える。結晶は顕微鏡で見るものと思ってたのでちょっとびっくりしたが,フラクタルだからかあ,と思うと何となく納得した。どこまで大きく作れるんだろう。


掲示板にロビー不安定の報告が挙がっていたので,高速バスからロビーサーバ再起動を試みるが,SSHログインがなぜかできなかった。残念。

スキーの物理シミュレーションのため(なのか?)蔵王へ。ちゃんと摩擦で曲がるようにするのはなかなか大変そう。

Weather TypingのFAQだが,ふと読んでみると変な箇所が。「まず DHCP でプライベートアドレスを自動設定にしている場合は,手動設定にして IP アドレスを固定します。とりあえず現在設定されている IP アドレスに設定しておけばよいと思います。」いや,そりゃまずいだろう。勝手にDHCPのIPアドレス振っちゃったら他のPCとかぶってしまう。

Weather Typingのマニュアルも結構前に作ったものなので今見返すと結構変なことが書いてある。ということで次バージョンで全面見直しが必要か。って次っていつになるんだろう。

World Testerは行列計算をDirectXを使っているのだが,そのせいで計算精度がfloat型になっている。そこでdouble型で計算したらどのくらい精度が上がるかを知りたくなったので行列とベクトルとクオータニオンを実装してみた。結果は結局あんまり変わらなかった。

せっかく作ったのだが速度が遅いのでやっぱりDirectX使用に戻すか,SSE2を使って速度を上げてみるか考えているところ。

Visual Studio 2008インストール完了。とりあえずβではビルドが通らなかったWorld Testerが通るようになっていた。

Microsoftのダウンロードページから巨大なファイルをダウンロードしようとすると,ダウンロード マネージャ使う? ていうリンクがある。Vistaでこのダウンロード マネージャを使い,デスクトップにファイルをダウンロードしたのだが,ダウンロードしたファイルが見つからない。実行してみると仮想CDにマウントはできるので,どこかにあるはず。と思ってProcess Explorerでオープンハンドルを検索。結局以下の場所に見つかった。すごいパス。IEの保護モードで保存したファイルはここにあるっていうのは有名な話なのだろうか。

C:UsersusernameAppDataLocalMicrosoftWindowsTemporary Internet FilesVirtualizedCUsersusernameDesktop

「Visual Studio 2008 Beta 2」をインストールしてみた。Silverlight 1.1開発をやってみよう。てことで「Microsoft Silverlight Tools Alpha for Visual Studio 2008 Beta 2」をインストールしようとしたが,以下のエラーでインストールできない。

You must install Microsoft Visual Studio 2008 Beta 2 before installing this product.

結局Visual Studio 2008のVisual Web Developerを選択していなかったのが原因だったのだが,どうやって調査したかをメモしてみる。

テンポラリフォルダにあるSilverlight Toolsインストーラのログを見ると,CA_CheckVSカスタムアクションで失敗している。で,テンポラリフォルダに展開されたsilverlighttools_vs.msiをWindows SDKのorcaで開いてみると,CA_CheckVSはMSWAPP.DLLというファイルの存在(とバージョン)をチェックした結果,なければエラーメッセージを出すようになっている。そこでVisual Studio 2008のvs_setup.msiを同様にorcaで開いてみると,MSWAPP.DLLは「Visual Web Developer」機能に含まれていることが分かった。つまりVisual Web Developer機能を選択しないとSilverlight Toolsはインストールできない。てかVisual Web Developerが必須なんてどこにも(かどうかは分からないけど?)書いてないじゃん。

何故か夏休み。今月最初にロビーサーバをバージョンアップして様子を見ていたのだが、今日ロビーを覗いてみるとログインしにくくなった方がいる模様。それっぽい箇所を直しておいたのでしばらく様子見。

Flash対抗技術と噂のsilverlightが公開されたということで,Expression Blendを使ってみた。MSらしからぬ画面デザイン。使い方はよく分からなかったけど,いろいろ試してみたい。のだが,MSDN Professionalでは配布されないのか。Developper Toolsに分類されてるんだからProfessionalでも配布してくれればいいのに。

Weather TypingもWorld TesterもせっかくUnicode化したんだし,ってことでロビークライアントを英語対応にしてみた。あとは…Weather Typing本体は英語化むずいけど,World Testerは英語化できるかな。

CPU対戦の入力方式,まだおかしい。入力方式を同期するにしておいて,CPU対戦ページを一度も開かずにプレイヤーの入力方式を変更してOKを押すとCPUの入力方式が変わっていない。ver2.1.1でも同様。なんか,CPU同期機能は仕様が複雑になりすぎてどうにもならなくなってきてる気がする。いっそver2.1.1のときに互換性を切って入力方式同期なしで統一してしまった方がよかったのかも。まあちゃんとテストしろって話ですけど。

一応,プレイヤーの入力方式を変えた後CPUページを一度開けばOKという回避ができるので,対策版を出すのはもう少し後にしようかと思う。


そういえばver2.1から一部の文字列に日本語以外の文字が使えるようになったというのを,マニュアルに書き忘れていた。ちなみに使えるのはファイルのパスくらいで,プレイヤー名とかワードの中身とかロビーの発言とかはまだ。現ロビーでハングル文字とかを入れるとサーバから強制切断されてしまうので注意。

Weather Typing 2.1.2を公開。変更点は以下の4点。

  • プレイヤー名に全角で12文字入力できるようになっていたのを半角換算で12文字に修正
  • ロビーからWeather Typingを起動した場合,ゲームを開始しても「対戦中」にならなくなっていたのを「対戦中」になるように修正
  • CPU対戦の入力方式をユーザに同期させないようにし,CPUの入力方式を変更し,ルールタブ,CPU対戦タブの順に移動するとCPUの入力方式が元に戻っていたのを,戻らないように修正
  • ロビー,発言ボックスを縦に少しだけ広げる

現在Unicode化の第2段階とかコモンダイアログとアイコンのVista化とかしているのだが,安定していないので今回の修正版には入っていない。並行開発はなかなかめんどくさい。


ロビーで宣伝していたら,プレイヤー名についてつっこみが入ったので補足。ver2.1のときから,プレイヤー名の最大長がいわゆる半角12文字じゃなくていわゆる全角12文字になっていた。つまり全て全角で入力すると6文字長く入力できたことになる。これだと画面からはみ出てしまうので,今回のバージョンで以前の仕様に近い形に戻した。

で,ロビーでつっこみが入ったのはロビーのハンドル。こっちも12文字使えるようになっていたのだが,今回の版ではあえて対策はしなかった。長くなっても特に実害はないため。

#とはいうものの以前ロビーで「長い名前を使えるようにして欲しい」という要望があって,通信量が増えるので却下した覚えがある。まあ,当時は通信回線が遅くて通信量を気にしてたけど,今の回線なら全然問題ないってことで。


ぱじさんからWeather Typing Flashの第2弾が届いたので入れ替えておいた。

久々にロビーに行ってみた。そこでいくつかバグ報告を受けたのでメモ。2番目は結構大きいので対策版を出す予定。

  • CPU対戦の入力方式をユーザに同期させないようにし,CPUの入力方式を変更し,ルールタブ,CPU対戦タブの順に移動するとCPUの入力方式が元に戻っている
  • ロビーからWeather Typingを起動した場合,ゲームを開始しても「対戦中」にならない

Weather Typing 2.1.1を公開。変更点は以下の2点。

  • 入力方式がQWERTYの場合,キー配列のaiueonがカタカナになっていたのを修正
  • プレイヤーの入力方式とCPUの入力方式が中途半端に同期していたのを改善

ちょっと面白かった出来事。職場で外国の方が日本語のソフトを使っていたのだが,ユーザ情報登録で「・・・で間違いはありませんか?」というダイアログで「いいえ」を何度か選択して悩んでいた。英語を少しでも知ってると分かる気がするが,間違いはないから「いいえ」を選択していたわけで,なんでダイアログが終了しないのかが分からなかったわけだ。ユーザインターフェース的にいうと「・・・で正しいですか?」みたいな肯定の表現にしておけばこんな混乱はないわけで,なんかUI設計のパターンに入りそうな感じがした。

Weather Typing 2.1World Tester1.2を公開。Weather Typingについては,かなり長い時間をかけて大幅に変えたのだが,機能的にはほとんど変えていない。98系を対象外にしたのが一番大きい変更点かも。とりあえず今回のバージョンでの変更が今後のバージョンのベースになっていくとかそんな感じ。World Testerはいろいろいじってみた。ホントはデフォルトのフィールドを増やしたかったのだが,そこまでは間に合わなかった。

Weather Typingのテスト項目を消化しているのだが,いくつかバグを発見。元々あったバグもあるけど。そのうちの1件はなかなか興味深いのでメモ。

例えば以下のコードがあったとする。"abcあ"はSJISなら半角5文字なので6文字書式に入る。

printf("%-6s", "abcあ")

しかし,これを何も考えずにUnicode化すると

wprintf(L"%-6s", L"abcあ")

L"abcあ"は(多分)8文字分になるので6文字書式からオーバーしてしまう。…という記述はMSDNには見つからなかったんだけど,実験上そんな感じになっているっぽい。結局桁がずれることになる。

# その後実験してみると,上に書いたのとはちょっと違って,%6sはUnicodeで6文字,足りない分は半角スペースで埋めるという微妙な動作だった。つまりいわゆる全角文字が含まれると固定幅にはならないので,位置合わせに使うときは注意が必要。

解決策は…どうやるんだろう。結局文字列引数を1個ずつ分けて描画するみたいな非効率な方法にしてしまった。