App-phoebe
view release on metacpan or search on metacpan
lib/App/Phoebe/Ijirait.pm view on Meta::CPAN
} } );
sub init {
my $next = 1;
$data = {
people => [
{
id => $next++, # 1
name => "Ijiraq",
description => "A shape-shifter with red eyes.",
fingerprint => "",
location => $next, # 2
ts => time,
} ],
rooms => [
{
id => $next++, # 2
name => "The Tent",
description => "This is a large tent, illuminated by candles.",
exits => [
{
id => $next++, # 3
name => "An exit leads outside.",
direction => "out",
destination => $next,
} ],
things => [],
words => [
{
text => "Welcome!",
by => 1, # Ijirait
ts => time,
} ],
},
{
id => $next++, # 4
name => "Outside The Tent",
description => "Youâre standing in a rocky hollow, somewhat protected from the wind. Thereâs a large tent, here.",
exits => [
{
id => $next++, # 5
name => "A tent flap leads inside.",
direction => "tent",
destination => 2, # The Tent
} ],
things => [],
words => [],
} ] };
$data->{next} = $next;
};
# Save the world every half hour.
Mojo::IOLoop->recurring(1800 => \&save_world);
# Streaming needs a special handler because the stream never closes.
unshift(@request_handlers, "^gemini://(?:$host)(?:\\d+)?/play/ijirait/stream" => \&add_streamer);
sub add_streamer {
my $stream = shift;
my $data = shift;
$log->debug("Handle streaming request");
$log->debug("Discarding " . length($data->{buffer}) . " bytes")
if $data->{buffer};
my $url = $data->{request};
my $port = App::Phoebe::port($stream);
if ($url =~ m!^(?:gemini:)?//($host)(?::$port)?/play/ijirait/stream$!) {
my $p = login($stream);
if ($p) {
# 1h timeout
$stream->timeout(3600);
# remove from channel members if an error happens
$stream->on(close => sub { my $stream = shift; logout($stream, $p, "Connection closed") });
$stream->on(error => sub { my ($stream, $err) = @_; logout($stream, $p, $err) });
push(@streamers, { stream => $stream, person => $p });
success($stream);
$stream->write(encode_utf8 "# Streaming $p->{name}\n");
$stream->write(encode_utf8 "Make sure you connect to game using a different client "
. "(with the same client certificate!) in order to play $p->{name}.\n");
$stream->write(encode_utf8 "=> /play/ijirait Play $p->{name}.");
# don't close the stream!
} else {
$stream->close_gracefully();
}
} else {
result($stream, "59", "Don't know how to handle $url");
$stream->close_gracefully();
}
}
sub logout {
my ($stream, $p, $msg) = @_;
$log->debug("Disconnected $p->{name}: $msg");
@streamers = grep { $_->{stream} ne $stream and $_->{person} ne $p } @streamers;
}
# run every minute and print a timestamp every 5 minutes
Mojo::IOLoop->recurring(60 => sub {
my $loop = shift;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time);
return unless $min % 5 == 0;
return unless @streamers > 0;
$log->debug("Ijirait streamer ping");
my $ts = sprintf("%02d:%02d UTC\n", $hour, $min);
for (@streamers) {
$_->{stream}->write($ts);
}});
# notify every streamer in the same room
sub notify {
my ($p, $msg) = @_;
eval {
for my $s (grep { $_->{person}->{location} == $p->{location} } @streamers) {
my $stream = $s->{stream};
next unless $stream;
$stream->write(encode_utf8 $msg);
$stream->write("\n");
}
};
$log->error("Error notifying people of '$msg': $@") if $@;
}
( run in 2.303 seconds using v1.01-cache-2.11-cpan-8f98c5d2c55 )