From 046203e5e7ac9d492c11c8292de1390ada00c48a Mon Sep 17 00:00:00 2001 From: JT Smith Date: Tue, 15 Mar 2011 18:07:04 -0500 Subject: [PATCH] space station lab now allows for building modules --- bin/lacuna.psgi | 8 +- docs/SpaceStationLab.pod | 82 ++++++++++++++- lib/Lacuna/DB/Result/Building/SSLa.pm | 137 ++++++++++++++++++++++++++ lib/Lacuna/RPC/Building/SSLa.pm | 48 ++++++++- t/SpaceStationLab.t | 76 ++++++++++++++ var/www/public/changes.txt | 1 + 6 files changed, 349 insertions(+), 3 deletions(-) create mode 100644 t/SpaceStationLab.t diff --git a/bin/lacuna.psgi b/bin/lacuna.psgi index b5b9e5a1..5ccb573f 100644 --- a/bin/lacuna.psgi +++ b/bin/lacuna.psgi @@ -1,5 +1,6 @@ use strict; use lib ('/data/Lacuna-Server/lib'); +use 5.010; use Config::JSON; use Plack::App::URLMap; use Log::Log4perl; @@ -40,7 +41,7 @@ my $gameover = [ 500, } ) ], ]; -builder { +my $app = builder { enable 'CrossOrigin', origins => '*', methods => ['GET', 'POST'], max_age => 60*60*24*30, headers => '*'; @@ -237,5 +238,10 @@ builder { }; Lacuna::Web::MissionCurator->new->to_app; }; + }; +say "Server Started"; + +$app; + diff --git a/docs/SpaceStationLab.pod b/docs/SpaceStationLab.pod index 32a7e472..445f4840 100644 --- a/docs/SpaceStationLab.pod +++ b/docs/SpaceStationLab.pod @@ -2,8 +2,88 @@ Space Station Lab is accessible via the URLs C, C, C, and C. The C URL controls all the actual functions of the lab, but you must build all four lab components to use the functions of SSL A. -The list of methods below represents changes and additions to the methods that all L share. +The list of methods below represents changes and additions to the methods that all L share. +B These methods and changes have only been made to C. + +=head2 view ( session_id, building_id ) + +This method is changed from the default because it adds a C element to the output. + + { + "building" : { ... }, + "status" : { ... }, + "make_plan" : { + "types" : { + "ibs" : "Interstellar Broadcast Station", + ... + }, + "level_costs" : [ + { + level => 1, + food => 10000, + ore => 10000, + water => 10000, + energy => 10000, + waste => 2500, + time => 1200 + }, + ... + ], + "subsidy_cost" : 2, + "making" : "Interstellar Broadcast Station (3+0)" + } + } + +If there is a plan being made then the C element will be present. + +=head3 session_id + +A session id. + +=head3 building_id + +The unique id of the space station lab. + + + +=head2 make_plan ( session_id, building_id, type, level ) + +Starts the plan creation process. + +Returns C. + +=head3 session_id + +A session id. + +=head3 building_id + +The unique id of the space station lab. + +=head3 type + +The key from the hash returned by the C method in make_plan > types. For example, C for "Interstellar Broadcast Station". + +=head3 level + +An integer between 1 and 30. The level from the array returned by the C method in make_plan > level_costs. + + + +=head2 subsidize_plan ( session_id, building_id ) + +Will spend essentia equal to the subsidy_cost returned by the C method to complete the current plan immediately. Returns C. + +Throws 1011. + +=head3 session_id + +A session id. + +=head3 building_id + +The unique id of the space station lab. diff --git a/lib/Lacuna/DB/Result/Building/SSLa.pm b/lib/Lacuna/DB/Result/Building/SSLa.pm index b0a4cef2..03884d5c 100644 --- a/lib/Lacuna/DB/Result/Building/SSLa.pm +++ b/lib/Lacuna/DB/Result/Building/SSLa.pm @@ -4,6 +4,7 @@ use Moose; use utf8; no warnings qw(uninitialized); extends 'Lacuna::DB::Result::Building'; +use Lacuna::Constants qw(ORE_TYPES INFLATION); around 'build_tags' => sub { my ($orig, $class) = @_; @@ -57,5 +58,141 @@ before can_build => sub { } }; +sub makeable_plans { + return { + command => 'Lacuna::DB::Result::Building::Module::StationCommand', + ibs => 'Lacuna::DB::Result::Building::Module::IBS', + parliament => 'Lacuna::DB::Result::Building::Module::Parliament', + warehouse => 'Lacuna::DB::Result::Building::Module::Warehouse', + }; +} + +sub makeable_plans_formatted { + my $self = shift; + my %out; + my $makeable_plans = $self->makeable_plans; + while (my ($type, $class) = each %{$makeable_plans}) { + $out{$type} = $class->name; + } + return \%out; +} + +sub level_costs_formatted { + my $self = shift; + my $max = $self->max_level; + return [] if $max == 0; + my @costs; + my $resource_cost = $self->plan_resource_cost; + my $time_cost = $self->plan_time_cost; + foreach my $level (1..$max) { + my $resource = $self->plan_cost_at_level($level, $resource_cost); + push @costs, { + level => $level, + ore => $resource, + water => $resource, + energy => $resource, + food => $resource, + waste => sprintf('%.0f', $resource/4), + time => $self->plan_cost_at_level($level, $time_cost), + }; + } + return \@costs; +} + +has plan_resource_cost => ( + is => 'rw', + lazy => 1, + default => sub { + my $self = shift; + return 40000 * ((100 - (5 * $self->body->empire->research_affinity)) / 100); + } +); + +has plan_time_cost => ( + is => 'rw', + lazy => 1, + default => sub { + my $self = shift; + return 1200 * ((100 - (5 * $self->body->empire->management_affinity)) / 100); + } +); + +sub plan_cost_at_level { + my ($self, $level, $base) = @_; + return sprintf('%.0f', $base * (INFLATION ** $level)); +} + +has max_level => ( + is => 'rw', + lazy => 1, + default => sub { + my $self = shift; + my $level = $self->level; + my $body = $self->body; + foreach my $part (qw(b c d)) { + my $building = $body->get_building_of_class('Lacuna::DB::Result::Building::SSL'.$part); + if (defined $building) { + $level = ($level > $building->level) ? $building->level : $level; + } + else { + $level = 0; + last; + } + } + return $level; + }, +); + +sub can_make_plan { + my ($self, $type, $level) = @_; + $level ||= 1; + if ($level > $self->max_level) { + confess [1013, 'This Space Station Lab is not a high enough level to make that plan.']; + } + my $makeable = $self->makeable_plans; + unless ($type ~~ [keys %{$makeable}]) { + confess [1009, 'Cannot make that type of plan.']; + } + my $resource_cost = $self->plan_cost_at_level($level, $self->plan_resource_cost); + my $fraction = sprintf('%.0f',$resource_cost * 0.01); + my $body = $self->body; + foreach my $ore (ORE_TYPES) { + if ($body->type_stored($ore) < $fraction) { + confess [1011, 'Not enough '.$ore.' in storage. You need at least '.$fraction.'.']; + } + } + foreach my $resource (qw(ore water food energy)) { + if ($body->type_stored($resource) < $resource_cost) { + confess [1011, 'Not enough '.$resource.' in storage. You need at least '.$resource_cost.'.']; + } + } + return 1; +} + +sub make_plan { + my ($self, $type, $level) = @_; + $level ||= 1; + my $makeable = $self->makeable_plans; + my $resource_cost = $self->plan_cost_at_level($level, $self->plan_resource_cost); + my $time_cost = $self->plan_cost_at_level($level, $self->plan_time_cost); + my $body = $self->body; + $body->spend_ore($resource_cost); + $body->spend_water($resource_cost); + $body->spend_food($resource_cost); + $body->spend_energy($resource_cost); + $body->add_waste($resource_cost/4); + $body->update; + $self->start_work({ + class => $makeable->{$type}, + level => $level, + }, $time_cost)->update; +} + +before finish_work => sub { + my $self = shift; + my $planet = $self->body; + $planet->add_plan($self->work->{class}, $self->work->{level}); +}; + no Moose; __PACKAGE__->meta->make_immutable(inline_constructor => 0); diff --git a/lib/Lacuna/RPC/Building/SSLa.pm b/lib/Lacuna/RPC/Building/SSLa.pm index 93b3f481..854f5732 100644 --- a/lib/Lacuna/RPC/Building/SSLa.pm +++ b/lib/Lacuna/RPC/Building/SSLa.pm @@ -13,8 +13,54 @@ sub model_class { return 'Lacuna::DB::Result::Building::SSLa'; } +around 'view' => sub { + my ($orig, $self, $session_id, $building_id) = @_; + my $empire = $self->get_empire_by_session($session_id); + my $building = $self->get_building($empire, $building_id, skip_offline => 1); + my $out = $orig->($self, $empire, $building); + $out->{make_plan} = { + types => $building->makeable_plans_formatted, + level_costs => $building->level_costs_formatted, + subsidy_cost => 2, + }; + if ($building->is_working) { + $out->{make_plan}{making} = $building->work->{class}->name . ' ('.$building->work->{level}.'+0)'; + } + return $out; +}; -__PACKAGE__->register_rpc_method_names(qw()); + +sub make_plan { + my ($self, $session_id, $building_id, $type, $level) = @_; + my $empire = $self->get_empire_by_session($session_id); + my $building = $self->get_building($empire, $building_id); + $building->can_make_plan($type, $level); + $building->make_plan($type, $level); + return $self->view($empire, $building); +} + +sub subsidize_plan { + my ($self, $session_id, $building_id) = @_; + my $empire = $self->get_empire_by_session($session_id); + my $building = $self->get_building($empire, $building_id); + + unless ($building->is_working) { + confess [1010, "There is no plan being built."]; + } + + unless ($empire->essentia >= 2) { + confess [1011, "Not enough essentia."]; + } + + $building->finish_work->update; + $empire->spend_essentia(2, 'ssl plan subsidy after the fact'); + $empire->update; + + return $self->view($empire, $building); +} + + +__PACKAGE__->register_rpc_method_names(qw(make_plan subsidize_plan)); no Moose; diff --git a/t/SpaceStationLab.t b/t/SpaceStationLab.t new file mode 100644 index 00000000..c1253f92 --- /dev/null +++ b/t/SpaceStationLab.t @@ -0,0 +1,76 @@ +use lib '../lib'; +use Test::More tests => 6; +use Test::Deep; +use Data::Dumper; +use 5.010; +use DateTime; +use Lacuna::Constants qw(ORE_TYPES); + +use TestHelper; +my $tester = TestHelper->new->generate_test_empire->build_infrastructure; +my $session_id = $tester->session->id; +my $empire = $tester->empire; +my $home = $empire->home_planet; + +my $ssla = Lacuna->db->resultset('Lacuna::DB::Result::Building')->new({ + x => 4, + y => 4, + class => 'Lacuna::DB::Result::Building::SSLa', + }); +$home->build_building($ssla); +$ssla->finish_upgrade; + +my $sslb = Lacuna->db->resultset('Lacuna::DB::Result::Building')->new({ + x => 5, + y => 4, + class => 'Lacuna::DB::Result::Building::SSLb', + }); +$home->build_building($sslb); +$sslb->finish_upgrade; + +my $sslc = Lacuna->db->resultset('Lacuna::DB::Result::Building')->new({ + x => 5, + y => 5, + class => 'Lacuna::DB::Result::Building::SSLc', + }); +$home->build_building($sslc); +$sslc->finish_upgrade; + +my $ssld = Lacuna->db->resultset('Lacuna::DB::Result::Building')->new({ + x => 4, + y => 5, + class => 'Lacuna::DB::Result::Building::SSLd', + }); +$home->build_building($ssld); +$ssld->finish_upgrade; + +my $result; + +$result = $tester->post('ssla', 'view', [$session_id, $ssla->id]); +is($result->{result}{make_plan}{subsidy_cost}, 2, 'got subsidy cost'); +is(scalar(@{$result->{result}{make_plan}{level_costs}}), 1, 'got level costs'); +ok($result->{result}{make_plan}{level_costs}[0]{food} > 1000, 'got good level costs'); +is($result->{result}{make_plan}{types}{ibs}, 'Interstellar Broadcast System', 'got types'); + +$home->ore_capacity(5_000_000); +$home->water_capacity(5_000_000); +$home->food_capacity(5_000_000); +$home->energy_capacity(5_000_000); +foreach my $ore (ORE_TYPES, qw(water algae energy)) { + $home->add_type($ore, 100_000); +} +$home->update; + +$result = $tester->post('ssla', 'make_plan', [$session_id, $ssla->id, 'ibs', 1]); +is($result->{result}{make_plan}{making}, 'Interstellar Broadcast System (1+0)', 'making plan'); + +$empire->add_essentia(10,'testing')->update; + +$result = $tester->post('ssla', 'subsidize_plan', [$session_id, $ssla->id]); +ok(!exists $result->{result}{make_plan}{making}, 'subsidize making plan'); + + + +END { + $tester->cleanup; +} diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index c10fd00d..d37bca4b 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -1,4 +1,5 @@ 3.0100 + - Add: The space station lab is now capable of producing some module plans. - Rule: Deployed bleeders now require a captcha to be demolished. - Fix: All body resource attributes have been upgraded to support 9223372036854775807 instead of 2147483647. - Fix: Space stations now count against your next colony cost while in transit. -- 2.51.2