忍者ブログ
え?全力で生きているかって? ――答えはYesだ。当たり前だろそれが人生なんだよ!!
[491]  [490]  [489]  [488]  [487]  [486]  [485]  [484]  [483]  [482]  [481
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

正直ちょっと飽きてきた。。。最近やってねぇ。



とりあえず誰も必要としてないソース公開。メールサーバーの記事書いてる時にはできてたけど、ちょっと動作に難ありで放置してた。だが修正するのも面倒になったからもうとりあえずこのまま公開。



…まぁ、チャットとかそういうのってそもそもMineCraftのシステム自体に用意されてるから、いちいちマシンを介してやる必要もないと思うが、それを言っちゃぁすべておしまいだからね。



動作だけど、もう簡単。打った文字をrednet.broadcast()で配信しまくってrednet.receive()で受け取りまくるだけ。

ここで、rednet.broadcast()の説明をちょっと。

これは、receive()状態にある周囲のマシン全部にメッセージを送信するメソッド。receive()状態じゃないともちろん受信はできない。

ここでちょっと疑問が湧くよね。receive()状態の時ってなんもできなくなるんちゃうん?って。いつメッセージ送れるんだよって話になる。

普通にやるとそうなるわけだが、今回はメッセージ送るメソッドとメッセージ受信するメソッドを並列に動作させてやることで、メッセージのやりとりがskypeみたいにできるようになっている。ワイルドだろぉ〜?



まぁとりあえずソースを晒そうか。

今回の名前はminechatでいく。以下ソース



MY_ID=os.getComputerID()
--os.getComputerID()で、使用しているマシンのID取得が可能
 
print("------------------------------")
print("  MineChat  created by kim")
print("------------------------------\n")
 
print("exit : type exit()\n")
 
print("press enter...")
str=read()
 
for i=1, 30 do
    print("\n")
end
--ここのfor文はあとで解説①
 
--cursor set
--これも後で説明②
cx,cy=term.getCursorPos()
 
--login send
--minechat起動してる人全員に「俺ログインしたぜ」って言うだけ
rednet.broadcast("#"..MY_ID.."is Online!")

 
--send message
--メッセージ送信メソッド
sendmsg=function()
    while true do
        --メッセージ入力待ち
        write("me> ")
        msg=read()
 
        if msg=="exit()" then
           --exit()って入力された時はminechat終了
           rednet.broadcast("#"..MY_ID.."is Offline...")
           return 
        else
           --それ以外だったらメッセージ送信
           rednet.broadcast(msg)
        end
    end
end
 
--get message
--メッセージ受信メソッド
getmsg=function()
    while true do
        --waiting message
        local event,id,msg=os.pullEvent("rednet_message")
 
        --message show
        term.setCursorPos(cx,cy)
        --カーソルの位置指定。後で説明③
        write(id.."> "..msg.."\nme> ")
        --受信したメッセージ表示
    end
end
 
parallel.waitForAny(sendmsg,getmsg)
--これで並列実行できる。後で説明④



ソース以上



後で説明することが多くなってしまっためんどくさい

まず①と②の部分。謎の改行。

このターミナルでは、表示する時のカーソル(以下表示カーソル)と入力する時のカーソル(以下入力カーソル)の位置がイコールじゃないらしい。

どういうことかを具体的に説明するのが難しいのだが、例えば


1 me> |
2
3
4

の状態で入力待機してたとする。左の数字は行数で | がターミナルに表示されてるカーソル。

今の状態で入力カーソルが | と同じ位置。で、文字入力してenter押したとする。

1 me> hello!
2 me> |
3
4

するとこんな感じ。この状態で24番からメッセージ受信したときに、

1 me> hello!
2 24> hi
3 me> |
4

ってなってほしいけど、実際は、

1 24> hillo!
2 me> |
3
4

みたいに、自分が打った文字の上に上書きされちゃう。これは、表示カーソルが1行目1文字目の位置にあるから、そこから相手のメッセージを表示しちゃうみたい。

その逆に、受信したメッセージの上に自分が上書きしちゃう時もある。



こういうのを回避するために、一回画面下まで全部改行してやって、画面左下に表示カーソルと入力カーソルを持って行ってやった。それが①の部分。

この状態でカーソルの位置取得。②の部分がそれ。



改行してからやるとこうなる。

仮にターミナルが20行のものだったとして、

16
17
18
19
20 me> |

で、文字入力してenterすると、

16
17
18
19 me> hello!
20 me> |

ってなる。メッセージ受信すると、カーソルの位置を設定してからメッセージを書き出す。さっき②で取得したカーソルの位置を③の書き方で指定。この例でいくと20行目1文字目から文字を表示していく。つまり20行目の m の部分に表示カーソルが行く。 

この状態で、相手ID> 相手メッセージ を書いてやると、20行目のme> の部分も上書きされて

16
17
18
19 me> hello!
20 24> hi

で、さらに \nme> を書かせてから入力待ち状態を作ると、

16
17
18 me> hello!
19 24> hi
20 me> |

ってなる。これなら問題ないよね。



で、今回一番重要なのが④の存在。これで、受信メソッドと送信メソッドの並列実行を行なっている。

ちなみに、parallel.waitForAny()とparallel.waitForAll()の2種類がある。

Any()のほうは、どれか一つでもメソッドがreturnしたら動作終了

All()のほうは、すべてのメソッドがreturnしたら動作終了

という感じ。

今回は、入力メソッド側がexit()って打った場合のみ終了したいわけだから、Any()のほうを使ってる。

動作ごとにメソッド用意してこれ書くだけで簡単に並列実行できるのは素晴らしいですね。





で、ここで一応今回の問題点を言っておく。

冒頭にも言ったとおり、今回はbroadcast()を使ってるから、周囲でreceive()状態になってるマシンすべてにメッセージが行く。

それはreceive()してるマシンは例外なく届くわけで、前回作ったメールサーバーにもメッセージが行くわけだ。

つまり、このプログラム使うときははメールサーバーがない環境かもしくはメールサーバーとは別の場所じゃないとまずい。全メッセージをメールサーバーが受信しちゃって超めんどくさい。逆に会話ログは取れるけどねw



だから、メールサーバーに干渉しないものを作ろうとすると、やっぱりsend()を使ったやり方じゃないと無理っぽいかな。でもsend()は送る相手一人だけだから、サーバーを一つ用意して、ログイン管理とかした上でメッセージをそれぞれ良い感じにみんなに配布していくようなプログラムを書くしか無いかな。



ってなことを考えてめんどくさくなってやめたわけ。



まぁそこまで大したプログラムにはならないと思うので、気が向いたらまたやります。



以上。
 


PR
この記事にコメントする
お名前
タイトル
文字色
メールアドレス
URL
コメント
パスワード   Vodafone絵文字 i-mode絵文字 Ezweb絵文字
カレンダー
03 2024/04 05
S M T W T F S
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
カウンター
プロフィール
HN:
Mugen
性別:
男性
職業:
社会人だよバカヤローー!!
趣味:
ピアノ、アニメ・音楽鑑賞、ネットサーフィンとかとか
自己紹介:
ただの車好きな変態です。

twitterもやってますんで、よければリンクからドゾー
Twitter




最新CM
[01/14 FreddieSpemo]
[01/13 FreddieSpemo]
[01/13 FreddieSpemo]
[12/21 réplique cartier bracelet]
[12/16 van cleef and arpels alhambra diamond necklace knock off]
バーコード
最新TB
ブログ内検索
アクセス解析
忍者ブログ [PR]