From abe03c59c66b8aada57ea49926099a7f6ab66d35 Mon Sep 17 00:00:00 2001 From: Graham Knop Date: Wed, 4 Jul 2012 21:43:42 -0400 Subject: [PATCH 01/36] add config templates --- etc/lacuna.conf.template | 76 ++++++++++++++++++++++++++++++++++++++ etc/log4perl.conf.template | 6 +++ setup_a_server.txt | 5 ++- 3 files changed, 85 insertions(+), 2 deletions(-) create mode 100755 etc/lacuna.conf.template create mode 100755 etc/log4perl.conf.template diff --git a/etc/lacuna.conf.template b/etc/lacuna.conf.template new file mode 100755 index 00000000..81a36a1e --- /dev/null +++ b/etc/lacuna.conf.template @@ -0,0 +1,76 @@ +# config-file-type: JSON 1 +{ + "access_key" : "XXXX", + "db" : { + "dsn" : "DBI:mysql:XXXX", + "password" : "XXXX", + "username" : "XXXX" + }, + "envolve" : { + "Sn" : 0, + "api_key" : "XXXX" + }, + "essentia_code_server_url" : "", + "facebook" : { + "api_key" : "XXXX", + "app_id" : "XXXX", + "secret" : "XXXX" + }, + "feeds" : { + "bucket" : "XXXX", + "surl" : "https://xxxx/", + "url" : "http://xxxx/" + }, + "itransact" : { + "APIKey" : "XXXX", + "APIUsername" : "XXXX", + "Gateway" : "XXXX", + "OrderFormUID" : "XXXX", + "SendCustomerEmail" : "TRUE", + "SendMerchantEmail" : "TRUE", + "TestMode" : "FALSE" + }, + "jambool" : { + "api_url" : "XXXX", + "offer_id" : "XXXX", + "secret_key" : "XXXX" + }, + "map_size" : { + "x" : [ + -500, + 500 + ], + "y" : [ + -500, + 500 + ] + }, + "memcached" : [ + { + "host" : "127.0.0.1", + "port" : "11211" + } + ], + "offline" : 0, + "paypal" : { + "APIPassword" : "XXXX", + "APIUsername" : "XXXX", + "Sandbox" : "0", + "Signature" : "XXXX" + }, + "rpc_limit" : 2500, + "rpc_throttle" : 200, + "secret_key" : "XXXX", + "self_destruct_after_inactive_days" : 9999999, + "server_key" : "XXXX", + "server_keys" : [ + "XXXX" + ], + "server_url" : "http://localhost:5000/", + "voting_sites" : [ + { + "name" : "XXXX", + "url" : "http://xxxx/" + } + ] +} diff --git a/etc/log4perl.conf.template b/etc/log4perl.conf.template new file mode 100755 index 00000000..f9647a90 --- /dev/null +++ b/etc/log4perl.conf.template @@ -0,0 +1,6 @@ +log4perl.logger = TRACE, mainlog +log4perl.appender.mainlog = Log::Log4perl::Appender::File +log4perl.appender.mainlog.filename = /tmp/lacuna.log +log4perl.appender.mainlog.layout = PatternLayout +log4perl.appender.mainlog.layout.ConversionPattern = %d - %p - %M[%L] - %m%n + diff --git a/setup_a_server.txt b/setup_a_server.txt index e4215d55..46c1b709 100644 --- a/setup_a_server.txt +++ b/setup_a_server.txt @@ -24,8 +24,9 @@ MySQL will depend on the system and how you installed it. Step 3: Config Files -You'll need to create lacuna.conf, nginx.conf, and log.conf in your Lacuna-Server/etc folder. The best way to do this -is probably to just get them off one of the play testers server. +You'll need to create lacuna.conf, nginx.conf, and log4perl.conf +in your Lacuna-Server/etc folder. Templates exist in the etc +directory. -- 2.51.2 From 2e5164f7eb8f51102a0ca28e3ae32880248a95ed Mon Sep 17 00:00:00 2001 From: Graham Knop Date: Wed, 4 Jul 2012 21:43:51 -0400 Subject: [PATCH 02/36] add license file --- LICENSE | 339 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..d159169d --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. -- 2.51.2 From eae449ed9e3c2cbd7df2ab15a294472c9af86a1d Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Thu, 6 Sep 2012 11:42:07 -0400 Subject: [PATCH 03/36] Minor changes to help to understand resource bug --- lib/Lacuna/DB/Result/Map/Body/Planet.pm | 22 ++-- lib/Lacuna/DB/Result/Ships.pm | 28 ++--- lib/Lacuna/Role/Container.pm | 134 ++++++++++++------------ lib/Lacuna/Role/Ship/Arrive/Defend.pm | 8 +- lib/Lacuna/Role/TraderRpc.pm | 50 --------- 5 files changed, 97 insertions(+), 145 deletions(-) diff --git a/lib/Lacuna/DB/Result/Map/Body/Planet.pm b/lib/Lacuna/DB/Result/Map/Body/Planet.pm index 5041c32f..24735968 100644 --- a/lib/Lacuna/DB/Result/Map/Body/Planet.pm +++ b/lib/Lacuna/DB/Result/Map/Body/Planet.pm @@ -1656,7 +1656,7 @@ sub can_add_type { my $capacity = $type.'_capacity'; my $stored = $type.'_stored'; my $available_storage = $self->$capacity - $self->$stored; - unless ($available_storage >= $value) { + if ($available_storage < $value) { confess [1009, "You don't have enough available storage."]; } return 1; @@ -1665,17 +1665,21 @@ sub can_add_type { sub add_type { my ($self, $type, $value) = @_; my $method = 'add_'.$type; - unless (eval{$self->can_add_type($type, $value)}) { + eval { + $self->can_add_type($type, $value); + }; + if ($@) { my $empire = $self->empire; - if (defined $empire && !$empire->skip_resource_warnings && !$empire->check_for_repeat_message('complaint_overflow'.$self->id)) { + if (defined $empire + && !$empire->skip_resource_warnings + && !$empire->check_for_repeat_message('complaint_overflow'.$self->id)) { $empire->send_predefined_message( - filename => 'complaint_overflow.txt', - params => [$type, $self->id, $self->name], - repeat_check=> 'complaint_overflow'.$self->id, - tags => ['Complaint','Alert'], - ); + filename => 'complaint_overflow.txt', + params => [$type, $self->id, $self->name], + repeat_check => 'complaint_overflow'.$self->id, + tags => ['Complaint','Alert'], + ); } - } $self->$method($value); return $self; diff --git a/lib/Lacuna/DB/Result/Ships.pm b/lib/Lacuna/DB/Result/Ships.pm index 3ab43752..1c4653f8 100644 --- a/lib/Lacuna/DB/Result/Ships.pm +++ b/lib/Lacuna/DB/Result/Ships.pm @@ -123,7 +123,7 @@ sub max_occupants { sub arrive { my $self = shift; eval {$self->handle_arrival_procedures}; # throws exceptions to stop subsequent actions from happening - my $reason = $@; + my $reason = $@; if (ref $reason eq 'ARRAY' && $reason->[0] eq -1) { # this is an expected exception, it means one of the roles took over return; @@ -167,7 +167,7 @@ sub can_send_to_target { sub can_recall { my $self = shift; - unless ($self->task ~~ [qw(Defend Orbiting)]) { + unless ($self->task ~~ [qw(Defend Orbiting)]) { confess [1010, 'That ship is busy.']; } return 1; @@ -250,16 +250,16 @@ sub get_status { name => $body->name, type => 'body', }; - my $orbiting = { - id => $self->foreign_body_id, + my $orbiting = { + id => $self->foreign_body_id, name => $self->foreign_body->name, - type => 'body', - x => $self->foreign_body->x, - y => $self->foreign_body->y, + type => 'body', + x => $self->foreign_body->x, + y => $self->foreign_body->y, }; - $status{from} = $from; - $status{orbiting} = $orbiting; - } + $status{from} = $from; + $status{orbiting} = $orbiting; + } return \%status; } @@ -318,15 +318,15 @@ sub finish_construction { } sub orbit { - my ($self) = @_; - $self->task('Orbiting'); + my ($self) = @_; + $self->task('Orbiting'); $self->date_available(DateTime->now); return $self; } sub defend { - my ($self) = @_; - $self->task('Defend'); + my ($self) = @_; + $self->task('Defend'); $self->date_available(DateTime->now); return $self; } diff --git a/lib/Lacuna/Role/Container.pm b/lib/Lacuna/Role/Container.pm index 4ad9a32b..159350d9 100644 --- a/lib/Lacuna/Role/Container.pm +++ b/lib/Lacuna/Role/Container.pm @@ -67,9 +67,8 @@ sub unload { if (exists $payload->{resources}) { my %resources = %{$payload->{resources}}; foreach my $type (keys %resources) { - $body->add_type($type, $resources{$type}); + $body->add_type($type, $resources{$type})->update; } - $body->update; delete $payload->{resources}; } if (exists $payload->{plans}) { @@ -79,52 +78,52 @@ sub unload { delete $payload->{plans}; } if (exists $payload->{glyphs}) { - foreach my $glyph (@{$payload->{glyphs}}) { - $body->add_glyph($glyph->{name}, $glyph->{quantity}); - } - delete $payload->{glyphs}; + foreach my $glyph (@{$payload->{glyphs}}) { + $body->add_glyph($glyph->{name}, $glyph->{quantity}); + } + delete $payload->{glyphs}; } $self->payload($payload); return $self; } sub format_description_of_payload { - my ($self) = @_; - my $item_arr = []; - my $scratch; - my $payload = $self->payload; + my ($self) = @_; + my $item_arr = []; + my $scratch; + my $payload = $self->payload; - # essentia - push @{$item_arr}, sprintf('%s essentia.', commify($payload->{essentia})) if ($payload->{essentia}); + # essentia + push @{$item_arr}, sprintf('%s essentia.', commify($payload->{essentia})) if ($payload->{essentia}); - # resources - foreach my $resource (keys %{ $payload->{resources}}) { - push @{$item_arr}, sprintf('%s %s', commify($payload->{resources}{$resource}), $resource); - } + # resources + foreach my $resource (keys %{ $payload->{resources}}) { + push @{$item_arr}, sprintf('%s %s', commify($payload->{resources}{$resource}), $resource); + } - # glyphs - foreach my $glyph (@{$payload->{glyphs}}) { - push @{$item_arr}, sprintf('%s %s glyph', commify($glyph->{quantity}), $glyph->{name}); - } + # glyphs + foreach my $glyph (@{$payload->{glyphs}}) { + push @{$item_arr}, sprintf('%s %s glyph', commify($glyph->{quantity}), $glyph->{name}); + } - # ships - my $ships = Lacuna->db->resultset('Lacuna::DB::Result::Ships'); + # ships + my $ships = Lacuna->db->resultset('Lacuna::DB::Result::Ships'); - undef $scratch; - foreach my $id (@{ $payload->{ships}}) { - my $ship = $ships->find($id); - next unless defined $ship; - my $pattern = '%s (speed: %s, stealth: %s, hold size: %s, berth: %s, combat: %s)' ; - push @{$scratch}, - sprintf($pattern, - $ship->type_formatted, - commify($ship->speed), - commify($ship->stealth), - commify($ship->hold_size), - commify($ship->berth_level), - commify($ship->combat)); - } - push @{$item_arr}, @{consolidate_items($scratch)} if (defined($scratch)); + undef $scratch; + foreach my $id (@{ $payload->{ships}}) { + my $ship = $ships->find($id); + next unless defined $ship; + my $pattern = '%s (speed: %s, stealth: %s, hold size: %s, berth: %s, combat: %s)' ; + push @{$scratch}, + sprintf($pattern, + $ship->type_formatted, + commify($ship->speed), + commify($ship->stealth), + commify($ship->hold_size), + commify($ship->berth_level), + commify($ship->combat)); + } + push @{$item_arr}, @{consolidate_items($scratch)} if (defined($scratch)); # plans undef $scratch; @@ -137,43 +136,42 @@ sub format_description_of_payload { push @{$item_arr}, sprintf('%s %s (%s) plan', $stats->{quantity}, $stats->{class}->name, $level); } - # spies - undef $scratch; - my $spies = Lacuna->db->resultset('Lacuna::DB::Result::Spies'); - if (exists $payload->{spies}) { - foreach my $id (@{$payload->{spies}}) { - my $spy = $spies->find($id); - next unless defined $spy; - push @{$scratch}, 'Level '.$spy->level.' spy named '.$spy->name . ' (transport)'; + # spies + undef $scratch; + my $spies = Lacuna->db->resultset('Lacuna::DB::Result::Spies'); + if (exists $payload->{spies}) { + foreach my $id (@{$payload->{spies}}) { + my $spy = $spies->find($id); + next unless defined $spy; + push @{$scratch}, 'Level '.$spy->level.' spy named '.$spy->name . ' (transport)'; + } + push @{$item_arr}, @{consolidate_items($scratch)} if (defined($scratch)); } - push @{$item_arr}, @{consolidate_items($scratch)} if (defined($scratch)); - } - # prisoners - undef $scratch; - if (exists $payload->{prisoners}) { - foreach my $id (@{$payload->{prisoners}}) { - my $spy = $spies->find($id); - next unless defined $spy; - push @{$scratch}, - 'Level '.$spy->level.' spy named '.$spy->name . - ' (prisoner) sentence expires '.$spy->format_available_on; + # prisoners + undef $scratch; + if (exists $payload->{prisoners}) { + foreach my $id (@{$payload->{prisoners}}) { + my $spy = $spies->find($id); + next unless defined $spy; + push @{$scratch}, + 'Level '.$spy->level.' spy named '.$spy->name . + ' (prisoner) sentence expires '.$spy->format_available_on; + } + push @{$item_arr}, @{consolidate_items($scratch)} if (defined($scratch)); } - push @{$item_arr}, @{consolidate_items($scratch)} if (defined($scratch)); - } - # fetch spies - undef $scratch; - if (exists $payload->{fetch_spies}) { - foreach my $id (@{$payload->{fetch_spies}}) { - my $spy = $spies->find($id); - push @{$scratch}, 'Level '.$spy->level.' spy named '.$spy->name . ' (fetch upon arrival)'; + # fetch spies + undef $scratch; + if (exists $payload->{fetch_spies}) { + foreach my $id (@{$payload->{fetch_spies}}) { + my $spy = $spies->find($id); + push @{$scratch}, 'Level '.$spy->level.' spy named '.$spy->name . ' (fetch upon arrival)'; + } + push @{$item_arr}, @{consolidate_items($scratch)} if (defined($scratch)); } - push @{$item_arr}, @{consolidate_items($scratch)} if (defined($scratch)); - } - return $item_arr; + return $item_arr; } - 1; diff --git a/lib/Lacuna/Role/Ship/Arrive/Defend.pm b/lib/Lacuna/Role/Ship/Arrive/Defend.pm index c2bda8b5..95046186 100644 --- a/lib/Lacuna/Role/Ship/Arrive/Defend.pm +++ b/lib/Lacuna/Role/Ship/Arrive/Defend.pm @@ -9,12 +9,12 @@ after handle_arrival_procedures => sub { # no defense at stars return unless $self->foreign_body_id; - # only defend on arrival to the foreign body - return if $self->direction eq 'in'; + # only defend on arrival to the foreign body + return if $self->direction eq 'in'; - $self->defend->update; + $self->defend->update; - confess [-1]; + confess [-1]; }; 1; diff --git a/lib/Lacuna/Role/TraderRpc.pm b/lib/Lacuna/Role/TraderRpc.pm index c506b661..7d182fd2 100644 --- a/lib/Lacuna/Role/TraderRpc.pm +++ b/lib/Lacuna/Role/TraderRpc.pm @@ -199,56 +199,6 @@ sub get_plan_summary { }; } - -sub get_plans_delete_me_i_am_not_used { - my ($self, $session_id, $building_id) = @_; - my $empire = $self->get_empire_by_session($session_id); - my $building = $self->get_building($empire, $building_id); - my $plans = Lacuna->db->resultset('Lacuna::DB::Result::Plans')->search( - {body_id => $building->body_id}, - {order_by => [ 'class', 'level']} - ); - my @out; - while (my $plan = $plans->next) { - push @out, { - id => $plan->id, - name => $plan->class->name, - level => $plan->level, - extra_build_level => $plan->extra_build_level, - }; - } - # Put plans in a sensible order - @out = sort {$a->{name} cmp $b->{name} || $a->{level} <=> $b->{level} || $b->{extra_build_level} <=> $a->{extra_build_level} } @out; - return { - plans => \@out, - cargo_space_used_each => 10_000, - status => $self->format_status($empire, $building->body), - }; -} - -sub get_glyphs_delete_me_i_am_not_used { - my ($self, $session_id, $building_id) = @_; - - my $empire = $self->get_empire_by_session($session_id); - my $building = $self->get_building($empire, $building_id); - my $glyphs = $building->body->glyph; - - my @out; - while (my $glyph = $glyphs->next) { - push @out, { - id => $glyph->id, - name => $glyph->type, - type => $glyph->type, - quantity => $glyph->quantity, - }; - } - return { - glyphs => \@out, - cargo_space_used_each => 100, - status => $self->format_status($empire, $building->body), - }; -} - sub get_glyph_summary { my ($self, $session_id, $building_id) = @_; -- 2.51.2 From 635c06041821c2c833e19c8b65ba98285177efb3 Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Thu, 6 Sep 2012 12:55:25 -0400 Subject: [PATCH 04/36] Black Hole Generator now creates new planet types --- lib/Lacuna/DB/Result/Map/Body.pm | 3 +++ lib/Lacuna/RPC/Building/BlackHoleGenerator.pm | 14 +++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/Lacuna/DB/Result/Map/Body.pm b/lib/Lacuna/DB/Result/Map/Body.pm index bc9b70a0..f82344e1 100644 --- a/lib/Lacuna/DB/Result/Map/Body.pm +++ b/lib/Lacuna/DB/Result/Map/Body.pm @@ -213,6 +213,9 @@ after 'sqlt_deploy_hook' => sub { 'Lacuna::DB::Result::Map::Body::Planet::Station' => 'Lacuna::DB::Result::Map::Body::Planet::Station', }); } +sub asteroid_types {return 26;} +sub planet_types {return 40;} +sub gas_giant_types {return 5;}; # RELATIONSHIPS diff --git a/lib/Lacuna/RPC/Building/BlackHoleGenerator.pm b/lib/Lacuna/RPC/Building/BlackHoleGenerator.pm index 8816e3ef..38ec3fb6 100644 --- a/lib/Lacuna/RPC/Building/BlackHoleGenerator.pm +++ b/lib/Lacuna/RPC/Building/BlackHoleGenerator.pm @@ -536,11 +536,11 @@ sub bhg_make_planet { my $old_size = $body->size; my $random = randint(0,99); if ($random < 5) { - $class = 'Lacuna::DB::Result::Map::Body::Planet::GasGiant::G'.randint(1,5); + $class = 'Lacuna::DB::Result::Map::Body::Planet::GasGiant::G'.randint(1,Lacuna::DB::Result::Map::Body->gas_giant_types); $size = randint(90, 121); } else { - $class = 'Lacuna::DB::Result::Map::Body::Planet::P'.randint(1,20); + $class = 'Lacuna::DB::Result::Map::Body::Planet::P'.randint(1,Lacuna::DB::Result::Map::Body->planet_types); $size = 30; } @@ -571,7 +571,7 @@ sub bhg_make_asteroid { my $new_size = int($building->level/5); $new_size = 10 if $new_size > 10; $body->update({ - class => 'Lacuna::DB::Result::Map::Body::Asteroid::A'.randint(1,21), + class => 'Lacuna::DB::Result::Map::Body::Asteroid::A'.randint(1,Lacuna::DB::Result::Map::Body->asteroid_types), size => $new_size, needs_recalc => 1, usable_as_starter_enabled => 0, @@ -629,12 +629,12 @@ sub bhg_random_type { my $btype = $target->get_type; my $return; if ($btype eq 'habitable planet') { - my $params = { newtype => randint(1,20) }; + my $params = { newtype => randint(1,Lacuna::DB::Result::Map::Body->planet_types) }; $body->add_news(50, sprintf('%s has gone thru extensive changes.', $target->name)); $return = bhg_change_type($target, $params); } elsif ($btype eq 'asteroid') { - my $params = { newtype => randint(1,21) }; + my $params = { newtype => randint(1,Lacuna::DB::Result::Map::Body->asteroid_types) }; $body->add_news(50, sprintf('%s has gone thru extensive changes.', $target->name)); $return = bhg_change_type($target, $params); } @@ -939,7 +939,7 @@ sub bhg_change_type { my $old_class = $class; my $btype = $body->get_type; if ($btype eq 'asteroid') { - if ($params->{newtype} >= 1 and $params->{newtype} <= 21) { + if ($params->{newtype} >= 1 and $params->{newtype} <= Lacuna::DB::Result::Map::Body->asteroid_types) { $class = 'Lacuna::DB::Result::Map::Body::Asteroid::A'.$params->{newtype}; } else { @@ -950,7 +950,7 @@ sub bhg_change_type { confess [1013, "We can't change the type of that body"]; } elsif ($btype eq 'habitable planet') { - if ($params->{newtype} >= 1 and $params->{newtype} <= 20) { + if ($params->{newtype} >= 1 and $params->{newtype} <= Lacuna::DB::Result::Map::Body->planet_types) { $class = 'Lacuna::DB::Result::Map::Body::Planet::P'.$params->{newtype}; $old_class =~ /::(P\d+)/; my $old_type = $1; -- 2.51.2 From 9a95bb3606d67bd134ccda28a5a36213e5150a0c Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Thu, 6 Sep 2012 12:56:52 -0400 Subject: [PATCH 05/36] Updated version and comments --- lib/Lacuna.pm | 2 +- var/www/public/changes.txt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Lacuna.pm b/lib/Lacuna.pm index bcae5928..8fcf8c7b 100644 --- a/lib/Lacuna.pm +++ b/lib/Lacuna.pm @@ -7,7 +7,7 @@ use Config::JSON; useall __PACKAGE__; -our $VERSION = 3.0868; +our $VERSION = 3.0869; my $config = Config::JSON->new('/data/Lacuna-Server/etc/lacuna.conf'); my $db = Lacuna::DB->connect($config->get('db/dsn'),$config->get('db/username'),$config->get('db/password'), { mysql_enable_utf8 => 1}); diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index ec9159d8..891c7073 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -1,3 +1,6 @@ +3.0869: + - Fix: Black Hole Generator now creates all new planet/asteroid types + 3.0868: - Fix: No longer try to send N19 news from an asteroid -- 2.51.2 From 3590e8e6062802b2ac8157168f79082b231017e5 Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Thu, 6 Sep 2012 13:29:18 -0400 Subject: [PATCH 06/36] BHG POD update for new planet types --- docs/BlackHoleGenerator.pod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/BlackHoleGenerator.pod b/docs/BlackHoleGenerator.pod index 7dc478ca..dfcb7eb9 100644 --- a/docs/BlackHoleGenerator.pod +++ b/docs/BlackHoleGenerator.pod @@ -108,7 +108,7 @@ Can increase the size of a habitable planet up to size 65 or an asteroid up to s =item Change Type -Can change the type of a habitable planet to any of the basic 20 types. Usable at Black Hole Generator level 25. +Can change the type of a habitable planet to any of the basic 40 types. Usable at Black Hole Generator level 25. Only allowed to change occupied planets that share your alliance. -- 2.51.2 From 0a2a5d0a0d4c49cced4c35f045db03e28ec7b4cd Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Fri, 7 Sep 2012 15:52:22 -0400 Subject: [PATCH 07/36] Attempt to ameleorate the missing resources issues --- lib/Lacuna/DB/Result/Map/Body/Planet.pm | 9 +++++++-- lib/Lacuna/Role/Container.pm | 5 ++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/Lacuna/DB/Result/Map/Body/Planet.pm b/lib/Lacuna/DB/Result/Map/Body/Planet.pm index 24735968..1185c1a1 100644 --- a/lib/Lacuna/DB/Result/Map/Body/Planet.pm +++ b/lib/Lacuna/DB/Result/Map/Body/Planet.pm @@ -1192,7 +1192,9 @@ sub recalc_stats { my $domestic_ore_hour = sprintf('%.0f',$self->$type * $ore_production_hour / $self->total_ore_concentration); $stats{$method} += $domestic_ore_hour; } - + $self->update; + $self->discard_changes; + # deal with negative amounts stored $self->water_stored(0) if $self->water_stored < 0; $self->energy_stored(0) if $self->energy_stored < 0; @@ -1200,6 +1202,8 @@ sub recalc_stats { my $stype = $type.'_stored'; $self->$stype(0) if ($self->$stype < 0); } + $self->update; + $self->discard_changes; # deal with storage overages if ($self->ore_stored > $stats{ore_capacity}) { @@ -1246,7 +1250,8 @@ sub recalc_stats { } $stats{happiness_hour} = -100_000_000_000 if ($stats{happiness_hour} < -100_000_000_000); } - + $self->update; + $self->discard_changes; $self->update(\%stats); return $self; } diff --git a/lib/Lacuna/Role/Container.pm b/lib/Lacuna/Role/Container.pm index 159350d9..27231ec1 100644 --- a/lib/Lacuna/Role/Container.pm +++ b/lib/Lacuna/Role/Container.pm @@ -66,9 +66,12 @@ sub unload { } if (exists $payload->{resources}) { my %resources = %{$payload->{resources}}; + $body->update; + $body->discard_changes; foreach my $type (keys %resources) { - $body->add_type($type, $resources{$type})->update; + $body->add_type($type, $resources{$type}); } + $body->update; delete $payload->{resources}; } if (exists $payload->{plans}) { -- 2.51.2 From 8beb7dec1bfa43145d48773e060622ff77fd03e4 Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Sun, 9 Sep 2012 02:18:15 -0400 Subject: [PATCH 08/36] Added hourly cron job to tick fissures --- bin/tick_fissures.pl | 174 ++++++++++++++++++ .../DB/Result/Building/Permanent/Fissure.pm | 30 ++- lib/Lacuna/DB/Result/Map/Body/Planet.pm | 59 +++--- lib/Lacuna/Util.pm | 38 ++-- var/www/public/changes.txt | 3 + 5 files changed, 251 insertions(+), 53 deletions(-) create mode 100644 bin/tick_fissures.pl diff --git a/bin/tick_fissures.pl b/bin/tick_fissures.pl new file mode 100644 index 00000000..bb9dde1c --- /dev/null +++ b/bin/tick_fissures.pl @@ -0,0 +1,174 @@ +use 5.010; +use strict; +use lib '/data/Lacuna-Server/lib'; +use Data::Dumper; +use Lacuna::DB; +use Lacuna; +use Lacuna::Util qw(randint format_date); +use Getopt::Long; +$|=1; +our $quiet; +GetOptions( + 'quiet' => \$quiet, +); + + +out('Started'); +my $start = time; + +out('Loading DB'); +our $db = Lacuna->db; + +out('Ticking fissures'); +my %has_fissures = map { $_->body_id => 1 } $db->resultset('Building')->search({ + class => 'Lacuna::DB::Result::Building::Permanent::Fissure', + })->all; + +for my $body_id (sort keys %has_fissures) { + my $body = $db->resultset('Map::Body')->find($body_id); + out('Ticking Fissures on '.$body->name); + my @fissures = $body->get_buildings_of_class('Lacuna::DB::Result::Building::Permanent::Fissure'); + + # Decrease the % efficiency of all Fissure containment systems. + # If a Fissure reaches 0% then it becomes unstable and upgrades a level and resets to 100% efficiency + # When upgrading, it causes up to 10% damage to all energy producing buildings + # When there is one Fissure at level 30 and 0% containment efficiency then another is spawned + # When there are two Fissures at level 30 and 0% containment efficiency then the planet implodes. + # When a new fissure is spawned, it first targets a BHG, then energy singularity, then any energy building + # and finally a spare space or a building at random (excluding the PCC). + # The level of the second Fissure is the same level as the BHG (if there is one) otherwise it is level 1 + # + for my $fissure (@fissures) { + out("Fissure at ".$fissure->x.",".$fissure->y." co-ordinates"); + if ($fissure->efficiency > 0) { + $fissure->efficiency($fissure->efficiency - 4); + } + if ($fissure->efficiency <= 0) { + $fissure->efficiency(0); + if ($fissure->level < 30) { + $fissure->level($fissure->level + 1); + $fissure->efficiency(100); + # damage energy buildings. + + } + } + out(" set to ".$fissure->efficiency."% containment efficiency"); + $fissure->is_working(0); + $fissure->update; + } + + # get number of Fissures at 0% efficiency and maximum level + my $max_fissures = grep { $_->efficiency == 0 and $_->level == 30 } @fissures; + if ($max_fissures == @fissures) { + if ($max_fissures == 1) { + out(" adding a second fissure!!!"); + # Then add a second fissure + # If there is a BHG then convert that! + my $building = $body->get_building_of_class("Lacuna::DB::Result::Building::Permanent::BlackHoleGenerator"); + my $fissure_level = 1; + if ($building) { + out(" using the existing BHG"); + my $now = DateTime->now; + $building->class('Lacuna::DB::Result::Building::Permanent::Fissure'); + if ($building->is_working) { + $building->is_working(0); + $building->work_ends($now); + } + $building->is_upgrading(0); + $building->efficiency(100); + $building->update; + $fissure_level = $building->level; + } + else { + # First locate all energy buildings. + my @energy_buildings = qw(Singularity Fusion Fission Hydrocarbon Geo Reserve); + BUILDING: + for my $energy_bld (@energy_buildings) { + if ($building = $body->get_building_of_class("Lacuna::DB::Result::Building::Energy::$energy_bld")) { + out(" Using the existing $energy_bld building!"); + last BUILDING; + } + } + if (not $building) { + # then any random building (except the PCC) + my @buildings = grep { + ($_->x != 0 or $_->y != 0) # anything except the PCC + and ($_->class != 'Lacuna::DB::Result::Building::Permanent::Fissure') # Not a Fissure! + and ($_->class != 'Lacuna::DB::Result::Building::Permanent::BlackHoleGenerator"') + } @{$body->building_cache}; + $building = random_element(@buildings); + out(" Using the existing ".$building->class." building!"); + } + if (not $building) { + # then any free space + my $x = randint(-5,5); + my $y = randint(-5,5); + if ($x == 0 and $y == 0) { + $x = 1; + } + out(" Output on free plot $x,$y"); + $building = Lacuna->db->resultset('Lacuna::DB::Result::Building')->new({ + x => $x, + y => $y, + class => 'Lacuna::DB::Result::Building::Permanent::Fissure', + level => $fissure_level - 1, + }); + $body->build_building($building); + $building->finish_upgrade; + } + $building->update({ + level => $fissure_level, + class => 'Lacuna::DB::Result::Building::Permanent::Fissure', + efficiency => 100, + available => DateTime->now, + is_working => 0, + }); + out(" Created a level ".$building->level." Fissure"); + } + } + else { + # If it is an empire. + if ($body->empire_id) { + my $empire = $body->empire; + + # Send the empire an email + + # If it is the empires home world + if ($body->id == $empire->home_planet_id) { + # check if there are other colonies we can move the capitol to + + # if so, then move the capitol + + # else find a new, remote colony and found it + + # Send an email with the new co-ordinates + + # Put something on N19 + } + else { + # else it is 'just' a colony + + # Send an email about the destruction + + # Put something on N19 + } + } + # demolish the planet + + + } + } +} + +############### +## SUBROUTINES +############### + +sub out { + my $message = shift; + unless ($quiet) { + say format_date(DateTime->now), " ", $message; + } +} + + diff --git a/lib/Lacuna/DB/Result/Building/Permanent/Fissure.pm b/lib/Lacuna/DB/Result/Building/Permanent/Fissure.pm index 9b1add81..d7c029d3 100644 --- a/lib/Lacuna/DB/Result/Building/Permanent/Fissure.pm +++ b/lib/Lacuna/DB/Result/Building/Permanent/Fissure.pm @@ -36,17 +36,24 @@ after finish_upgrade => sub { }; before 'can_demolish' => sub { - my $self = shift; - unless ($self->level == 1) { - confess [1013, 'You must fill in the fissure by spending resources to downgrade it before you can demolish it.']; - } + my $self = shift; + unless ($self->efficiency >= 100) { + confess [1013, 'Unless your Fissure maintenance equipment is 100% operational, it is just too dangerous to attempt']; + } + unless ($self->level == 1) { + confess [1013, 'You must fill in the fissure by spending resources to downgrade it before you can demolish it.']; + } }; before 'can_downgrade' => sub { - my $self = shift; - unless ($self->has_resources_to_fill_in_fissure) { - confess [1013, 'You need '.int($self->cost_to_fill_in_fissure).' in ore to fill in the fissure.']; - } + my $self = shift; + + unless ($self->efficiency >= 100) { + confess [1013, 'Unless your Fissure maintenance equipment is 100% operational, it is just too dangerous to attempt.']; + } + unless ($self->has_resources_to_fill_in_fissure) { + confess [1013, 'You need '.int($self->cost_to_fill_in_fissure).' in ore to fill in the fissure.']; + } }; before downgrade => sub { @@ -58,9 +65,9 @@ before downgrade => sub { $body->spend_ore($cost); } else { - $cost -= $stored; $body->spend_ore($stored); } + $self->body->add_news(30, sprintf('Scientists on %s successfully downgraded a Fissure today.', $self->body->name)); }; sub cost_to_fill_in_fissure { @@ -77,6 +84,11 @@ sub has_resources_to_fill_in_fissure { use constant name => 'Fissure'; use constant time_to_build => 0; +use constant food_to_build => 18; +use constant energy_to_build => 20; +use constant ore_to_build => 21; +use constant water_to_build => 20; +use constant waste_to_build => 10; no Moose; diff --git a/lib/Lacuna/DB/Result/Map/Body/Planet.pm b/lib/Lacuna/DB/Result/Map/Body/Planet.pm index 1185c1a1..9781f94f 100644 --- a/lib/Lacuna/DB/Result/Map/Body/Planet.pm +++ b/lib/Lacuna/DB/Result/Map/Body/Planet.pm @@ -582,7 +582,7 @@ has building_count => ( sub _build_building_count { my ($self) = @_; - # Bleeders count toward building count, but supply pods don't since they can't be shot down. +# Bleeders count toward building count, but supply pods don't since they can't be shot down. my $count = grep {$_->class !~ /Permanent/ and $_->class !~ /SupplyPod/} @{$self->building_cache}; return $count; } @@ -632,9 +632,9 @@ has archaeology => ( is => 'rw', lazy => 1, default => sub { - my $self = shift; - my $building = $self->get_building_of_class('Lacuna::DB::Result::Building::Archaeology'); - return $building; + my $self = shift; + my $building = $self->get_building_of_class('Lacuna::DB::Result::Building::Archaeology'); + return $building; }, ); @@ -784,43 +784,43 @@ sub has_room_in_build_queue { use constant operating_resource_names => qw(food_hour energy_hour ore_hour water_hour); has future_operating_resources => ( - is => 'rw', - clearer => 'clear_future_operating_resources', - lazy => 1, - default => sub { + is => 'rw', + clearer => 'clear_future_operating_resources', + lazy => 1, + default => sub { my $self = shift; - # get current +# get current my %future; foreach my $method ($self->operating_resource_names) { - $future{$method} = $self->$method; + $future{$method} = $self->$method; } - # adjust for what's already in build queue +# adjust for what's already in build queue my @queued_builds = @{$self->builds}; foreach my $build (@queued_builds) { - my $other = $build->stats_after_upgrade; - foreach my $method ($self->operating_resource_names) { - $future{$method} += $other->{$method} - $build->$method; - } + my $other = $build->stats_after_upgrade; + foreach my $method ($self->operating_resource_names) { + $future{$method} += $other->{$method} - $build->$method; + } } return \%future; - }, -); + }, + ); sub has_resources_to_operate { my ($self, $building) = @_; - # get future +# get future my $future = $self->future_operating_resources; - # get change for this building +# get change for this building my $after = $building->stats_after_upgrade; - # check our ability to sustain ourselves +# check our ability to sustain ourselves foreach my $method ($self->operating_resource_names) { my $delta = $after->{$method} - $building->$method; - # don't allow it if it sucks resources && its sucking more than we're producing +# don't allow it if it sucks resources && its sucking more than we're producing if ($delta < 0 && $future->{$method} + $delta < 0) { my $resource = $method; $resource =~ s/(\w+)_hour/$1/; @@ -833,12 +833,12 @@ sub has_resources_to_operate { sub has_resources_to_operate_after_building_demolished { my ($self, $building) = @_; - # get future +# get future my $planet = $self->future_operating_resources; - # check our ability to sustain ourselves +# check our ability to sustain ourselves foreach my $method ($self->operating_resource_names) { - # don't allow it if it sucks resources && its sucking more than we're producing +# don't allow it if it sucks resources && its sucking more than we're producing if ($planet->{$method} - $building->$method < 0) { my $resource = $method; $resource =~ s/(\w+)_hour/$1/; @@ -1098,7 +1098,7 @@ sub recalc_stats { } $stats{max_berth} = 1; #calculate building production - my ($gas_giant_platforms, $terraforming_platforms, $station_command, $pantheon_of_hagness, $ore_production_hour, $ore_consumption_hour, $food_production_hour, $food_consumption_hour) = 0; + my ($gas_giant_platforms, $terraforming_platforms, $station_command, $pantheon_of_hagness, $ore_production_hour, $ore_consumption_hour, $food_production_hour, $food_consumption_hour, $fissure_percent) = 0; foreach my $building (@{$self->building_cache}) { $stats{waste_capacity} += $building->waste_capacity; $stats{water_capacity} += $building->water_capacity; @@ -1166,7 +1166,16 @@ sub recalc_stats { if ($building->isa('Lacuna::DB::Result::Building::Module::StationCommand')) { $station_command += $building->level; } + if ($building->isa('Lacuna::DB::Result::Building::Permanent::Fissure')) { + # A fissure is controlled by maintenance equipment. The less efficient + # the equipment, the more energy the Fissure will suck in. + # Fissure affect on energy_hour is 1% per level subject to efficiency + $fissure_percent += $building->level * ($building->efficiency - 100) / 100; + } } + # Energy reduced by Fissure action + $stats{energy_hour} -= $stats{energy_hour} * $fissure_percent / 100; + $stats{food_consumption_hour} = $food_consumption_hour; $stats{ore_consumption_hour} = $ore_consumption_hour; diff --git a/lib/Lacuna/Util.pm b/lib/Lacuna/Util.pm index 30fc1976..6aae3b5b 100644 --- a/lib/Lacuna/Util.pm +++ b/lib/Lacuna/Util.pm @@ -18,11 +18,11 @@ sub format_date { # Return a random integer between $low and $high inclusive sub randint { - my ($low, $high) = @_; - $low = 0 unless defined $low; - $high = 1 unless defined $high; - ($low, $high) = ($high,$low) if $low > $high; - return $low + int( rand( $high - $low + 1 ) ); + my ($low, $high) = @_; + $low = 0 unless defined $low; + $high = 1 unless defined $high; + ($low, $high) = ($high,$low) if $low > $high; + return $low + int( rand( $high - $low + 1 ) ); } sub random_element { @@ -31,23 +31,23 @@ sub random_element { } sub commify { - my $text = reverse $_[0]; - $text =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g; - return scalar reverse $text; + my $text = reverse $_[0]; + $text =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g; + return scalar reverse $text; } sub consolidate_items { - my ($item_arr) = @_; - - my $item_hash = {}; - for my $item (@{$item_arr}) { - $item_hash->{$item}++; - } - undef $item_arr; - for my $item (sort keys %{$item_hash}) { - push @{$item_arr}, sprintf("%5s %s", commify($item_hash->{$item}), $item); - } - return $item_arr; + my ($item_arr) = @_; + + my $item_hash = {}; + for my $item (@{$item_arr}) { + $item_hash->{$item}++; + } + undef $item_arr; + for my $item (sort keys %{$item_hash}) { + push @{$item_arr}, sprintf("%5s %s", commify($item_hash->{$item}), $item); + } + return $item_arr; } 1; diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index 891c7073..a9c4fd4c 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -1,5 +1,8 @@ 3.0869: - Fix: Black Hole Generator now creates all new planet/asteroid types + - Add: Fissure now sucks in energy from your planet based on it's level and efficiency + - Add: You can now repair the fissure stabilization equipment at a Fissure. + - Add: You can only downgrade or demolish a Fissure which is 100% maintained. 3.0868: - Fix: No longer try to send N19 news from an asteroid -- 2.51.2 From 86bb503b7b23f2fb0022ff0cb5b67bd0aa49c59b Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Sun, 9 Sep 2012 14:44:07 -0400 Subject: [PATCH 09/36] More changes for Fissure --- bin/tick_fissures.pl | 12 +++++++----- lib/Lacuna/DB/Result/Map/Body/Planet.pm | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/bin/tick_fissures.pl b/bin/tick_fissures.pl index bb9dde1c..8f24e674 100644 --- a/bin/tick_fissures.pl +++ b/bin/tick_fissures.pl @@ -4,7 +4,7 @@ use lib '/data/Lacuna-Server/lib'; use Data::Dumper; use Lacuna::DB; use Lacuna; -use Lacuna::Util qw(randint format_date); +use Lacuna::Util qw(randint format_date random_element); use Getopt::Long; $|=1; our $quiet; @@ -93,10 +93,9 @@ for my $body_id (sort keys %has_fissures) { # then any random building (except the PCC) my @buildings = grep { ($_->x != 0 or $_->y != 0) # anything except the PCC - and ($_->class != 'Lacuna::DB::Result::Building::Permanent::Fissure') # Not a Fissure! - and ($_->class != 'Lacuna::DB::Result::Building::Permanent::BlackHoleGenerator"') + and ($_->class ne 'Lacuna::DB::Result::Building::Permanent::Fissure') # Not a Fissure! } @{$body->building_cache}; - $building = random_element(@buildings); + $building = random_element(\@buildings); out(" Using the existing ".$building->class." building!"); } if (not $building) { @@ -120,11 +119,14 @@ for my $body_id (sort keys %has_fissures) { level => $fissure_level, class => 'Lacuna::DB::Result::Building::Permanent::Fissure', efficiency => 100, - available => DateTime->now, is_working => 0, }); out(" Created a level ".$building->level." Fissure"); } + if ($body->empire_id) { + $body->needs_recalc(1); + $body->tick; + } } else { # If it is an empire. diff --git a/lib/Lacuna/DB/Result/Map/Body/Planet.pm b/lib/Lacuna/DB/Result/Map/Body/Planet.pm index 9781f94f..89f85e4e 100644 --- a/lib/Lacuna/DB/Result/Map/Body/Planet.pm +++ b/lib/Lacuna/DB/Result/Map/Body/Planet.pm @@ -1170,7 +1170,7 @@ sub recalc_stats { # A fissure is controlled by maintenance equipment. The less efficient # the equipment, the more energy the Fissure will suck in. # Fissure affect on energy_hour is 1% per level subject to efficiency - $fissure_percent += $building->level * ($building->efficiency - 100) / 100; + $fissure_percent += $building->level * (100 - $building->efficiency) / 100; } } # Energy reduced by Fissure action -- 2.51.2 From c2b3ea3766e98d41a2a2cd60fbf85bd2bdfad194 Mon Sep 17 00:00:00 2001 From: lemming552 Date: Sun, 9 Sep 2012 16:59:57 -0600 Subject: [PATCH 10/36] Fissures can't be reduced via spies and excavs. --- lib/Lacuna/DB/Result/Building/Archaeology.pm | 1 + lib/Lacuna/DB/Result/Spies.pm | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/Lacuna/DB/Result/Building/Archaeology.pm b/lib/Lacuna/DB/Result/Building/Archaeology.pm index 55ac77ed..5d7780f8 100644 --- a/lib/Lacuna/DB/Result/Building/Archaeology.pm +++ b/lib/Lacuna/DB/Result/Building/Archaeology.pm @@ -517,6 +517,7 @@ sub plans_of_type { )]; my $disallow = [qw( Lacuna::DB::Result::Building::Permanent::EssentiaVein + Lacuna::DB::Result::Building::Permanent::Fissure Lacuna::DB::Result::Building::Permanent::KasternsKeep Lacuna::DB::Result::Building::Permanent::MassadsHenge Lacuna::DB::Result::Building::Permanent::TheDillonForge diff --git a/lib/Lacuna/DB/Result/Spies.pm b/lib/Lacuna/DB/Result/Spies.pm index eb3e1453..522f3267 100644 --- a/lib/Lacuna/DB/Result/Spies.pm +++ b/lib/Lacuna/DB/Result/Spies.pm @@ -2216,6 +2216,7 @@ sub steal_building { ($_->level > 1) and ($_->class ne 'Lacuna::DB::Result::Building::Permanent::EssentiaVein') and ($_->class ne 'Lacuna::DB::Result::Building::Permanent::TheDillonForge') and + ($_->class ne 'Lacuna::DB::Result::Building::Permanent::Fissure') and !($_->class =~ /^Lacuna::DB::Result::Building::LCOT/) and ($_->class ne 'Lacuna::DB::Result::Building::DeployedBleeder') } -- 2.51.2 From 78975332f99e17b7c792b39e172446a6b4f1e9a1 Mon Sep 17 00:00:00 2001 From: lemming552 Date: Tue, 11 Sep 2012 09:26:30 -0600 Subject: [PATCH 11/36] New sizes. --- lib/Lacuna/RPC/Building/BlackHoleGenerator.pm | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/Lacuna/RPC/Building/BlackHoleGenerator.pm b/lib/Lacuna/RPC/Building/BlackHoleGenerator.pm index 38ec3fb6..79ee22bb 100644 --- a/lib/Lacuna/RPC/Building/BlackHoleGenerator.pm +++ b/lib/Lacuna/RPC/Building/BlackHoleGenerator.pm @@ -1006,7 +1006,7 @@ sub bhg_size { } elsif ($variance == 1) { if ($current_size >= 10) { - $current_size++ if (randint(0,99) < 10); + $current_size++ if (randint(0,99) < 25); $current_size = 20 if ($current_size > 20); } else { @@ -1017,6 +1017,7 @@ sub bhg_size { else { $current_size += randint(1,5) - 3; $current_size = 1 if ($current_size < 1); + $current_size = 20 if ($current_size > 20); } } elsif ($btype eq 'gas giant') { @@ -1028,19 +1029,19 @@ sub bhg_size { $current_size = 30 if ($current_size < 30); } elsif ($variance == 1) { - if ($current_size >= 65) { - $current_size++ if (randint(0,99) < 10); - $current_size = 70 if ($current_size > 70); + if ($current_size >= 70) { + $current_size++ if (randint(0,99) < 25); + $current_size = 75 if ($current_size > 75); } else { $current_size += $building->level; - $current_size = 65 if ($current_size > 65); + $current_size = 70 if ($current_size > 70); } } else { $current_size += randint(1,5) - 3; $current_size = 30 if ($current_size < 30); - $current_size = 70 if ($current_size > 70); + $current_size = 75 if ($current_size > 75); } if ($old_size != $current_size && $body->empire) { $body->empire->send_predefined_message( -- 2.51.2 From 7d694bb43871352b735d189a118fbdd84296faf2 Mon Sep 17 00:00:00 2001 From: lemming552 Date: Tue, 11 Sep 2012 12:27:36 -0600 Subject: [PATCH 12/36] Update changes.txt --- var/www/public/changes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index a9c4fd4c..3807fd60 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -3,6 +3,7 @@ - Add: Fissure now sucks in energy from your planet based on it's level and efficiency - Add: You can now repair the fissure stabilization equipment at a Fissure. - Add: You can only downgrade or demolish a Fissure which is 100% maintained. + - Mod: Increase size on habitables can now get to new max. Soft Cap 70, Hard Cap 75. 3.0868: - Fix: No longer try to send N19 news from an asteroid -- 2.51.2 From 48d53676a68bb425a075c1ecd3e1032c6234d6f0 Mon Sep 17 00:00:00 2001 From: lemming552 Date: Tue, 11 Sep 2012 15:51:49 -0600 Subject: [PATCH 13/36] Bad Boolean logic fix. --- .../DB/Result/Building/Permanent/BlackHoleGenerator.pm | 5 ++--- var/www/public/changes.txt | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Lacuna/DB/Result/Building/Permanent/BlackHoleGenerator.pm b/lib/Lacuna/DB/Result/Building/Permanent/BlackHoleGenerator.pm index 3a13a2ca..622a23e9 100644 --- a/lib/Lacuna/DB/Result/Building/Permanent/BlackHoleGenerator.pm +++ b/lib/Lacuna/DB/Result/Building/Permanent/BlackHoleGenerator.pm @@ -38,9 +38,8 @@ after finish_upgrade => sub { sub can_build_on { my $self = shift; - if ( !$self->body->isa('Lacuna::DB::Result::Map::Body::Planet') || - $self->body->isa('Lacuna::DB::Result::Map::Body::Planet::Station') || - $self->body->isa('Lacuna::DB::Result::Map::Body::Planet::Gas Giant')) { + my $btype = $self->body->type; + unless ($btype eq 'habitable planet') { confess [1009, 'Can only be built on habitable planets.']; } return 1; diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index 3807fd60..1a2ee9ec 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -4,6 +4,7 @@ - Add: You can now repair the fissure stabilization equipment at a Fissure. - Add: You can only downgrade or demolish a Fissure which is 100% maintained. - Mod: Increase size on habitables can now get to new max. Soft Cap 70, Hard Cap 75. + - Fix: Check body type closely for building BHG. 3.0868: - Fix: No longer try to send N19 news from an asteroid -- 2.51.2 From 706405fd2d2755230256bf3a0ef65607b60ec129 Mon Sep 17 00:00:00 2001 From: lemming552 Date: Tue, 11 Sep 2012 16:01:10 -0600 Subject: [PATCH 14/36] get_type, not type... --- lib/Lacuna/DB/Result/Building/Permanent/BlackHoleGenerator.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Lacuna/DB/Result/Building/Permanent/BlackHoleGenerator.pm b/lib/Lacuna/DB/Result/Building/Permanent/BlackHoleGenerator.pm index 622a23e9..f214fa94 100644 --- a/lib/Lacuna/DB/Result/Building/Permanent/BlackHoleGenerator.pm +++ b/lib/Lacuna/DB/Result/Building/Permanent/BlackHoleGenerator.pm @@ -38,7 +38,7 @@ after finish_upgrade => sub { sub can_build_on { my $self = shift; - my $btype = $self->body->type; + my $btype = $self->body->get_type; unless ($btype eq 'habitable planet') { confess [1009, 'Can only be built on habitable planets.']; } -- 2.51.2 From 45ee74148b0a7db194feecfc0fb4abdc1d4897ae Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Thu, 13 Sep 2012 07:14:01 -0400 Subject: [PATCH 15/36] Added more code to the Fissure --- bin/tick_fissures.pl | 174 +++++++++++++++++++++++-------------- lib/Lacuna.pm | 2 +- var/www/public/changes.txt | 6 +- 3 files changed, 113 insertions(+), 69 deletions(-) diff --git a/bin/tick_fissures.pl b/bin/tick_fissures.pl index 8f24e674..cfb196c6 100644 --- a/bin/tick_fissures.pl +++ b/bin/tick_fissures.pl @@ -29,9 +29,9 @@ for my $body_id (sort keys %has_fissures) { out('Ticking Fissures on '.$body->name); my @fissures = $body->get_buildings_of_class('Lacuna::DB::Result::Building::Permanent::Fissure'); - # Decrease the % efficiency of all Fissure containment systems. + # Decrease the efficiency of all Fissure containment systems by an average of 4% # If a Fissure reaches 0% then it becomes unstable and upgrades a level and resets to 100% efficiency - # When upgrading, it causes up to 10% damage to all energy producing buildings + # When upgrading, it causes up to 15% damage to all energy producing buildings # When there is one Fissure at level 30 and 0% containment efficiency then another is spawned # When there are two Fissures at level 30 and 0% containment efficiency then the planet implodes. # When a new fissure is spawned, it first targets a BHG, then energy singularity, then any energy building @@ -40,15 +40,29 @@ for my $body_id (sort keys %has_fissures) { # for my $fissure (@fissures) { out("Fissure at ".$fissure->x.",".$fissure->y." co-ordinates"); + my $damage = randint(2,6); if ($fissure->efficiency > 0) { - $fissure->efficiency($fissure->efficiency - 4); + $fissure->efficiency($fissure->efficiency - $damage); } if ($fissure->efficiency <= 0) { $fissure->efficiency(0); if ($fissure->level < 30) { $fissure->level($fissure->level + 1); $fissure->efficiency(100); - # damage energy buildings. + + # damage energy and BHG buildings. + my @energy_buildings = grep {$_->class =~ /::Energy::/ || $_->class =~ /::Black/} @{$body->building_cache}; + foreach $bld (@energy_buildings) { + my $rnd = randint(5,15); + $bld->efficiency($bld->efficiency - $rnd); + $bld->efficiency(0) if $bld->efficiency < 0; + $bld->update; + } + # Send email to empire and N19 news + # + # + # + # } } @@ -56,96 +70,121 @@ for my $body_id (sort keys %has_fissures) { $fissure->is_working(0); $fissure->update; } + if ($body->empire_id) { + $body->needs_recalc(1); + $body->tick; + } # get number of Fissures at 0% efficiency and maximum level my $max_fissures = grep { $_->efficiency == 0 and $_->level == 30 } @fissures; - if ($max_fissures == @fissures) { - if ($max_fissures == 1) { + if (($max_fissures == @fissures) or (scalar @fissures == 3)) { + if (scalar @fissures == 1) { out(" adding a second fissure!!!"); # Then add a second fissure # If there is a BHG then convert that! my $building = $body->get_building_of_class("Lacuna::DB::Result::Building::Permanent::BlackHoleGenerator"); my $fissure_level = 1; if ($building) { - out(" using the existing BHG"); + $fissure_level = $building->level > 0 ? $building->level : 1; + } + else { + # otherwise convert an energy building. + my @buildings = grep { + $_->class =~ /::Energy::/ + } @{$body->building_cache}; + + $building = random_element(\@buildings); + } + + if (not $building) { + # otherwise any random building (except the PCC or the Fissure) + my @buildings = grep { + ($_->x != 0 or $_->y != 0) # anything except the PCC + and ($_->class ne 'Lacuna::DB::Result::Building::Permanent::Fissure') # Not a Fissure! + } @{$body->building_cache}; + + $building = random_element(\@buildings); + } + + if ($building) { my $now = DateTime->now; - $building->class('Lacuna::DB::Result::Building::Permanent::Fissure'); - if ($building->is_working) { - $building->is_working(0); - $building->work_ends($now); - } - $building->is_upgrading(0); - $building->efficiency(100); - $building->update; - $fissure_level = $building->level; + + $building->update({ + level => $fissure_level, + class => 'Lacuna::DB::Result::Building::Permanent::Fissure', + efficiency => 100, + is_working => 0, + work_ends => $now, + is_upgrading => 0, + + }); + out(" Converted building ".$building->class." into a level $fissure_level Fissure!"); + # send email to empire and N19 news + # + # + # + # } else { - # First locate all energy buildings. - my @energy_buildings = qw(Singularity Fusion Fission Hydrocarbon Geo Reserve); - BUILDING: - for my $energy_bld (@energy_buildings) { - if ($building = $body->get_building_of_class("Lacuna::DB::Result::Building::Energy::$energy_bld")) { - out(" Using the existing $energy_bld building!"); - last BUILDING; - } - } - if (not $building) { - # then any random building (except the PCC) - my @buildings = grep { - ($_->x != 0 or $_->y != 0) # anything except the PCC - and ($_->class ne 'Lacuna::DB::Result::Building::Permanent::Fissure') # Not a Fissure! - } @{$body->building_cache}; - $building = random_element(\@buildings); - out(" Using the existing ".$building->class." building!"); - } - if (not $building) { - # then any free space - my $x = randint(-5,5); - my $y = randint(-5,5); - if ($x == 0 and $y == 0) { - $x = 1; - } - out(" Output on free plot $x,$y"); - $building = Lacuna->db->resultset('Lacuna::DB::Result::Building')->new({ - x => $x, - y => $y, - class => 'Lacuna::DB::Result::Building::Permanent::Fissure', - level => $fissure_level - 1, - }); - $body->build_building($building); - $building->finish_upgrade; + # otherwise any free space + my $x = randint(-5,5); + my $y = randint(-5,5); + if ($x == 0 and $y == 0) { + $x = 1; } - $building->update({ - level => $fissure_level, - class => 'Lacuna::DB::Result::Building::Permanent::Fissure', - efficiency => 100, - is_working => 0, + out(" using free plot $x,$y"); + $building = Lacuna->db->resultset('Lacuna::DB::Result::Building')->new({ + x => $x, + y => $y, + class => 'Lacuna::DB::Result::Building::Permanent::Fissure', + level => $fissure_level - 1, }); - out(" Created a level ".$building->level." Fissure"); + $body->build_building($building); + $building->finish_upgrade; + # send email to empire and N19 news + # + # + # + # + # } + + if ($body->empire_id) { $body->needs_recalc(1); $body->tick; } } else { + # If we get here. We have no option but to implode the planet!! + # If it is an empire. if ($body->empire_id) { my $empire = $body->empire; - # Send the empire an email - # If it is the empires home world if ($body->id == $empire->home_planet_id) { # check if there are other colonies we can move the capitol to - - # if so, then move the capitol - - # else find a new, remote colony and found it - - # Send an email with the new co-ordinates - - # Put something on N19 + my @colonies = $empire->planets; + @colonies = grep {$_->id != $empire->home_planet_id} @colonies; + if (@colonies) { + # Then move the capitol to a random colony + + my $new_capitol = random_element(\@colonies); + $empire->home_planet_id($new_capitol->id); + $empire->update; + $body->sanitize; + + # + # Send the empire an email + # Put out news on N19 + } + else { + # No more colonies, found a new empire on a remote planet + # + # Send an email with the new planet + # Send out N19 news about the survivors. + } } else { # else it is 'just' a colony @@ -157,7 +196,8 @@ for my $body_id (sort keys %has_fissures) { } # demolish the planet - + # Damage planets in range (damage depends upon distance from the event) + } } } diff --git a/lib/Lacuna.pm b/lib/Lacuna.pm index 8fcf8c7b..f1a72de1 100644 --- a/lib/Lacuna.pm +++ b/lib/Lacuna.pm @@ -7,7 +7,7 @@ use Config::JSON; useall __PACKAGE__; -our $VERSION = 3.0869; +our $VERSION = 3.0870; my $config = Config::JSON->new('/data/Lacuna-Server/etc/lacuna.conf'); my $db = Lacuna::DB->connect($config->get('db/dsn'),$config->get('db/username'),$config->get('db/password'), { mysql_enable_utf8 => 1}); diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index a9c4fd4c..9f50e3d7 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -1,9 +1,13 @@ -3.0869: + +3.0870: - Fix: Black Hole Generator now creates all new planet/asteroid types - Add: Fissure now sucks in energy from your planet based on it's level and efficiency - Add: You can now repair the fissure stabilization equipment at a Fissure. - Add: You can only downgrade or demolish a Fissure which is 100% maintained. +3.0869: + - Add: Fissure now has repair cost + 3.0868: - Fix: No longer try to send N19 news from an asteroid -- 2.51.2 From c66dd1ad7c96205e78b281203f37b58dbf4bd52a Mon Sep 17 00:00:00 2001 From: lemming552 Date: Sat, 15 Sep 2012 09:44:53 -0600 Subject: [PATCH 16/36] List prisoners that are being sold/transported as captured. --- lib/Lacuna/DB/Result/Building/Module/PoliceStation.pm | 6 ++++-- lib/Lacuna/DB/Result/Building/Security.pm | 6 ++++-- lib/Lacuna/DB/Result/Spies.pm | 2 +- lib/Lacuna/RPC/Building/PoliceStation.pm | 2 ++ lib/Lacuna/RPC/Building/Security.pm | 2 ++ var/www/public/changes.txt | 1 + 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/Lacuna/DB/Result/Building/Module/PoliceStation.pm b/lib/Lacuna/DB/Result/Building/Module/PoliceStation.pm index 64c1c108..df92c6cf 100644 --- a/lib/Lacuna/DB/Result/Building/Module/PoliceStation.pm +++ b/lib/Lacuna/DB/Result/Building/Module/PoliceStation.pm @@ -19,7 +19,9 @@ sub foreign_spies { return Lacuna ->db ->resultset('Lacuna::DB::Result::Spies') - ->search({ level => { '<=' => int($self->level * 1.25)}, task => { '!=' => 'Captured'}, on_body_id => $self->body_id, empire_id => { '!=' => $self->body->empire_id } }); + ->search({ level => { '<=' => int($self->level * 1.25)}, + task => { 'not in' => [ 'Captured', 'Prisoner Transport' }, + on_body_id => $self->body_id, empire_id => { '!=' => $self->body->empire_id } }); } sub prisoners { @@ -30,7 +32,7 @@ sub prisoners { ->search( { on_body_id => $self->body_id, - task => 'Captured', + task => { 'in' => [ 'Captured', 'Prisoner Transport' ] }, available_on=> { '>' => DateTime->now }, } ); diff --git a/lib/Lacuna/DB/Result/Building/Security.pm b/lib/Lacuna/DB/Result/Building/Security.pm index 33fbacbd..561a0298 100644 --- a/lib/Lacuna/DB/Result/Building/Security.pm +++ b/lib/Lacuna/DB/Result/Building/Security.pm @@ -50,7 +50,9 @@ sub foreign_spies { return Lacuna ->db ->resultset('Lacuna::DB::Result::Spies') - ->search({ level => { '<=' => $self->level}, task => { '!=' => 'Captured'}, on_body_id => $self->body_id, empire_id => { '!=' => $self->body->empire_id } }); + ->search({ level => { '<=' => $self->level }, + task => { 'not in' => [ 'Captured', 'Prisoner Transport' }, + on_body_id => $self->body_id, empire_id => { '!=' => $self->body->empire_id } }); } sub prisoners { @@ -61,7 +63,7 @@ sub prisoners { ->search( { on_body_id => $self->body_id, - task => 'Captured', + task => { 'in' => [ 'Captured', 'Prisoner Transport' ] }, available_on=> { '>' => DateTime->now }, } ); diff --git a/lib/Lacuna/DB/Result/Spies.pm b/lib/Lacuna/DB/Result/Spies.pm index 522f3267..19bc228e 100644 --- a/lib/Lacuna/DB/Result/Spies.pm +++ b/lib/Lacuna/DB/Result/Spies.pm @@ -1713,7 +1713,7 @@ sub prevent_insurrection { my $conspirators = Lacuna->db ->resultset('Lacuna::DB::Result::Spies') ->search( { on_body_id => $self->on_body_id, - task => { 'not in' => ['Killed in Action', 'Travelling','Captured'] }, + task => { 'not in' => ['Killed in Action', 'Travelling','Captured', 'Prisoner Transport'] }, empire_id => { 'in' => \@member_ids } }); my $max_cnt = $defender->level; $max_cnt = ($max_cnt < 3) ? 6 : $max_cnt * 2; diff --git a/lib/Lacuna/RPC/Building/PoliceStation.pm b/lib/Lacuna/RPC/Building/PoliceStation.pm index 51c10d08..d9f12c9b 100644 --- a/lib/Lacuna/RPC/Building/PoliceStation.pm +++ b/lib/Lacuna/RPC/Building/PoliceStation.pm @@ -31,6 +31,7 @@ sub view_foreign_spies { push @out, { name => $spy->name, level => $spy->level, + task => $spy->task, next_mission => $available_on, }; } @@ -110,6 +111,7 @@ sub view_prisoners { id => $spy->id, name => $spy->name, level => $spy->level, + task => $spy->task, sentence_expires => $available_on, }; } diff --git a/lib/Lacuna/RPC/Building/Security.pm b/lib/Lacuna/RPC/Building/Security.pm index 96d0869e..575d4b85 100644 --- a/lib/Lacuna/RPC/Building/Security.pm +++ b/lib/Lacuna/RPC/Building/Security.pm @@ -32,6 +32,7 @@ sub view_foreign_spies { name => $spy->name, level => $spy->level, next_mission => $available_on, + task => $spy->task, }; } return { @@ -111,6 +112,7 @@ sub view_prisoners { id => $spy->id, name => $spy->name, level => $spy->level, + task => $spy->task, sentence_expires => $available_on, }; } diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index 1a2ee9ec..ef03b1b3 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -5,6 +5,7 @@ - Add: You can only downgrade or demolish a Fissure which is 100% maintained. - Mod: Increase size on habitables can now get to new max. Soft Cap 70, Hard Cap 75. - Fix: Check body type closely for building BHG. + - Fix: Spies that are being transported or sold are listed as prisoners in Security and Police Station. 3.0868: - Fix: No longer try to send N19 news from an asteroid -- 2.51.2 From ce09a5a292a189628b2dd5d4c3c8b49e5eef2679 Mon Sep 17 00:00:00 2001 From: lemming552 Date: Sat, 15 Sep 2012 13:17:03 -0600 Subject: [PATCH 17/36] Updated pod. --- docs/PoliceStation.pod | 2 ++ docs/Security.pod | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/PoliceStation.pod b/docs/PoliceStation.pod index 9d1e6e17..1bf88f9b 100644 --- a/docs/PoliceStation.pod +++ b/docs/PoliceStation.pod @@ -18,6 +18,7 @@ Displays a list of the spies that have been captured. "id" : "id-goes-here", "name" : "James Bond", "level" : "20", + "task" : "Captured" or "Prisoner Transport", "sentence_expires" : "01 31 2010 13:09:05 +0600" }, ... @@ -93,6 +94,7 @@ Displays a list of the spies that are on your planet, and have a level lower tha { "name" : "James Bond", "level" : 11, + "task" : "Appropriate Technology", "next_mission" : "01 31 2010 13:09:05 +0600" }, ... diff --git a/docs/Security.pod b/docs/Security.pod index 3576f643..4290b231 100644 --- a/docs/Security.pod +++ b/docs/Security.pod @@ -15,9 +15,10 @@ Displays a list of the spies that have been captured. "status" : { ... }, "prisoners" : [ { - "id" : "id-goes-here", - "name" : "James Bond", + "id" : "id-goes-here", + "name" : "James Bond", "level" : "20", + "task" : "Captured" or "Prisoner Transport", "sentence_expires" : "01 31 2010 13:09:05 +0600" }, ... @@ -93,6 +94,7 @@ Displays a list of the spies that are on your planet, and have a level lower tha { "name" : "James Bond", "level" : 11, + "task" : "Appropriate Technology", "next_mission" : "01 31 2010 13:09:05 +0600" }, ... @@ -117,4 +119,4 @@ Defaults to 1. Each page contains 25 spies. -=cut \ No newline at end of file +=cut -- 2.51.2 From 45f05998212e6a5c959cb6c59b66a94044692b95 Mon Sep 17 00:00:00 2001 From: lemming552 Date: Sat, 15 Sep 2012 13:42:50 -0600 Subject: [PATCH 18/36] Forgot closing bracket --- lib/Lacuna/DB/Result/Building/Module/PoliceStation.pm | 2 +- lib/Lacuna/DB/Result/Building/Security.pm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Lacuna/DB/Result/Building/Module/PoliceStation.pm b/lib/Lacuna/DB/Result/Building/Module/PoliceStation.pm index df92c6cf..efb65bfa 100644 --- a/lib/Lacuna/DB/Result/Building/Module/PoliceStation.pm +++ b/lib/Lacuna/DB/Result/Building/Module/PoliceStation.pm @@ -20,7 +20,7 @@ sub foreign_spies { ->db ->resultset('Lacuna::DB::Result::Spies') ->search({ level => { '<=' => int($self->level * 1.25)}, - task => { 'not in' => [ 'Captured', 'Prisoner Transport' }, + task => { 'not in' => [ 'Captured', 'Prisoner Transport' ] }, on_body_id => $self->body_id, empire_id => { '!=' => $self->body->empire_id } }); } diff --git a/lib/Lacuna/DB/Result/Building/Security.pm b/lib/Lacuna/DB/Result/Building/Security.pm index 561a0298..34c7d34f 100644 --- a/lib/Lacuna/DB/Result/Building/Security.pm +++ b/lib/Lacuna/DB/Result/Building/Security.pm @@ -51,7 +51,7 @@ sub foreign_spies { ->db ->resultset('Lacuna::DB::Result::Spies') ->search({ level => { '<=' => $self->level }, - task => { 'not in' => [ 'Captured', 'Prisoner Transport' }, + task => { 'not in' => [ 'Captured', 'Prisoner Transport'] }, on_body_id => $self->body_id, empire_id => { '!=' => $self->body->empire_id } }); } -- 2.51.2 From 15d0510606e1e85d05d9dd480752b4d870874c0d Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Sat, 15 Sep 2012 16:37:08 -0400 Subject: [PATCH 19/36] Added weather to some planets --- lib/Lacuna/Constants.pm | 3 ++ lib/Lacuna/DB/Result/Map/Body/Planet/P30.pm | 1 + lib/Lacuna/DB/Result/Map/Body/Planet/P33.pm | 45 +++++++++++---------- lib/Lacuna/DB/Result/Map/Body/Planet/P35.pm | 4 +- lib/Lacuna/DB/Result/Map/Body/Planet/P36.pm | 2 +- var/www/public/changes.txt | 2 +- 6 files changed, 33 insertions(+), 24 deletions(-) diff --git a/lib/Lacuna/Constants.pm b/lib/Lacuna/Constants.pm index 3a4d7453..669fca12 100644 --- a/lib/Lacuna/Constants.pm +++ b/lib/Lacuna/Constants.pm @@ -4,6 +4,7 @@ use strict; use base 'Exporter'; use constant INFLATION => 1.75; +use constant SECONDS_IN_A_DAY => 60 * 60 * 24; use constant GROWTH => 1.55; use constant FOOD_TYPES => (qw(cheese bean lapis potato apple root corn cider wheat bread soup chip pie pancake milk meal algae syrup fungus burger shake beetle)); use constant ORE_TYPES => (qw(rutile chromite chalcopyrite galena gold uraninite bauxite goethite halite gypsum trona kerogen methane anthracite sulfur zircon monazite fluorite beryl magnetite)); @@ -124,6 +125,7 @@ use constant SHIP_WASTE_TYPES => (qw( our @EXPORT_OK = qw( INFLATION + SECONDS_IN_A_DAY GROWTH FOOD_TYPES ORE_TYPES @@ -137,6 +139,7 @@ our @EXPORT_OK = qw( our %EXPORT_TAGS = ( all => [qw( INFLATION + SECONDS_IN_A_DAY GROWTH FOOD_TYPES ORE_TYPES diff --git a/lib/Lacuna/DB/Result/Map/Body/Planet/P30.pm b/lib/Lacuna/DB/Result/Map/Body/Planet/P30.pm index 7b61b6f7..3e42503e 100644 --- a/lib/Lacuna/DB/Result/Map/Body/Planet/P30.pm +++ b/lib/Lacuna/DB/Result/Map/Body/Planet/P30.pm @@ -7,6 +7,7 @@ extends 'Lacuna::DB::Result::Map::Body::Planet'; use constant image => 'p30'; + use constant water => 6450; use constant rutile => 1; use constant chromite => 1; diff --git a/lib/Lacuna/DB/Result/Map/Body/Planet/P33.pm b/lib/Lacuna/DB/Result/Map/Body/Planet/P33.pm index fe3c90b8..83e8b83b 100644 --- a/lib/Lacuna/DB/Result/Map/Body/Planet/P33.pm +++ b/lib/Lacuna/DB/Result/Map/Body/Planet/P33.pm @@ -6,29 +6,32 @@ no warnings qw(uninitialized); extends 'Lacuna::DB::Result::Map::Body::Planet'; use Lacuna::Util qw(randint); +with "Lacuna::Role::Planet::Weather"; +with "Lacuna::Role::Planet::GeoChaos"; + use constant image => 'p33'; -sub water { randint(1000,10000) } -sub rutile { randint(1,1000) } -sub chromite { randint(1,1000) } -sub chalcopyrite { randint(1,1000) } -sub galena { randint(1,1000) } -sub gold { randint(1,1000) } -sub uraninite { randint(1,1000) } -sub bauxite { randint(1,1000) } -sub goethite { randint(1,1000) } -sub halite { randint(1,1000) } -sub gypsum { randint(1,1000) } -sub trona { randint(1,1000) } -sub sulfur { randint(1,1000) } -sub methane { randint(1,1000) } -sub kerogen { randint(1,1000) } -sub anthracite { randint(1,1000) } -sub magnetite { randint(1,1000) } -sub fluorite { randint(1,1000) } -sub beryl { randint(1,1000) } -sub zircon { randint(1,1000) } -sub monazite { randint(1,1000) } +sub water { return 6000; }; +sub anthracite { return 1000; }; +sub bauxite { return 1000; }; +sub beryl { return 1000; }; +sub chalcopyrite { return 1000; }; +sub chromite { return 1000; }; +sub fluorite { return 1000; }; +sub galena { return 1000; }; +sub goethite { return 1000; }; +sub gold { return 1000; }; +sub gypsum { return 1000; }; +sub halite { return 1000; }; +sub kerogen { return 1000; }; +sub magnetite { return 1000; }; +sub methane { return 1000; }; +sub monazite { return 1000; }; +sub rutile { return 1000; }; +sub sulfur { return 1000; }; +sub trona { return 1000; }; +sub uraninite { return 1000; }; +sub zircon { return 1000; }; no Moose; diff --git a/lib/Lacuna/DB/Result/Map/Body/Planet/P35.pm b/lib/Lacuna/DB/Result/Map/Body/Planet/P35.pm index 265b6baf..ea318c66 100644 --- a/lib/Lacuna/DB/Result/Map/Body/Planet/P35.pm +++ b/lib/Lacuna/DB/Result/Map/Body/Planet/P35.pm @@ -5,9 +5,11 @@ use utf8; no warnings qw(uninitialized); extends 'Lacuna::DB::Result::Map::Body::Planet'; +with "Lacuna::Role::Planet::Weather"; + use constant image => 'p35'; -use constant water => 5885; +sub water { return 11500; }; use constant rutile => 500; use constant chromite => 500; use constant chalcopyrite => 500; diff --git a/lib/Lacuna/DB/Result/Map/Body/Planet/P36.pm b/lib/Lacuna/DB/Result/Map/Body/Planet/P36.pm index 133c3605..da97f7f4 100644 --- a/lib/Lacuna/DB/Result/Map/Body/Planet/P36.pm +++ b/lib/Lacuna/DB/Result/Map/Body/Planet/P36.pm @@ -7,7 +7,7 @@ extends 'Lacuna::DB::Result::Map::Body::Planet'; use constant image => 'p36'; -use constant water => 15000; +use constant water => 30000; use constant rutile => 100; use constant chromite => 100; use constant chalcopyrite => 100; diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index 9f50e3d7..0cef430a 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -1,9 +1,9 @@ - 3.0870: - Fix: Black Hole Generator now creates all new planet/asteroid types - Add: Fissure now sucks in energy from your planet based on it's level and efficiency - Add: You can now repair the fissure stabilization equipment at a Fissure. - Add: You can only downgrade or demolish a Fissure which is 100% maintained. + - Add: Some planets now have seasons. 3.0869: - Add: Fissure now has repair cost -- 2.51.2 From 15065034f47dd5d66e93656380b50eddecedb0c9 Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Sun, 16 Sep 2012 15:21:07 -0400 Subject: [PATCH 20/36] Completed Fissure Explosion code --- bin/tick_fissures.pl | 135 +++++++++++++++++---- lib/Lacuna/Role/Planet/GeoChaos.pm | 29 +++++ lib/Lacuna/Role/Planet/Weather.pm | 25 ++++ t/470_fissure.t | 42 +++++++ var/messages/fissure_capitol_moved.txt | 9 ++ var/messages/fissure_collateral_damage.txt | 10 ++ var/messages/fissure_colony_destroyed.txt | 7 ++ var/messages/fissure_replaced_energy.txt | 8 ++ var/messages/fissure_spawned.txt | 8 ++ 9 files changed, 249 insertions(+), 24 deletions(-) create mode 100644 lib/Lacuna/Role/Planet/GeoChaos.pm create mode 100644 lib/Lacuna/Role/Planet/Weather.pm create mode 100644 t/470_fissure.t create mode 100644 var/messages/fissure_capitol_moved.txt create mode 100644 var/messages/fissure_collateral_damage.txt create mode 100644 var/messages/fissure_colony_destroyed.txt create mode 100644 var/messages/fissure_replaced_energy.txt create mode 100644 var/messages/fissure_spawned.txt diff --git a/bin/tick_fissures.pl b/bin/tick_fissures.pl index cfb196c6..45ea3cad 100644 --- a/bin/tick_fissures.pl +++ b/bin/tick_fissures.pl @@ -52,7 +52,7 @@ for my $body_id (sort keys %has_fissures) { # damage energy and BHG buildings. my @energy_buildings = grep {$_->class =~ /::Energy::/ || $_->class =~ /::Black/} @{$body->building_cache}; - foreach $bld (@energy_buildings) { + foreach my $bld (@energy_buildings) { my $rnd = randint(5,15); $bld->efficiency($bld->efficiency - $rnd); $bld->efficiency(0) if $bld->efficiency < 0; @@ -109,6 +109,12 @@ for my $body_id (sort keys %has_fissures) { if ($building) { my $now = DateTime->now; + out(" Converted building ".$building->class." into a level $fissure_level Fissure!"); + $body->empire->send_predefined_message( + tags => ['Alert'], + filename => 'fissure_replaced_energy.txt', + params => [$body->name, $building->x,$building->y, $fissure_level], + ); $building->update({ level => $fissure_level, class => 'Lacuna::DB::Result::Building::Permanent::Fissure', @@ -118,12 +124,6 @@ for my $body_id (sort keys %has_fissures) { is_upgrading => 0, }); - out(" Converted building ".$building->class." into a level $fissure_level Fissure!"); - # send email to empire and N19 news - # - # - # - # } else { # otherwise any free space @@ -133,20 +133,24 @@ for my $body_id (sort keys %has_fissures) { $x = 1; } out(" using free plot $x,$y"); + $building = Lacuna->db->resultset('Lacuna::DB::Result::Building')->new({ - x => $x, - y => $y, - class => 'Lacuna::DB::Result::Building::Permanent::Fissure', - level => $fissure_level - 1, + x => $x, + y => $y, + class => 'Lacuna::DB::Result::Building::Permanent::Fissure', + level => $fissure_level - 1, + is_upgrading => 0, }); - $body->build_building($building); - $building->finish_upgrade; + $body->build_building($building,0,1); # send email to empire and N19 news # - # - # - # - # + if ($body->empire_id) { + $body->empire->send_predefined_message( + tags => ['Alert'], + filename => 'fissure_spawned.txt', + params => [$body->name], + ); + } } @@ -173,31 +177,114 @@ for my $body_id (sort keys %has_fissures) { my $new_capitol = random_element(\@colonies); $empire->home_planet_id($new_capitol->id); $empire->update; - $body->sanitize; - # # Send the empire an email - # Put out news on N19 + $empire->send_predefined_message( + tags => ['Colonization','Alert'], + filename => 'fissure_capitol_moved.txt', + params => [$new_capitol->name], + ); } else { # No more colonies, found a new empire on a remote planet # + my @zones = $db->resultset('Map::Star')->search( + undef, + { distinct => 1 })->get_column('zone')->all; + @zones = grep {@_ !~ m/0/} @zones; + my $zone = random_element(@zones); + + my @bodies = $db->resultset('Map::Body')->search({ + 'me.zone' => $zone, + 'me.empire_id' => undef, + 'stars.station_id' => undef, + 'me.class' => { like => 'Lacuna::DB::Result::Map::Body::Planet::P%' }, + 'me.orbit' => { between => [$empire->min_orbit, $empire->max_orbit] }, + },{ + join => 'stars', + rows => 100, + order_by => 'me.name', + }); + my $new_capitol = random_element(@bodies); + $empire->found($new_capitol); + # Send an email with the new planet - # Send out N19 news about the survivors. + $empire->send_predefined_message( + tags => ['Colonization','Alert'], + filename => 'fissure_capitol_moved.txt', + params => [$body->name], + ); } } else { # else it is 'just' a colony # Send an email about the destruction - - # Put something on N19 + $empire->send_predefined_message( + tags => ['Colonization','Alert'], + filename => 'fissure_colony_destroyed.txt', + params => [$body->name], + ); } + # Send out N19 news about the lost colony. + $body->add_news(10, sprintf('A huge ripple in space-time was felt, caused by the implosion of %s, millions feared dead.',$body->name)); + $body->sanitize; } - # demolish the planet + # demolish the planet (convert it into an asteroid) + $body->delete_buildings($body->building_cache); + my $new_size = randint(1,10); + $body->update({ + class => 'Lacuna::DB::Result::Map::Body::Asteroid::A'.randint(1,Lacuna::DB::Result::Map::Body->asteroid_types), + size => $new_size, + needs_recalc => 1, + usable_as_starter_enabled => 0, + alliance_id => undef, + }); # Damage planets in range (damage depends upon distance from the event) + # get 10 closest planets + my $minus_x = 0 - $body->x; + my $minus_y = 0 - $body->y; + my $closest = Lacuna->db->resultset('Map::Body')->search({ + -and => [ + { empire_id => { '>' => 1 }}, + { empire_id => { '!=' => $body->id }}, + ], + },{ + '+select' => [ + { ceil => \"pow(pow(me.x + $minus_x,2) + pow(me.y + $minus_y,2), 0.5)", '-as' => 'distance' }, + ], + '+as' => [ + 'distance', + ], + order_by => 'distance', + }); + my $damaged = 0; + DAMAGED: + while (my $to_damage = $closest->next) { + # damage planet + out("Damaging planet ".$to_damage->name." at distance ".$to_damage->get_column('distance')); + my $distance = $to_damage->get_column('distance'); + # scale so a distance of 100 causes 1% damage and a distance of 0 causes 50% damage + my $distance = $to_damage->get_column('distance'); + $distance = 1 if $distance < 1; + my $damage = $distance / 100; + foreach my $building (@{$body->building_cache}) { + my $bld_damage / randint(1,$damage); + $building->efficiency(int($building->efficiency - $bld_damage)); + $building->efficiency(0) if $building->efficiency < 0; + } + + $to_damage->empire->send_predefined_message( + tags => ['Colonization','Alert'], + filename => 'fissure_collateral_damage.txt', + params => [$body->name, $to_damage->name], + ); + if (++$damaged == 10) { + last DAMAGED; + } + } } } } diff --git a/lib/Lacuna/Role/Planet/GeoChaos.pm b/lib/Lacuna/Role/Planet/GeoChaos.pm new file mode 100644 index 00000000..d41fec26 --- /dev/null +++ b/lib/Lacuna/Role/Planet/GeoChaos.pm @@ -0,0 +1,29 @@ +package Lacuna::Role::Planet::GeoChaos; + +use Digest::MD5 qw(md5_hex); + +use Moose::Role; +use Lacuna::Constants qw(SECONDS_IN_A_DAY ORE_TYPES); + +foreach my $ore (ORE_TYPES) { + around $ore => sub { + my $orig = shift; + my $self = shift; + + my $max = $self->$orig(@_); + + # offset the day so all planets have a different start cycle + my $day = time / SECONDS_IN_A_DAY; + $day += $self->id * $self->orbit; + + # give ores a cycle of between 7 and 39 days + my $period = (hex substr md5_hex($ore.$self->id), 2, 1) % 32 + 7; + + my $radians = ($day / ($period / (2 * 3.14159))); + return int(($max/2) + sin($radians) * ($max/2)) + 1; + } +}; + + + +1; diff --git a/lib/Lacuna/Role/Planet/Weather.pm b/lib/Lacuna/Role/Planet/Weather.pm new file mode 100644 index 00000000..61a5f7cb --- /dev/null +++ b/lib/Lacuna/Role/Planet/Weather.pm @@ -0,0 +1,25 @@ +package Lacuna::Role::Planet::Weather; + +use Digest::MD5 qw(md5_hex); + +use Moose::Role; +use Lacuna::Constants qw(SECONDS_IN_A_DAY); + +around 'water' => sub { + my $orig = shift; + my $self = shift; + + my $max = $self->$orig(@_); + + # offset the day so all planets have a different start cycle + my $day = time / SECONDS_IN_A_DAY; + $day += $self->id * $self->orbit; + + # give the weather a cycle of between 7 and 39 days + my $period = (hex substr md5_hex($self->id), 2, 1) % 32 + 7; + + my $radians = ($day / ($period / (2 * 3.14159))); + return int(($max/2) + sin($radians) * ($max/2)) + 1; +}; + +1; diff --git a/t/470_fissure.t b/t/470_fissure.t new file mode 100644 index 00000000..1177c0e5 --- /dev/null +++ b/t/470_fissure.t @@ -0,0 +1,42 @@ +use lib '../lib'; + +use strict; +use warnings; + +use Test::More tests => 3; +use Test::Deep; +use Test::Memory::Cycle; +use Data::Dumper; +use 5.010; +use DateTime; +use Lacuna; + + +my $minus_x = 493; +my $minus_y = 498; +my $closest = Lacuna->db->resultset('Map::Body')->search({ + empire_id => {'>' => 1}, +},{ + '+select' => [ + { ceil => \"pow(pow(me.x + $minus_x,2) + pow(me.y + $minus_y,2), 0.5)", '-as' => 'distance' }, + ], + '+as' => [ + 'distance', + ], + order_by => 'distance', +}); + + +diag($closest); +my $damaged = 0; +DAMAGED: +while (my $to_damage = $closest->next) { + # damage planet + diag("Damaging planet ".$to_damage->name." at distance ".$to_damage->get_column('distance')); + + if (++$damaged == 10) { + last DAMAGED; + } +} + + diff --git a/var/messages/fissure_capitol_moved.txt b/var/messages/fissure_capitol_moved.txt new file mode 100644 index 00000000..eb32f7bf --- /dev/null +++ b/var/messages/fissure_capitol_moved.txt @@ -0,0 +1,9 @@ +Capitol Lost to Fissure +~~~ +Due to gross negligence the Fissure Containment System on your capitol failed today. As a result the planet imploded and most of the population was lost. + +Luckily the legislature was able to flee the planet in time, take a fast ship, and re-establish your capitol on %s, Hurrah! + +Regards, + +Your Humble Assistant diff --git a/var/messages/fissure_collateral_damage.txt b/var/messages/fissure_collateral_damage.txt new file mode 100644 index 00000000..b0e220e9 --- /dev/null +++ b/var/messages/fissure_collateral_damage.txt @@ -0,0 +1,10 @@ +Fissure causes local destruction +~~~ +The collapse of the Fissure Containment System on %s sent out a sub-ether shock-wave resulting in damage to many planets including %s. + +Local empires are investigating who is responsible for this outrage. + +Regards, + +Your Humble Assistant + diff --git a/var/messages/fissure_colony_destroyed.txt b/var/messages/fissure_colony_destroyed.txt new file mode 100644 index 00000000..1fc915a9 --- /dev/null +++ b/var/messages/fissure_colony_destroyed.txt @@ -0,0 +1,7 @@ +Colony Lost to Fissure +~~~ +Due to gross negligence the Fissure Containment System on your colony, %s, failed today. As a result the planet imploded and all of the population was lost. + +Regards, + +Your Humble Assistant diff --git a/var/messages/fissure_replaced_energy.txt b/var/messages/fissure_replaced_energy.txt new file mode 100644 index 00000000..94ff68dd --- /dev/null +++ b/var/messages/fissure_replaced_energy.txt @@ -0,0 +1,8 @@ +Fissure spawns! +~~~ +The bad maintenance of the Fissure Containment System on %s resulted in the building at %s,%s being converted into a level %s Fissure. Take immediate steps to remove both the new and the original Fissure before your planet implodes! + +Regards, + +Your Humble Assistant + diff --git a/var/messages/fissure_spawned.txt b/var/messages/fissure_spawned.txt new file mode 100644 index 00000000..55eeb6a2 --- /dev/null +++ b/var/messages/fissure_spawned.txt @@ -0,0 +1,8 @@ +Fissure spawns! +~~~ +The bad maintenance of the Fissure Containment System on %s resulted in the existing Fissure spawning a secord! Take immediate steps to remove both the new and the original Fissure before your planet implodes! + +Regards, + +Your Humble Assistant + -- 2.51.2 From a9e774e27e0aedb03d94823fa971645c714abe9a Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Mon, 17 Sep 2012 09:32:57 -0400 Subject: [PATCH 21/36] Added cron job to tick fissures and to test the weather --- bin/run_hourly.sh | 4 +++- bin/test_weather.pl | 47 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 bin/test_weather.pl diff --git a/bin/run_hourly.sh b/bin/run_hourly.sh index 026802e8..517f3439 100755 --- a/bin/run_hourly.sh +++ b/bin/run_hourly.sh @@ -15,4 +15,6 @@ perl trelvestian/send_attack.pl >>/tmp/hourly.log 2>>/tmp/hourly.log & perl diablotin/hourly_update.pl >>/tmp/hourly.log 2>>/tmp/hourly.log perl saben/hourly_update.pl >>/tmp/hourly.log 2>>/tmp/hourly.log perl delambert/hourly_update.pl >>/tmp/hourly.log 2>>/tmp/hourly.log -#perl check_for_total_victory.pl >>/tmp/hourly.log 2>>/tmp/hourly.log +perl tick_fissures.pl >>/tmp/tick_fissures.log 2>>/tmp/tick_fissures.log +perl test_weather.pl >>/tmp/test_weather.csv 2>/tmp/test_weather.log + diff --git a/bin/test_weather.pl b/bin/test_weather.pl new file mode 100644 index 00000000..06ff27eb --- /dev/null +++ b/bin/test_weather.pl @@ -0,0 +1,47 @@ +use 5.010; +use strict; +use lib '/data/Lacuna-Server/lib'; +use Lacuna::DB; +use Lacuna; +use Lacuna::Util qw(randint format_date); +use Getopt::Long; +use utf8; +$|=1; +our $quiet; +GetOptions( + 'quiet' => \$quiet, +); + + +out('Started'); +my $start = time; + +out('Loading DB'); +our $db = Lacuna->db; + +my $planet_rs = $db->resultset('Map::Body'); + +out(join(',', "Planet ID","Class","Water","Gold")); +foreach my $type (qw(P33 P34 P35 P36)) { + my @planets = $planet_rs->search( + {class => "Lacuna::DB::Result::Map::Body::Planet::$type"}, + {order_by => 'id', rows => 5}); + foreach my $planet (@planets) { + out(join(',', $planet->id,$type,$planet->water,$planet->gold)); + } +} + + + +############### +## SUBROUTINES +############### + +sub out { + my $message = shift; + unless ($quiet) { + say format_date(DateTime->now), " ", $message; + } +} + + -- 2.51.2 From db6fda2562cf7bf4faf805966bddd15490f633bd Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Mon, 17 Sep 2012 09:36:41 -0400 Subject: [PATCH 22/36] Removed merge indicator --- var/www/public/changes.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index 7dfecab0..b50660e7 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -10,7 +10,6 @@ 3.0869: - Add: Fissure now has repair cost ->>>>>>> 15d0510606e1e85d05d9dd480752b4d870874c0d 3.0868: - Fix: No longer try to send N19 news from an asteroid -- 2.51.2 From f931d6f75abd85b673978c05fdc162e3e7615297 Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Mon, 17 Sep 2012 11:17:08 -0400 Subject: [PATCH 23/36] Test Weather and all ore types --- bin/test_weather.pl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/bin/test_weather.pl b/bin/test_weather.pl index 06ff27eb..1113876b 100644 --- a/bin/test_weather.pl +++ b/bin/test_weather.pl @@ -5,6 +5,9 @@ use Lacuna::DB; use Lacuna; use Lacuna::Util qw(randint format_date); use Getopt::Long; +use Lacuna::Constants qw(ORE_TYPES); +use Data::Dumper; + use utf8; $|=1; our $quiet; @@ -20,14 +23,17 @@ out('Loading DB'); our $db = Lacuna->db; my $planet_rs = $db->resultset('Map::Body'); - -out(join(',', "Planet ID","Class","Water","Gold")); -foreach my $type (qw(P33 P34 P35 P36)) { +my @ores = sort map {$_.''} ORE_TYPES; +my $title = "Planet ID,Class,Water,"; +map { $title .= $_.',' } @ores; +print "$title\n"; +foreach my $type (qw(P33)) { my @planets = $planet_rs->search( {class => "Lacuna::DB::Result::Map::Body::Planet::$type"}, {order_by => 'id', rows => 5}); foreach my $planet (@planets) { - out(join(',', $planet->id,$type,$planet->water,$planet->gold)); + my $text = join(',', $planet->id,$type,$planet->water, map {$planet->$_} @ores); + print "$text\n"; } } -- 2.51.2 From eb67a4a2fa6d9a7b2a36ee624b4156804e006ef7 Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Tue, 18 Sep 2012 15:30:38 -0400 Subject: [PATCH 24/36] BHG can now be subsidized for both success and cooldown --- docs/BlackHoleGenerator.pod | 51 +++++++++++- .../DB/Result/Building/Permanent/Fissure.pm | 2 +- lib/Lacuna/RPC/Building/BlackHoleGenerator.pm | 78 +++++++++++++++---- var/www/public/changes.txt | 3 + 4 files changed, 116 insertions(+), 18 deletions(-) diff --git a/docs/BlackHoleGenerator.pod b/docs/BlackHoleGenerator.pod index dfcb7eb9..d7e22699 100644 --- a/docs/BlackHoleGenerator.pod +++ b/docs/BlackHoleGenerator.pod @@ -31,7 +31,33 @@ This method is extended to include the list of tasks. -=head2 generate_singularity ( session_id, building_id, target, task_name, [ params ] ) +=head2 generate_singularity + +Note: this method call now supports both the fixed argument list and the new +named argument call method (to be introduced into V4.000). For backwards compatibility +the original fixed argument list will continue to be supported but will not support +any new arguments (in this case the subsidize option). You will need to use the named +argument calling convention if you want to subsidize the BHG and achieve 'perfection'. + +=head3 fixed argument list (original calling method) + + session_id, building_id, target, task_name, [ params ] + +=head3 named arguments + + { + "session_id" : "329da49c-7e88-4897-9d8c-3e5f6309d9b7", + "building_id" : 124333, + "target" : { "body_name" : "mars" }, + "task_name" : "Change Type", + "params" : { "newtype" : 33 }, + "subsidize" : 1 + } + +Note that named arguments can be in any order. If optional then they can be omitted +the C argument will cost E to achieve 'perfection' of 100% reliability, if +omitted then you accept the risk of failure. + Returns success, failure, and side effect results. @@ -143,7 +169,8 @@ Returns status and task list with success percentage for defined target. "reason" : "You can only make an asteroid from a planet." "recovery" : 129600, "side_chance" : 25, - "success" : 0, + "success" : 50, + "essentia_cost" : 0, "throw" : 1009, "types" : [ "habitable planet", @@ -156,4 +183,24 @@ Returns status and task list with success percentage for defined target. Options are as described for generate_singularity +B is the amount in Essentia which will make the task 'perfect' (i.e. 100% success) the lower +the probability of success, the higher the cost. The minimum is 2E. + +If the chance of success is zero, then no amount of Essentia will make it succeed. + + +=head2 subsidize_cooldown ( session_id, building_id ) + +Will spend 2 essentia to cool down the BHG immediately. Returns C. + +Throws 1011. + +=head3 session_id + +A session id. + +=head3 building_id + +The unique id of the Black Hole Generator. + =cut diff --git a/lib/Lacuna/DB/Result/Building/Permanent/Fissure.pm b/lib/Lacuna/DB/Result/Building/Permanent/Fissure.pm index d7c029d3..70e89f9b 100644 --- a/lib/Lacuna/DB/Result/Building/Permanent/Fissure.pm +++ b/lib/Lacuna/DB/Result/Building/Permanent/Fissure.pm @@ -40,7 +40,7 @@ before 'can_demolish' => sub { unless ($self->efficiency >= 100) { confess [1013, 'Unless your Fissure maintenance equipment is 100% operational, it is just too dangerous to attempt']; } - unless ($self->level == 1) { + if ($self->level > 1) { confess [1013, 'You must fill in the fissure by spending resources to downgrade it before you can demolish it.']; } }; diff --git a/lib/Lacuna/RPC/Building/BlackHoleGenerator.pm b/lib/Lacuna/RPC/Building/BlackHoleGenerator.pm index 79ee22bb..92be239a 100644 --- a/lib/Lacuna/RPC/Building/BlackHoleGenerator.pm +++ b/lib/Lacuna/RPC/Building/BlackHoleGenerator.pm @@ -137,6 +137,7 @@ sub get_actions_for { $task->{reason} = $chance->{reason}; $task->{success} = $chance->{success}; $task->{throw} = $chance->{throw}; + $task->{essentia_cost} = $chance->{essentia_cost}; } return { status => $self->format_status($empire, $body), @@ -187,20 +188,38 @@ sub task_chance { return $return; } $return->{success} = (100 - $task->{base_fail}) - int( ($dist/$range) * (95-$task->{base_fail})); - $return->{success} = 5 if $return->{success} < 5; + $return->{success} = 0 if $return->{success} < 1; + + $return->{essentia_cost} = $return->{success} ? int(2000 / $return->{success})/10 : 0; + return $return; } sub generate_singularity { - my ($self, $session_id, $building_id, $target_params, $task_name, $params) = @_; - my $empire = $self->get_empire_by_session($session_id); - my $building = $self->get_building($empire, $building_id); - my $body = $building->body; - my $target = $self->find_target($target_params); - my $effect = {}; + my $self = shift; + my $args = shift; + + if (ref($args) ne "HASH") { + $args = { + session_id => $args, + building_id => shift, + target => shift, + task_name => shift, + params => shift, + }; + } + my $empire = $self->get_empire_by_session($args->{session_id}); + my $building = $self->get_building($empire, $args->{building_id}); + my $task_name = $args->{task_name}; + my $subsidize = $args->{subsidize}; + + my $body = $building->body; + my $target = $self->find_target($args->{target}); + my $effect = {}; + my $return_stats = {}; if ($building->is_working) { - confess [1010, 'The Black Hole Generator is cooling down from the last use.'] + confess [1010, 'The Black Hole Generator is cooling down from the last use.']; } unless (defined $target) { confess [1002, 'Could not locate target.']; @@ -221,6 +240,12 @@ sub generate_singularity { $task->{side_chance} = $bhg_param->{side_chance} if ($bhg_param->{side_chance}); $chance->{success} = $bhg_param->{success} if ($bhg_param->{success}); } + if ($subsidize) { + if ($empire->essentia < $chance->{essentia_cost}) { + confess [1011, "Not enough essentia."]; + } + $chance->{success} = 100; + } my $btype; my $tempire; @@ -324,11 +349,11 @@ sub generate_singularity { $body->spend_waste($task->{waste_cost})->update; $building->start_work({}, $task->{recovery})->update; -# Pass the basic checks -# Check for startup failure + # Pass the basic checks + # Check for startup failure my $roll = randint(0,99); - unless ($roll < $chance->{success}) { -# Something went wrong with the start + if ($roll >= $chance->{success}) { + # Something went wrong with the start my $fail = randint(0,19); if ($fail == 0) { $return_stats = bhg_self_destruct($building); @@ -371,7 +396,7 @@ sub generate_singularity { $effect->{fail} = $return_stats; } else { -# We have a working BHG! + # We have a working BHG! if ($task->{name} eq "Make Planet") { $return_stats = bhg_make_planet($building, $target); $body->add_news(50, @@ -387,7 +412,7 @@ sub generate_singularity { $body->add_news(50, sprintf('%s has expanded %s.', $empire->name, $target->name)); } elsif ($task->{name} eq "Change Type") { - $return_stats = bhg_change_type($target, $params); + $return_stats = bhg_change_type($target, $args->{params}); $body->add_news(50, sprintf('The geology of %s has been extensively altered by powers unknown', $target->name)); } elsif ($task->{name} eq "Swap Places") { @@ -432,6 +457,9 @@ sub generate_singularity { $effect->{side} = $return_stats; } } + if ($subsidize) { + } + return { status => $self->format_status($empire, $body), effect => $effect, @@ -1142,7 +1170,27 @@ sub bhg_tasks { return @tasks; } -__PACKAGE__->register_rpc_method_names(qw(generate_singularity get_actions_for)); +sub subsidize_cooldown { + 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, "No one is searching."]; + } + + unless ($empire->essentia >= 2) { + confess [1011, "Not enough essentia."]; + } + + $building->finish_work->update; + $empire->spend_essentia(2, 'BHG cooldown subsidy after the fact'); + $empire->update; + + return $self->view($empire, $building); +} + +__PACKAGE__->register_rpc_method_names(qw(generate_singularity get_actions_for subsidize_cooldown)); no Moose; __PACKAGE__->meta->make_immutable; diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index b50660e7..6316bcba 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -1,3 +1,6 @@ +future: + - Add: Black Hole Generator can now be subsidized both for accuracy and cooldown + 3.0870: - Fix: Black Hole Generator now creates all new planet/asteroid types - Add: Fissure now sucks in energy from your planet based on it's level and efficiency -- 2.51.2 From 6309bcf5b9bb175b1c187c7fba8098d9bf364449 Mon Sep 17 00:00:00 2001 From: ysth Date: Wed, 19 Sep 2012 12:50:42 -0700 Subject: [PATCH 25/36] document view_excavators "travelling" --- docs/Archaeology.pod | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/Archaeology.pod b/docs/Archaeology.pod index 33b86395..da192271 100644 --- a/docs/Archaeology.pod +++ b/docs/Archaeology.pod @@ -133,7 +133,8 @@ Returns a list of the excavator sites currently controlled by this ministry. { "status" : { ... }, - "max_excavators" : 1, + "max_excavators" : 2, + "travelling" : 1, "excavators" : [ { "id" : "id-goes-here", -- 2.51.2 From 922054c6c1dfc1a3b1b84cd87a06c509446d04c2 Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Wed, 19 Sep 2012 16:52:01 -0400 Subject: [PATCH 26/36] Fixed it so that when a Fissure explodes it causes damage to nearby colonies. --- bin/tick_fissures.pl | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/bin/tick_fissures.pl b/bin/tick_fissures.pl index 45ea3cad..dae33430 100644 --- a/bin/tick_fissures.pl +++ b/bin/tick_fissures.pl @@ -227,7 +227,7 @@ for my $body_id (sort keys %has_fissures) { ); } # Send out N19 news about the lost colony. - $body->add_news(10, sprintf('A huge ripple in space-time was felt, caused by the implosion of %s, millions feared dead.',$body->name)); + $body->add_news(100, sprintf('A huge ripple in space-time was felt, caused by the implosion of %s, millions feared dead.',$body->name)); $body->sanitize; } # demolish the planet (convert it into an asteroid) @@ -266,14 +266,20 @@ for my $body_id (sort keys %has_fissures) { out("Damaging planet ".$to_damage->name." at distance ".$to_damage->get_column('distance')); my $distance = $to_damage->get_column('distance'); - # scale so a distance of 100 causes 1% damage and a distance of 0 causes 50% damage + # scale so a distance of 100 causes 1% damage and a distance of 0 causes + # an average of 50% damage my $distance = $to_damage->get_column('distance'); - $distance = 1 if $distance < 1; - my $damage = $distance / 100; - foreach my $building (@{$body->building_cache}) { - my $bld_damage / randint(1,$damage); + my $damage = int(100 - $distance); + $damage = 1 if $damage < 1; + out(" Causing an average of $damage damage to each building"); + my @all_buildings = @{$to_damage->building_cache}; + out(" there are ".scalar(@all_buildings)." buildings"); + foreach my $building (@all_buildings) { + my $bld_damage = randint(1,$damage); + out("Damaging ".$building->name." by ${bld_damage}%"); $building->efficiency(int($building->efficiency - $bld_damage)); $building->efficiency(0) if $building->efficiency < 0; + $building->update; } $to_damage->empire->send_predefined_message( -- 2.51.2 From 3bd8ad2432c2388f100004ac49f7dc919cd3075b Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Thu, 20 Sep 2012 02:52:14 -0400 Subject: [PATCH 27/36] Stars are now sorted in Parliament --- lib/Lacuna/RPC/Building/Parliament.pm | 2 +- var/www/public/changes.txt | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/Lacuna/RPC/Building/Parliament.pm b/lib/Lacuna/RPC/Building/Parliament.pm index d5438b01..b30d1610 100644 --- a/lib/Lacuna/RPC/Building/Parliament.pm +++ b/lib/Lacuna/RPC/Building/Parliament.pm @@ -52,7 +52,7 @@ sub get_stars_in_jurisdiction { my $empire = $self->get_empire_by_session($session_id); my $building = $self->get_building($empire, $building_id); my @out; - my $stars = $building->body->stars; + my $stars = $building->body->stars->search({},{order_by => name}); while (my $star = $stars->next) { push @out, $star->get_status; } diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index 6316bcba..c3b9a033 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -1,7 +1,6 @@ -future: - - Add: Black Hole Generator can now be subsidized both for accuracy and cooldown - 3.0870: + - Add: Black Hole Generator can now be subsidized both for accuracy and cooldown + - Fix: List of stars to rename in Parliament are now sorted - Fix: Black Hole Generator now creates all new planet/asteroid types - Add: Fissure now sucks in energy from your planet based on it's level and efficiency - Add: You can now repair the fissure stabilization equipment at a Fissure. -- 2.51.2 From ba36e3fcadd8a913648672d6d9173277ebe38edd Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Thu, 20 Sep 2012 03:41:07 -0400 Subject: [PATCH 28/36] Added test for star order in Parliament --- lib/Lacuna/RPC/Building/Parliament.pm | 2 +- t/480_parliament_stars.t | 82 +++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 t/480_parliament_stars.t diff --git a/lib/Lacuna/RPC/Building/Parliament.pm b/lib/Lacuna/RPC/Building/Parliament.pm index b30d1610..8c1a27c7 100644 --- a/lib/Lacuna/RPC/Building/Parliament.pm +++ b/lib/Lacuna/RPC/Building/Parliament.pm @@ -52,7 +52,7 @@ sub get_stars_in_jurisdiction { my $empire = $self->get_empire_by_session($session_id); my $building = $self->get_building($empire, $building_id); my @out; - my $stars = $building->body->stars->search({},{order_by => name}); + my $stars = $building->body->stars->search({},{order_by => "name"}); while (my $star = $stars->next) { push @out, $star->get_status; } diff --git a/t/480_parliament_stars.t b/t/480_parliament_stars.t new file mode 100644 index 00000000..ff718684 --- /dev/null +++ b/t/480_parliament_stars.t @@ -0,0 +1,82 @@ +use lib '../lib'; + +use strict; +use warnings; + +use Test::More tests => 3; +use Test::Deep; +use Test::Memory::Cycle; +use Data::Dumper; +use 5.010; +use DateTime; +use Lacuna; +use TestHelper; + +my $empire_name = 'TLE Test Empire'; +my $station_name = 'TLE Test SS'; + +my $tester = TestHelper->new({empire_name => $empire_name}); +my $empire = $tester->empire; +my $session = $empire->start_session({api_key => 'tester'}); + +my ($station) = Lacuna->db->resultset('Map::Body::Planet')->search({name => $station_name}); + +my $stars = Lacuna->db->resultset('Star')->search; + +# get all stars in this stations jurisdiction +# give them a name we can sort by +my $stars_rs = $stars->search({ station_id => $station->id }); +my $star_num = '001'; +while( my $star = $stars_rs->next ) { + diag ("Rename ".$star->name." to $station_name $star_num"); + $star->name("$station_name $star_num"); + $star->update; + $star_num++; +} + +# TODO Call get_stars_in_jurisdiction and check sort order + + +my $influence_spent = $station->influence_spent; +my $influence_remaining = $station->influence_remaining; + +# get unseized stars in order distance from station. +my $minus_x = 0 - $station->x; +my $minus_y = 0 - $station->y; + +my $closest = Lacuna->db->resultset('Star')->search({ + station_id => 0, +},{ + '+select' => [ + { ceil => \"pow(pow(me.x + $minus_x,2) + pow(me.y + $minus_y,2), 0.5)", '-as' => 'distance' }, + ], + '+as' => [ + 'distance', + ], + order_by => 'distance', +}); + +# Test setting seize propositions +while ($influence_remaining) { + my $star = $closest->next; + + diag("Propose seizing star ".$star->name); + my $proposition = Lacuna->db->resultset('Lacuna::DB::Result::Propositions')->new({ + type => 'SeizeStar', + name => 'Seize '.$star->name, + description => 'Seize control of {Starmap '.$star->x.' '.$star->y.' '.$star->name.'} by {Planet '.$station->id.' '.$station->name.'}, and apply all present laws to said star and its inhabitants.', + scratch => { star_id => $star->id }, + proposed_by_id => $empire->id, + }); + $proposition->station($station); + $proposition->proposed_by($empire); + $proposition->insert; + $influence_remaining--; +} + +# TODO check that we can vote on propositions. +# TODO check that stars are in order. +# TODO check that propositions are in order. + +1; + -- 2.51.2 From b606cbe06b1a92ef3b2fd2db679e62de066285ba Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Thu, 20 Sep 2012 04:04:57 -0400 Subject: [PATCH 29/36] Fixed test for star sort order --- t/480_parliament_stars.t | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/t/480_parliament_stars.t b/t/480_parliament_stars.t index ff718684..55ece69f 100644 --- a/t/480_parliament_stars.t +++ b/t/480_parliament_stars.t @@ -13,7 +13,7 @@ use Lacuna; use TestHelper; my $empire_name = 'TLE Test Empire'; -my $station_name = 'TLE Test SS'; +my $station_name = 'TLE Test Station'; my $tester = TestHelper->new({empire_name => $empire_name}); my $empire = $tester->empire; @@ -21,7 +21,7 @@ my $session = $empire->start_session({api_key => 'tester'}); my ($station) = Lacuna->db->resultset('Map::Body::Planet')->search({name => $station_name}); -my $stars = Lacuna->db->resultset('Star')->search; +my $stars = Lacuna->db->resultset('Map::Star')->search; # get all stars in this stations jurisdiction # give them a name we can sort by @@ -44,8 +44,8 @@ my $influence_remaining = $station->influence_remaining; my $minus_x = 0 - $station->x; my $minus_y = 0 - $station->y; -my $closest = Lacuna->db->resultset('Star')->search({ - station_id => 0, +my $closest = Lacuna->db->resultset('Map::Star')->search({ + station_id => undef, },{ '+select' => [ { ceil => \"pow(pow(me.x + $minus_x,2) + pow(me.y + $minus_y,2), 0.5)", '-as' => 'distance' }, @@ -60,7 +60,7 @@ my $closest = Lacuna->db->resultset('Star')->search({ while ($influence_remaining) { my $star = $closest->next; - diag("Propose seizing star ".$star->name); + diag("Propose seizing\t".$star->x."\t".$star->y."\t ".$star->name); my $proposition = Lacuna->db->resultset('Lacuna::DB::Result::Propositions')->new({ type => 'SeizeStar', name => 'Seize '.$star->name, -- 2.51.2 From 287ad1bd6580391383e4b9c7f7c8586cf8150e74 Mon Sep 17 00:00:00 2001 From: ysth Date: Thu, 20 Sep 2012 10:38:36 -0700 Subject: [PATCH 30/36] shipyard get_buildable: report queue availability, not just how many docks --- lib/Lacuna/RPC/Building/Shipyard.pm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/Lacuna/RPC/Building/Shipyard.pm b/lib/Lacuna/RPC/Building/Shipyard.pm index 09704303..dd1c91d4 100644 --- a/lib/Lacuna/RPC/Building/Shipyard.pm +++ b/lib/Lacuna/RPC/Building/Shipyard.pm @@ -138,9 +138,14 @@ sub get_buildable { if (defined $port) { $docks = $port->docks_available; } + my $max_ships = $building->max_ships; + my $total_ships_building = Lacuna->db->resultset('Lacuna::DB::Result::Ships')->search({body_id => $self->body_id, task=>'Building'})->count; + return { buildable => \%buildable, docks_available => $docks, + build_queue_max => $max_ships, + build_queue_used => $total_ships_building, status => $self->format_status($empire, $building->body), }; } -- 2.51.2 From d5575e7d7ae0388b0219dee34157486efb012df9 Mon Sep 17 00:00:00 2001 From: ysth Date: Thu, 20 Sep 2012 10:41:49 -0700 Subject: [PATCH 31/36] shipyard get_buildable: report queue availability, not just how many docks --- docs/Shipyard.pod | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/Shipyard.pod b/docs/Shipyard.pod index 4d2062f9..6fe73955 100644 --- a/docs/Shipyard.pod +++ b/docs/Shipyard.pod @@ -91,6 +91,8 @@ Returns a list of buildable ships and their costs, and if they're not buildable, ... }, "docks_available" : 7, # you can only build ships up to the number of docks you have available + "build_queue_max" : 60, # maximum queueable ships + "build_queue_used" : 3, # ships in queue for all shipyards "status" : { ... }, } -- 2.51.2 From d833cff409792800f5cb60ba717ba187de613277 Mon Sep 17 00:00:00 2001 From: lemming552 Date: Thu, 20 Sep 2012 21:23:03 -0600 Subject: [PATCH 32/36] building->body_id not self->body_id --- lib/Lacuna/RPC/Building/Shipyard.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Lacuna/RPC/Building/Shipyard.pm b/lib/Lacuna/RPC/Building/Shipyard.pm index dd1c91d4..7b30464f 100644 --- a/lib/Lacuna/RPC/Building/Shipyard.pm +++ b/lib/Lacuna/RPC/Building/Shipyard.pm @@ -139,7 +139,7 @@ sub get_buildable { $docks = $port->docks_available; } my $max_ships = $building->max_ships; - my $total_ships_building = Lacuna->db->resultset('Lacuna::DB::Result::Ships')->search({body_id => $self->body_id, task=>'Building'})->count; + my $total_ships_building = Lacuna->db->resultset('Lacuna::DB::Result::Ships')->search({body_id => $building->body_id, task=>'Building'})->count; return { buildable => \%buildable, -- 2.51.2 From c62a1806d68974e8c696ffdfa8cd1e5dfa3155ea Mon Sep 17 00:00:00 2001 From: lemming552 Date: Thu, 20 Sep 2012 21:34:15 -0600 Subject: [PATCH 33/36] Updated changes.txt --- var/www/public/changes.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index c3b9a033..acb072fe 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -8,7 +8,11 @@ - Mod: Increase size on habitables can now get to new max. Soft Cap 70, Hard Cap 75. - Fix: Check body type closely for building BHG. - Fix: Spies that are being transported or sold are listed as prisoners in Security and Police Station. + - Add: Last task of Foreign Spies listed and prisoners have a status of Captured or Prisoner Transport. - Add: Some planets now have seasons. + - Add: Available Shipyard Queue now returned. + - UI : Shipyard Queue available displayed. + - UI : Prisoners being transported or sold displayed as prisoners. 3.0869: - Add: Fissure now has repair cost -- 2.51.2 From 563ffeab654f22deab16d6b70912879bb8016a62 Mon Sep 17 00:00:00 2001 From: ysth Date: Fri, 21 Sep 2012 04:57:46 -0700 Subject: [PATCH 34/36] observator get probed stars: report count of probes en route --- docs/Observatory.pod | 4 +++- lib/Lacuna/RPC/Building/Observatory.pm | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/Observatory.pod b/docs/Observatory.pod index fd38c439..701b0818 100644 --- a/docs/Observatory.pod +++ b/docs/Observatory.pod @@ -26,7 +26,9 @@ Returns a list of the stars that have been probed by this planet. ... ] ], - "star_count" : 37 + "star_count" : 37, + "max_probes" : 90, + "travelling" : 2 } diff --git a/lib/Lacuna/RPC/Building/Observatory.pm b/lib/Lacuna/RPC/Building/Observatory.pm index 695dd36d..f71001b5 100644 --- a/lib/Lacuna/RPC/Building/Observatory.pm +++ b/lib/Lacuna/RPC/Building/Observatory.pm @@ -45,12 +45,14 @@ sub get_probed_stars { while (my $probe = $probes->next) { push @stars, $probe->star->get_status($empire); } + my $travelling = Lacuna->db->resultset('Lacuna::DB::Result::Ships')->search({ body_id => $building->body_id, type=>'probe', task=>'Travelling' })->count; return { stars => \@stars, star_count => $probes->pager->total_entries, status => $self->format_status($empire, $building->body), max_probes => $building->max_probes, - }; + travelling => $travelling, + }; } __PACKAGE__->register_rpc_method_names(qw(get_probed_stars abandon_probe)); -- 2.51.2 From 0c1b8d1ceed2e5bb328d017b6603ebebd14ab4a6 Mon Sep 17 00:00:00 2001 From: lemming552 Date: Sat, 22 Sep 2012 21:19:31 -0600 Subject: [PATCH 35/36] Changes.txt --- var/www/public/changes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index acb072fe..00865edd 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -11,6 +11,7 @@ - Add: Last task of Foreign Spies listed and prisoners have a status of Captured or Prisoner Transport. - Add: Some planets now have seasons. - Add: Available Shipyard Queue now returned. + - Add: Observatory get probed stars: report count of probes en route - UI : Shipyard Queue available displayed. - UI : Prisoners being transported or sold displayed as prisoners. -- 2.51.2 From 09b2df707caee939da02eb072c685dbff583ded7 Mon Sep 17 00:00:00 2001 From: lemming552 Date: Sat, 22 Sep 2012 21:44:06 -0600 Subject: [PATCH 36/36] its --- var/www/public/changes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index 00865edd..5215940f 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -2,7 +2,7 @@ - Add: Black Hole Generator can now be subsidized both for accuracy and cooldown - Fix: List of stars to rename in Parliament are now sorted - Fix: Black Hole Generator now creates all new planet/asteroid types - - Add: Fissure now sucks in energy from your planet based on it's level and efficiency + - Add: Fissure now sucks in energy from your planet based on its level and efficiency - Add: You can now repair the fissure stabilization equipment at a Fissure. - Add: You can only downgrade or demolish a Fissure which is 100% maintained. - Mod: Increase size on habitables can now get to new max. Soft Cap 70, Hard Cap 75. -- 2.51.2