Giter VIP home page Giter VIP logo

smr's Introduction

Run Tests Test Coverage PHPStan Level Build Live

Installation

Dependencies

Make sure the following software is installed:

  • docker (version 19.03.0+)
  • docker compose plugin (v2)

To run unit tests on your machine:

  • Composer (2.0.5+)

Setup

First, you will need to clone this repository. Then inside the clone, you will need to create installation-specific copies of the following files:

  • .env.sample.env
  • config/config.specific.sample.phpconfig/config.specific.php

The sample versions have sensible defaults, but update the copies as necessary. The options must be consistent between the various configuration files.

Populate the mysql database

To initialize the database or update it with new patches, run:

docker compose run --rm flyway

To modify the database, add a file called V<VERSION_NUMBER>__<NAME>.sql into db/patches and rerun the command.

You can optionally start up phpMyAdmin to inspect your mysql database in a web browser at http://localhost/pma/:

docker compose up --build -d pma

Start up the services

Then you can start up the persistent game services

docker compose up --build -d traefik smr

For development, it may be desirable to automatically pick up source code changes without rebuilding the docker image. Simply use the smr-dev service instead of smr, i.e.:

docker compose up --build -d traefik smr-dev

Runtime

Permissions

In order to create an admin account you should first create a standard account via the register form, then run the following command to give that account admin permissions:

db/init_admin.sh

The account should now have an "Admin Tools" link on the left whilst logged in, which will allow you to assign any extra permissions to yourself and others.

Creating a Game

To create a game you will have to have assigned yourself the "1.6 Universe Generator" and then access this link via the admin tools to create the game. Once you are happy with the game you need to edit the "game" table and set the "enabled" flag for your game to 'TRUE' in order for it to appear in the list of games to join.

Coding Style

This is the coding style that should be used for any new code, although currently not all code currently follows these guidelines (the guidelines are also likely to require extension).

  • Opening races should be placed on the same line with a single space before

  • Single line if statements should still include braces

     if (true) {
     }
  • Variable names should be camelCase normally, except when in templates when they should be UpperCamelCase (to enforce some mental separation between the two contexts).

     $applicationVar = 'value';
     $TemplateVar = 'value';
  • Function names should be camelCase, class names should be UpperCamelCase

     function exampleFunction() {
    
     }
    
     class ExampleClass {
     	public function exampleMethod() {
     	}
     }
  • Associative array indices should be UpperCamelCase

     $container['SectorID'] = $sectorID;

SMR-isms

File inclusion

Classes should be added to src/lib/Smr to take advantage of the PSR-4 autoloader. Engine files and their associated templates should be placed in src/engine and src/templates respectively (see Page::process for how they will be included).

Links

If possible use a function from Globals or a relevant object to generate links (e.g. Globals::getCurrentSectorHREF() or $otherPlayer->getExamineTraderHREF()). This is usually clearer and allows hooking into the hotkey system. To create a link you first create a "container" using a Page class, e.g.:

$container = new CurrentSector();

You can then call $container->href() to get a HREF, which will give a link that can be displayed on the page. In this example, clicking the link will load the "Current Sector" page next.

You can also call $container->go(), which will immediately forward to this page within the same HTTP request.

Request variables

For any page which takes input through POST or GET, these values may be accessed using Smr\Session::getRequestVar() and relatives, which will store the value in the session. When a page is auto-refreshed with AJAX, these inputs are not resent, but they are still required to render the page correctly.

Abstract vs normal classes

This initially started out to be used in the "standard" way for NPCs but that idea has since been discarded. Now all core/shared "Default" code should be in the abstract version, with the normal class child implementing game type specific functionality/overrides, for instance "lib/Semi Wars/Account" which is used to make every account appear to be a "vet" account when playing semi wars.

Unit testing

SMR uses PHPUnit to run unit tests.

