Minecraft-Overviewer/docs/contributing.rst

298 lines
13 KiB
ReStructuredText

============
Contributing
============
In this page, you'll be given some pointers on how to start contributing to the
Minecraft-Overviewer project. This is useful for people who want to help develop
the Overviewer, but don't quite know where to start.
This page is mostly focused on where to look for things and how to get your
changes back into the project, for help on how to compile the Overviewer, check
:doc:`Building <building>`.
Prerequisites
=============
Ideally you're familiar with Python (Overviewer uses Python 3), and know the
basics of Git. Both have various very good resources online that help you in
learning them, but the best way of learning is always to use them in the real
world, so don't hesitate to jump right in after having a basic grasp and ask
questions along the way.
Additionally, some parts of Overviewer are written in C, though unless you're
interested in the drawing and compositing routines or the rendermodes, you don't
need to know C.
Last but not least, some of the Overviewer's code is written in JavaScript,
namely the part that runs in your browser when you view the map.
Acquiring the Source Code
=========================
First, you'll need to get the Overviewer source code. We do version management
of code through Git_, which allows multiple people to work on the code at the
same time. Naturally, this means you'll also be getting the source code through
Git. For this to work, you'll have to install Git on your computer.
.. _Git: https://git-scm.com/
Our source code is hosted on GitHub_, so it's a good idea to make an account
there if you don't already have one.
.. _GitHub: https://github.com/overviewer/Minecraft-Overviewer
This page won't go into the details of how to use Git, but it'll give you some
advice on how your workflow should be to avoid some trouble.
Finding Your Way around the Code Base
=====================================
At first glance, all the code can be a bit overwhelming. So here's a quick
overview of the important parts.
* ``setup.py`` is the build script. If you need to make any changes to how the
Overviewer is built, you'll want to look there.
* ``overviewer.py`` is the entry-point of the application. It imports all the
other functionality, and does the command line parsing.
* ``overviewer_core/`` is the directory where the vast majority of the
Overviewer's functionality is. More on that below.
* ``overviewer_core/aux_files/genPOI.py`` is where the genPOI functionality is
implemented. If you're looking into changing the way markers are generated,
look there.
* ``overviewer_core/src/`` is the directory for all the files that are part of
Overviewer's C extension. This includes things such as rendermodes, which are
stored in the ``primitives`` sub-directory.
* ``overviewer_core/data/`` mostly contains the parts that make up Overviewer's
web front-end, with ``js_src`` containing the JS files and ``web_assets``
containing the ``index.html``, CSS files and image files such as icons or the
compass.
* ``docs/`` contains the documentation, which can be built with the included
Makefile if you have sphinx installed.
overviewer_core
---------------
Let's take a closer look at the ``overviewer_core/`` directory:
* ``assetmanager.py`` controls how the HTML and JS output are written out, as
well as the ``overviewerConfig.js`` format.
* ``cache.py`` implements a Least-Recently-Used (LRU) cache, which is used for
caching chunks in memory as the rendering happens.
* ``config_parser.py`` contains some code that sets up how the config is parsed,
but is not really involved in the definitions of individual settings therein.
* ``dispatcher.py`` is the code that sets up multiprocessing, so Overviewer can
use all available CPU threads on a machine.
* ``files.py`` implements helpful routines which allow you to determine whether
some file operations such as replacing a file work in a given directory, and
also implements the ``FileReplacer`` class which can then safely replace a
file given the capabilities of the filesystem.
* ``items.py`` is a remnant of the past and entirely unused.
* ``logger.py`` sets up and implements Overviewer's logging facilities.
* ``nbt.py`` contains the code that is used to parse the Minecraft NBT file
structure.
* ``observer.py`` defines all the observers that are available. If you want to
add a new observer, this is the place where you'll want to look.
* ``optimizeimages.py`` defines all the optimizeimg tools and how they're
called.
* ``progressbar.py`` implements the fancy progress bar that the Overviewer has.
* ``rcon.py`` implements an rcon client for the Minecraft server, used by the
RConObserver.
* ``rendermodes.py`` contains definitions and glue code for the rendermodes in
the C extension.
* ``settingsDefinitions.py`` includes all definitions for the Overviewer
configuration file. If you want to add a new configuration option, this is
where you'll want to start.
* ``settingsValidators.py`` contains validation code for the settings
definitions, which ensures that the values are all good.
* ``signals.py`` is multiprocessing communication code. Scary stuff.
* ``textures.py`` contains all the block definitions and how Overviewer should
render them. If you want to add a new block to the Overviewer, this is where
you'll want to do it. Additionally, this code also controls how the textures
are loaded.
* ``tileset.py`` contains code that maps a render dict entry to the output tiled
image structure.
* ``util.py`` contains random utility code that has no home anywhere else.
* ``world.py`` is a whole lot of code that does things like choosing which
chunks to load and to cache, and general functionality revolving around the
concept of Minecraft worlds.
docs
----
The documentation is written in reStructuredText_, a markup format. It can be
compiled into an HTML output using the Makefile in the ``docs/`` subtree by
typing ``make``. You'll need to have sphinx_ installed for this to work.
.. _reStructuredText: http://docutils.sourceforge.net/rst.html
.. _sphinx: http://www.sphinx-doc.org/en/stable/
The theme that will be used in the locally generated HTML is different than what
is used on http://docs.overviewer.org. However, it should still be sufficient
to get a good idea of how your changes will end up looking like when they're on
the main docs page.
Code Style
==========
To be honest, currently the Overviewer's codebase is a bit of a mess. There is
no consistent code style in use right now. However, it's probably a good idea
to stick to PEP8_ when writing new code. If you're refactoring old code, it
would be great if you were to fix it to make it PEP8 compliant as well.
To check whether the code is PEP8 compliant, you can use pycodestyle_. You can
easily install it with pip by using ``pip3 install pycodestyle``.
.. _PEP8: https://www.python.org/dev/peps/pep-0008/
.. _pycodestyle: https://pypi.python.org/pypi/pycodestyle
Example Scenarios
=================
This section will demonstrate by example how a few possible contributions might
be made. These serve as guidelines on how to quickly get started if you're
interested in doing a specific task that many others before you have done too
in some other form.
Adding a Block
--------------
Let's assume you want to add support for a new block to the Overviewer. This is
probably one of the most common ways people start contributing to the project,
as all blocks in the Overviewer are currently hardcoded and code to handle them
needs to be added by hand.
The place to look here is ``textures.py``. It contains the block definitions,
which are assisted by Python decorators_, which make it quite a bit simpler to
add new blocks.
The big decorator in question is ``@material``, which takes arguments such as
the ``blockid`` (a list of block IDs this block definition should handle), and
``data`` (a list of possible data values for this block). Additionally, it can
also take various additional arguments for the different block properties, such
as ``solid=True`` to indicate that the block is a solid block.
.. _decorators: https://en.wikipedia.org/wiki/Python_syntax_and_semantics#Decorators
Simple Solid 6-Sided Block
~~~~~~~~~~~~~~~~~~~~~~~~~~
A lot of times, new blocks are basically just your standard full-height block
with a new texture. For a block this simple, we don't even really need to use
the material decorator. As an example, check out the definition of the coal
block::
block(blockid=173, top_image="assets/minecraft/textures/blocks/coal_block.png")
Block with a Different Top
~~~~~~~~~~~~~~~~~~~~~~~~~~
Another common theme is a block where the top is a different texture than the
sides. Here we use the ``@material`` decorator to create the jukebox block::
@material(blockid=84, data=range(16), solid=True)
def jukebox(self, blockid, data):
return self.build_block(self.load_image_texture("assets/minecraft/textures/blocks/jukebox_top.png"), self.load_image_texture("assets/minecraft/textures/blocks/noteblock.png"))
As you can see, we define a method called ``jukebox``, taking the parameters
``blockid`` and ``data``, decorated by a decorator stating that the following
definition is a material with a ``blockid`` of ``84`` and a data value range
from ``0`` to ``15`` (or ``range(16)``), which we won't use as it doesn't affect
the rendering of the block. We also specify that the block is solid.
Inside the method, we then return the return value of ``self.build_block()``,
which is a helper method that takes a texture for the top and a texture for the
side as its arguments.
Block with Variable Colors
~~~~~~~~~~~~~~~~~~~~~~~~~~
Occasionally, blocks can have colors stored in their data values.
``textures.py`` includes an easy mapping list, called ``color_map``, to map
between data values and Minecraft color names. Let's take stained hardened clay
as an example of how this is used::
@material(blockid=159, data=range(16), solid=True)
def stained_clay(self, blockid, data):
texture = self.load_image_texture("assets/minecraft/textures/blocks/hardened_clay_stained_%s.png" % color_map[data])
return self.build_block(texture,texture)
As you can see, we specify that the block has 16 data values, then depending
on the data value we load the right block texture by looking up the color name
in the ``color_map`` list, formatting a string for the filename with it.
Good Git Practices
==================
How you structure your Git workflow is ultimately up to you, but here are a few
recommendations to make your life and the life of the people who want to merge
your pull requests easier.
* **Commit your changes in a separate branch, and then submit a pull request
from that branch.** This makes it easier for you to rebase your changes, and
allows you to keep your repository's master branch in-sync with our master
branch, so you can easily split off a new branch from master if you want to
develop a new change while your old change still isn't merged into the master.
* **Format your commit messages properly.** The first line should be a 50
character long summary of the change the commit makes, in present tense, e.g.
"Add a spinner to the progress bar". This should be followed by a blank line,
and a longer explanation of the change the commit actually does, wrapped at
72 characters.
* **Don't merge master into your branch.** If you plan on submitting a change as
a pull request and the master branch has moved in the meantime, then don't
merge the master branch into the branch of your pull request. Instead, rebase
your branch on top of the updated master.
* **Keep commits logically separated.** Don't try to cram unrelated changes into
just one commit unless it's a commit full of small fixes. If you find yourself
struggling to keep the commit summary below 50 characters, and find yourself
using the word "and" in it, rethink whether the changes you're making should
be just one commit.
It's also a good idea to look at the output of ``git diff`` before committing a
change, to make sure nothing was unintentionally changed in the file where you
weren't expecting it. ``git diff`` will also highlight blank lines with spaces
in them with a solid red background.
Talking with other Developers
=============================
Occasionally, the issue tracker simply doesn't cut it. You need to talk with
another developer, maybe to brainstorm a new feature or ask a question about
the code. For this, we have `an IRC channel on Libera.Chat`_, which allows you to
talk with other developers that are on the IRC channel in real-time.
.. _an IRC channel on Libera.Chat: https://overviewer.org/irc/
Since most developers have jobs or are in college or university, it may
sometimes take a few moments to get a reply. So it's useful to stick around and
wait for someone who can help you to be around.