Setup

  1. Ensure the MySQL container is running, and ready for any integration tests that touch the database:
    • composer start:test-services
  2. Run composer phpunit to execute the full suite of PHPUnit tests.
  3. Add new tests as needed in the /test directory.

Setting up your IDE to run tests

This information applies to IDEA-based IDEs, e.g. IntelliJ, PHPStorm. For other vendors, please refer to your vendor's documentation for running PHPUnit tests against a remote container.

  • In order to perform these next steps in IntelliJ, you must have the following Jetbrains-provided plugins installed:
  • PHP
  • PHP Docker
Configure a remote PHP interpreter for the project
  1. File > Settings > Languages & Frameworks > PHP. In the CLI Interpreter area, click the ... button
  2. Press the "+" button in the top left, and select From Docker, Vagrant, VM, WSL, Remote...
  3. In the new window, choose Docker Compose, and in the Service area, select phpunit. Press "OK".
  4. It will check the configuration by starting up the Docker container, and gathering PHP information. Once that's finished, you should be on a configuration screen for the new interpreter. It should have the PHP information from the Docker container, and also the Xdebug information.
  5. In the Environment variables box on the new intepreter's screen, paste in the values from /test/env in the project directory.
  6. The rest of the default settings should be fine, so you can press "Apply".
  7. On the settings navigation tree, underneath PHP, click the Composer item: In the CLI Interpreter drop down, select the new interpreter you've created. Press "Apply".
  8. On the settings navigation tree, underneath PHP, click the Test Frameworks item.
  9. Click the + button to create an entry, select the newly created interpreter from the drop down, and press "OK".
  10. In the PHPUnit library section, set the Path to script value to /smr/vendor/autoload.php
  11. In the Test Runner section, set the Default configuration file to /smr/phpunit.xml
  12. Press "OK", and you should be good to go for executing tests inside the IDE.

Writing integration tests

  1. To create an integration test that uses the database, your test should extend SmrTest\BaseIntegrationSpec. This will ensure that any test data that gets written to the database will be cleaned up after each test.
  • The SMR database uses MyISAM for a storage engine, so we cannot simply rollback transactions after each test. Instead, the BaseIntegrationSpec will check for any tables that are populated from the flyway migration during startup, and truncate all other tables after your test.

smr's People

Contributors

curufir avatar dependabot-preview[bot] avatar dependabot[bot] avatar hemberger avatar imgbotapp avatar jdormer avatar lgtm-com[bot] avatar michaelkunze avatar page- avatar red-cross-knight avatar scrutinizer-auto-fixer avatar snyk-bot avatar stupidnewbie avatar tmaus avatar wcyrek avatar witold-cyrek avatar xaerodegreaz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

smr's Issues

Port Goods Refresh With Differing Rates

Different port goods refresh at different rates, but only one "last update" time is stored for all of them, which is only incremented by the smallest time addition of any of the goods that were increased. Realistically this time needs to be stored for each good, as currently it means when the page is being refreshed regularly (ie sat on port with the ajax autorefresh), the lower level goods refresh much quicker than they should (due to having a lot of their refresh not increment the last update, since the higher level goods didn't refresh at all)

Color preferences do not apply to the Galaxy Map

If you change the color preferences (e.g. "Friendly colour"), those changes apply to the local map, but do not apply to the galaxy map. The galaxy map retains the default colors. This can be confusing when reading the galaxy map, especially since the default colors are not colorblind-friendly.

Remove improper uses of references

In strict PHP, you can only assign variables by reference. Things
that are not variables include function calls and constants.

So we begin the herculean task of removing all unneeded references.
Here are some important details about references:

  • Objects are always passed/copied by reference (in the c++ sense).
    We can pass an object without the & and still access/modify
    its internal data.

  • Arrays are passed/copied by value, but not really because of
    copy-on-write, which means that it will only make a copy of
    the array if you try to modify it.

  • References disable copy-on-write. If you have an array that was
    copied by value, and then you take a reference to it, you will
    immediately make a copy of it, even if the reference doesn't
    modify that array.

Moral of the story

Do not use references in an attempt to improve performance. PHP
does all the right performance things behind the scenes if
you are using the language in the intended way.

References are only intended for when you truly want to pass
something to another function and have that function modify it.

For more details, see
http://schlueters.de/blog/archives/125-Do-not-use-PHP-references.html

InternalServerError in lib/Login/loginSmarty.php

The line

$gameNews[] = array('Date' => date(DEFAULT_DATE_DATE_SHORT,$db->getField('time')), 'Time' => date(DEFAULT_DATE_TIME_SHORT,$db->getField('time')), 'Message' => bbifyMessage($db->getField('news_message')));

gives a 500 error on login. has been commented for the time being.

Docker PHP is slower than host by roughly 5x

Test configurations and rough average page load times:

live (nginx + php-fpm): 0.01s
live (nginx + php-apache docker): 0.05s
dev (nginx + php-fpm both docker): 0.04s
dev (php-apache docker): 0.04s

For the live configurations, mysql is on the host and PHP connects via a socket. For the dev configurations, mysql is in docker (with /var/lib/mysql in a data volume) and the PHP container connects with the usual networking scheme.

For reference, the live configuration uses the "overlay2" storage driver, while dev uses "aufs".

Possible causes of the slownless:

  • Network latency communicating with mysql (unlikely since the socket connection is also slow)
  • Network latency and/or filesystem I/O with volume mounts (I guess... but why would they have the same performance degredation?)
  • Apache vs. Nginx+FPM (unlikely since both are slow)
  • Production php.ini vs. development (tested both, and only about a 10% change in speed, not a 500% change)

I did some profiling with Xdebug (in dev only, haven't set it up on live), and noticed that the mysql calls were the greatest expense by far on every page, which I assumed confirmed my suspicion that it was somehow related to the way we were connecting to mysql within docker.
image

However, when I came across this bug report (after flailing with google searches trying in a last desperate attempt to understand what was causing this slowness), I realized that all the file includes did seem a bit expensive.

docker-library/php#493

image
(Perhaps ~25% just for require_once on this page.)

I think any satisfying conclusion involves using Xdebug to profile the speedy live configuration. In the meantime, we can monitor the above bug report to see if anyone confirms that this is an issue with Docker itself.

Switch from AWStats to GoogleAnalytics?

Now that the server has been rebooted, AWStats is working again. However, I think that switching to GoogleAnalytics may still be preferable.

Some of the benefits:

  • Google's servers are reliable, and we don't need to worry about maintaining it on our server
  • Additional enterprise features that aren't available in AWStats
  • It will work no matter where or how the server is hosted

Disadvantages:

  • It will download a ~35 byte file on every page load (this usually takes ~10ms)
  • We probably have to do a little more work if we want to track ajax updates

Upgrade to php7

The current Dockerfile uses php 5.4, which has already reached end of life. We should switch to 5.6 as soon as possible, which, while active support was dropped in Jan 2017, security support will continue until the end of 2018. I have extensively tested the game, Caretaker, and NPC's with 5.6 and have found no incompatibilities, so I'd be happy to see the upgrade immediately (I'd be happy to provide a PR if desired).

However, we'd be well advised to upgrade to php 7+, which I am beginning to test now. One of the biggest changes that needs to be made is migrating to a new MySQL API, since php-mysql was deprecated in php 5.5. Here are some considerations to help choose between PDO and mysqli. Are there any preferences?

CSRF state token does not match one provided

There might be a problem with the login_processing.php and Facebook.

I'm getting alot of those in my server log:

2014/10/27 04:03:31 [error] 17076#0: *4093313 FastCGI sent in stderr: "PHP message: CSRF state token does not match one provided" while reading response header from upstream, client: xxx.xxx.xxx.xxx, server: www.smrealms.de, request: "GET /login_processing.php?loginType=Facebook&code=XXXXXXX&state=XXXXXX HTTP/1.1", upstream: "fastcgi://unix:/some/path/php5-fpm.sock:", host: "www.smrealms.de", referrer: "https://www.facebook.com/dialog/oauth?client_id=XXXXX&redirect_uri=https%3A%2F%2Fwww.smrealms.de%2Flogin_processing.php%3FloginType%3DFacebook&state=XXXXX&scope=email"

Anon Account Viewing on Admin tools

An issue with anon account view on admin tools. it keeps looking up the very first game name of the account even if you are looking up an account for this game. for example:

[16:14] ok check out anon account 6
[16:15] <~Hot_MaMa> k
[16:16] <~Hot_MaMa> JettJackson Deposit 1
[16:16] <~Hot_MaMa> JettMulti Payment 1
[16:16] <~Hot_MaMa> see its using the first name that account used for the player name
[16:16] <~Hot_MaMa> when i do it for my annon account it uses hot mama and nala wich was the fisrt name i gave my multi
[16:18] hmm
[16:18] maybe it is using the account name?
[16:22] <~Hot_MaMa> nope cause my account name is hot mama 2 for my multi
[16:22] <~Hot_MaMa> i just found that odd
[16:27] <~Hot_MaMa> i mean its not a huge deal cause i can then search for that player name in the multi tools
[16:27] <~Hot_MaMa> noticed it when i was looking into the sergi molly thing earlier
[16:36] ahh
[16:36] yeah its odd

Coldfront IRC server is now The Airlock

The rebranding of the Coldfront IRC server has caused several items to break:

  1. The in-game IRC Chat link reports that the user is banned (though it is simply because the server address still points to the Coldfront address) and does not allow them to connect.
  2. Some of the IRC tools point to the wrong server and will not work (including Caretaker).

The server address needs to be updated from irc.coldfront.net to irc.theairlock.net.

I will submit a merge request to address the problems that can be fixed in code, but at least one thing will need to be updated on the server hosting SMR (tools/irc/config.specific.php needs to have its IRC_BOT_SERVER_ADDRESS changed to irc.theairlock.net because it is not a version-controlled file).

Ports reset to 1 good on each shot

To save combat logs for future viewing, all combatant data is serialized and then saved in the combat_logs table. For port raids, this includes the target port. However, part of the serialization routine for SmrPort is to set all the goods to 1 supply to increase the efficiency of the cache (see SmrPort::__sleep), because if they had different supply, everyone would see different versions of the cached port. Since the serialization (perhaps unwisely) modifies the port itself, this means we suddenly have a cached port in the $CACHE_PORTS global; all ports in $CACHE_PORTS are updated in the database at the end of every HTTP request (e.g. in do_voodoo()), and so in this case the modified supply is incorrectly saved.

NOTE: the nomenclature is confusing here. $CACHE_PORTS is where regular SmrPort instances are cached. A "cached port" is an SmrPort that has been slimmed down for serialization, and should never be in $CACHE_PORTS, but rather in $CACHE_CACHED_PORTS. The slimmed down version probably should have used a different word than "cached" to avoid this ambiguity.

This bug can be fixed by avoiding serialization of the SmrPort when the combatant data is saved in the combat_logs table. Since we only use the name of the port in the logs, we could easily store the TargetPortName instead of TargetPort. But this breaks the consistent structure of how the combat logs are saved for port, planet, force, and player combat.

There is another solution that is a lot more work, but, by my evaluation, much more correct. And that is to fix the serialization routine for SmrPort so that it is not modifying the port it is serializing. Doing so actually simplifies some routines (e.g. addCachePorts) that were doing extra work to undo this modification.

Increasing Build times

The idea behind this is to allow planets to be built quickly in the beginning and to take longer near the end. The following formula has been provided (may require revision). This is JUST for build times only, calculating experience using a similar formula can be introduced later (exp per build is currently stored in DB)

Actual Formula n=current build number
Turret (3+((n)^1.55)_LOG10(n)^2)_1/GameSpeed
Hanger (0.5+((n/10)^0.8)_LOG10(n)^1)_1/GameSpeed
Gens (0.5+((n/10)^0.8)_LOG10(n)^1)_1/(2_GameSpeed)
Experience: BuildTime_10 (total exp ~11.5k per planet, open to interpretation)

Concerns:
[3:56:38 PM] Page: the formula seems inherently flawed
[3:57:05 PM] Page: because total build time will be a lot longer if you build gens first and a lot shorter if you build turrets first
[3:57:29 PM] Page: because it takes into account the total building built so far and not the total time spent building so far

[3:59:15 PM] Michael Moody (Curufir): No real issue. Change n to number of structure (e.g. N turrets/Max turrets)
[3:59:19 PM] Michael Moody (Curufir): *70

Versioning CSS files

I have hesitated to make improvements to the CSS because of caching. It would be nice to implement a strategy that will ensure the new CSS files are downloaded if they happen to change. The most canonical way I know to do this is to add a version number to the CSS link, which tricks the browser into downloading it, even though the actual path of the file has not changed.

See https://stackoverflow.com/questions/7671168/why-adding-version-number-to-css-file-path.

Any objections to this approach?

Newsletter - Admin tool

Ability to submit newsletterin HTML format. Save to Db, preview ability.

Add approval requirement of 3 admins before newsletter can be sent

Question about color options in Account Preferences

There appear to be three new color options in Account Preferences (Friendly, Neutral, and Enemy). I assumed that these would apply to the Trader icons on the Local Map. But when I change these color options, I cannot identify anything in the game that is changing. What are these options supposed to change?

By the way, I am color-blind, so the prospect of customizing colors is very exciting!

Changes to Racial Councils

Ref: http://smrcnn.smrealms.de/viewtopic.php?f=94&t=11675

Following changes to be made:

  1. Council size = 5
  2. Relation change increased from +-10 to +-15
  3. Vote length changed to 48 hours (if possible make vote length based on game speed;which would actually put 1.5x at 54 hours)
  4. Veto time should = vote time - 24 hours

Further clarification, please refer to thread or contact Jouldax.

Is TIME_BEFORE_NEWBIE_TIME too short?

Setting aside the fact that this was probably supposed to be called TIME_BEFORE_NEWBIE_TURN... ;)

This is currently set to 1 hour. If no one accesses the server, we assume the server went down and give everyone (who is not on a planet) a newbie turn. Perhaps this doesn't matter too much, since if no one is playing for one hour, then everyone is likely to be on a planet or in fed anyway; otherwise, if someone is moving and the server goes down for over an hour, then they are given the safety of a newbie turn.

With the reduced game population, I was just wondering if this 1 hour still makes sense.

IRC: Caretaker fails to identify registered nicknames

With the changes from my pull request to switch to irc.theairlock.net, the mibbit link is working again and Caretaker can join the IRC server. However there is a new problem:

Registered nicknames are no longer recognized by Caretaker. If you perform commands (such as !money), Caretaker will respond with

<nick>, you are not using a registered nick. Please identify with NICKSERV and try the last command again.

I believe this is because TheAirlock changed the NickServ software to Anope, or at least to a newer version. The command /whois <nick> no longer returns the string <nick> :is a registered nick if the user is registered. Instead, it returns <nick> :is identified for this nick as the 307 server message, and no 307 message if not.

We could switch to using status instead of whois to parse the registration, which has the following outputs:

0 - no such user online or nickname not registered
1 - user not recognized as nickname's owner
2 - user recognized as owner via access list only
3 - user recognized as owner via password identification

This is probably more robust than parsing textual output, but for simplicity I think we can just modify the server 307 preg_match to match the new string. I will submit a pull request for this.

A related problem is that NickServ is still [email protected] instead of [email protected]. I don't know if this will continue to be true going forward, but we may want to modify the affected preg_match uses in notice.php. I do not have a test case for this, so I will not propose a change here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.