Bravo Documentation¶
Bravo is an elegant, speedy, and extensible implementation of the Minecraft Alpha/Beta protocol. Only the server side is implemented. The following introductory topics provide a better look at the project, its goals, and current capabilities.
A high-level introduction¶
Bravo is an open source, reverse-engineered implementation of Minecraft’s server application. Two of the major building blocks are Python and Twisted, but you need not be familiar with either to run, administer, and play on a Bravo-based server.
Similar and different¶
While one of the goals of Bravo is to be roughly on par with the standard, “Notchian” Minecraft server, Bravo does change and improve things for the better, where appropriate. See Differences vs. vanilla Minecraft Server for more details.
Some of the more positive hilights include:
- More responsiveness with higher populations.
- Much less memory and bandwidth consumption.
- Better inventory system that avoids some bugs found in the standard server.
Current state¶
Bravo is currently in heavy development. While it is probably safe to run creative games, we lack some elements needed for Survival-Multiplayer. Take a look at Features to get an idea of where we currently stand.
We encourage the curious to investigate for themselves, and post any bugs, questions, or ideas you may have to our issue tracker.
Project licensing¶
Bravo is MIT/X11-licensed. A copy of the license is included in the
LICENSE
file in the repository or distribution. This extremely
permissive license gives you all of the flexibility you could ever want.
Q & A¶
Why are you doing this? What’s wrong with the official Alpha/Beta server?
Plenty. The biggest architectural mistake is the choice of dozens of threads instead of NIO and an asynchronous event-driven model, but there are other problems as well. Additionally, the offical server development team has recently moved to remove all other servers as options for people wishing to deploy servers. We don’t approve of that.
Are you implying that the official Alpha server is bad?
Yes. As previous versions of this FAQ have stated, Notch is a cool guy, but the official server is bad.
Are you going to make an open-source client? That would be awesome!
The server is free, but the client is not. Accordingly, we are not pursuing an open-source client at this time. If you want to play Alpha, you should pay for it. There’s already enough Minecraft piracy going on; we don’t feel like being part of the problem. That said, Bravo’s packet parser and networking tools could be used in a client; the license permits it, after all.
Where did the docs go?
We contribute to the Minecraft Collective’s wiki at http://mc.kev009.com/wiki/ now, since it allows us to share data faster. All general Minecraft data goes to that wiki. Bravo-specific docs are shipped in ReST form, and a processed Sphinx version is available online at http://bravo.readthedocs.org/.
Why did you make design decision <X>?
There’s an entire page dedicated to this in the documentation. Look at docs/philosophy.rst or Philosophy.
It doesn’t install? Okay, maybe it installed, but I’m having issues!
On Freenode IRC (irc.freenode.net), #bravo is dedicated to Bravo development and assistance, and #mcdevs is a more general channel for all custom Minecraft development. You can generally get help from those channels. If you think you have found a bug, you can directly report it on the Github issue tracker as well.
Please, please, please read the installation instructions in the README first, as well as the comments in bravo.ini.example. I did not type them out so that they could be ignored. :3
Credits¶
Who are you guys, anyway?
Corbin Simpson (MostAwesomeDude/simpson) is the main coder. Derrick Dymock (Ac-town) is the visionary and provider of network traffic dumps. Ben Kero and Mark Harris are the reluctant testers and bug-reporters. The Minecraft Coalition has been an invaluable forum for discussion.
Features¶
Bravo’s extensible design means that there are many different plugins and features. Since most servers do not have an extensive or exhaustive list of the various plugins that they include, one is provided here for Bravo.
Standard features¶
These features are found in official, Mojang-sponsored, unmodified servers.
Console¶
Bravo provides a small, plain console suitable for piping input and output, as well as interactive sessions.
Login¶
Bravo supports the two login methods supported by the Mojang-sponsored client: offline authentication and online authentication.
Geometry¶
Bravo understands how to manipulate and transfer geometry. In addition, Bravo can read and write the Alpha NBT and Beta MCR disk formats.
Time¶
Bravo fully implements the in-game day and night. Bravo’s days are exactly 20 minutes long.
Entities¶
Bravo understands the concept of entities, and is able to track the following kinds of entities:
- Mobs
- Paintings
- Pickups
- Players
- Tiles
Mobs¶
Bravo understands the following mobs:
- Chickens/ducks (“Chucks”)
- Cows
- Creepers
- Ghasts
- Giant zombies
- Pigs
- Sheep
- Skeletons
- Slimes
- Spiders
- Squids
- Wolves
- Zombie pigmen
- Zombies
Inventory¶
Bravo provides server-side inventory handling.
Physics¶
Bravo simulates physics, including the behaviors of sand, gravel, water and lava, and redstone.
Extended features¶
Bravo provides many things not in other servers. While a strict comparison of other open-source servers is impossible due to the speedy rate at which they are changing, the features that separate Bravo from the Mojang-sponsored server are listed here.
Console¶
Bravo ships with a fancy console which supports readline-like editing features.
Time¶
Bravo implements an in-game year of 360 in-game days.
Differences vs. vanilla Minecraft Server¶
Bravo was written from the ground up and doesn’t inherit code from any other Minecraft project. This means that it sometimes behaves very differently, in subtle and obvious ways, from other servers.
The “Notchian” server is the server authored by Notch and distributed by Mojang as a companion to the Mojang-sponsored client.
Responsiveness¶
Bravo is occasionally perceived to be “lighter” or “snappier” compared to the Notchian server. Reports of feeling like players are moving faster than normal are also common. The root cause is simple: Bravo is quicker to respond to clients than the Notchian server. This is normal, expected, and not currently planned to be fixed.
Chunks¶
The Notchian server maintains a floating pattern above players, centered on the chunk the player is standing in. This pattern is always a square of chunks, 21 chunks to a side. This results in a total of 441 chunks being deployed to the client at any one time. All 441 chunks are deployed before the client is permitted to interact with the world.
Bravo does something slightly different; while Bravo also has a floating pattern above each of its players, the pattern is a circle with the same diameter as the Notchian server’s square. This effectively results in a circle of 315 chunks deployed to the client; a savings of nearly 30% in memory and bandwidth for chunks. Additionally, only the 50 closest chunks are deployed before the client is spawned and permitted to interact with the world.
Inventory¶
The Notchian viewpoint of items in the inventory is as a list of slots. Each slot holds an item, identified by a single number, and can hold 1 to 64 instances of that item. Some items can be damaged. Some items are completely different depending on their damage.
Bravo views item identifiers as a composite key of a primary and secondary identifier. In this scheme, items with identical primary keys and different secondary keys are properly segregated, and item damage is stored as the secondary key, keeping items with differing amounts of damage from occupying the same slot. This avoids an entire class of bugs, where items can be stacked and unstacked to change the amount of damage on them, which have historically plagued the Notchian codebase.
Minecarts¶
Bravo permits minecart tracks to be placed on glass.
Philosophy¶
Design Decisions¶
A design decision is a core component of building a large piece of software. Roughly stated, it is a choice to use a certain language, library, or methodology when constructing software. Design decisions can be metaphysical, and affect other design decisions. This is merely a way of talking formally and reasonably about choices made in producing Bravo.
This section is largely dedicated to members of the community that have decided that things in Bravo are done incorrectly. While we agree with the need of the community to constructively criticize itself, some things are not worth debating again.
Python¶
Python is occasionally seen as slow compared to statically typed languages. Some benchmarks certainly are very unflattering to Python, but we feel that there are several advantages to Python which are too important to sacrifice:
- Rapid prototyping
- Algorithmic simplicity
- Simple types
- Twisted
Additionally, with the advent of PyPy, the question of whether a full-fledged Python application is too slow for consumer hardware is rapidly fading.
Compared to Other Languages¶
C++¶
Mineserver was a cool attempt to write a custom server in C++. It still receives occasional updates, but never attempted the more ambitious features.
Haskell¶
The Bravo team attempted to port Bravo to Haskell. It was unsuccessful. Haskell does not yet have a mature library for creating massively event-driven network servers.
No Extension Modules¶
There are several good reasons to not ship “extension modules,” pieces of code written in Fortran, C, or C++ which are compiled and dynamically linked against the CPython extension API. Some of them are:
- Portability
- Python and C have different scopes of portability, and the scope of the C API for Python is limited practically to CPython. Each module we depend on externally has the potential to reduce the number of platforms we can support.
- Maintainability
- C is not maintainable on the same scale as Python, even with (and, some would argue, especially with) the extremely structured syntax required to interface with the C API for Python. Cython is maintainable, but does not solve the other problems.
- Dependencies
- Somebody has to provide binary versions of the modules for all the people without compilers. Practically, this does mean that Win32 users need to have binaries provided for them, as long as our thin veneer of Win32 compatibility holds up.
- Forward-compatibility
- Frankly, extension modules are forever incompatible with the spirit of PyPy, and require, at bare minimum, a recompile and prayer before they’ll cooperate. We support running Bravo on PyPy, and on this alone, we wish to not depend on them.
Frankly, most extension modules aren’t worth this trouble. Extension modules which are well-tested, ubiquitous, and actively maintained, are generally going to be favored more than extensions which break, are hard to obtain or compile, or are derelict.
Twisted¶
Apparently, in this day and age, people are still of the opinion that Twisted is too big and not necessary for speedy, relatively bug-free networking. Nothing written here will convince these people; so, instead, I offer this promise: If anybody contributes a patch which makes Bravo not depend on Twisted, does not degrade its performance measureably, and does not break any part of Bravo, then I will acknowledge and apply it.
No Threads¶
Threads are evil. They are not an effective concurrency model in most cases. Tests done with offloading various parts of Bravo’s CPU-bound tasks to threads have shown that threads are a liability in most cases, enforcing locking overhead while providing little to no actual benefit in terms of speed and latency.
However, as a concession to the CPU-centric nature of geometry generation, Bravo will offload all geometry generation to separate processes when Ampoule is available and enabled in its configuration file, which does yield massive improvements to server interactivity.
Extreme Extensibility¶
Bravo is remarkably extensible. Pieces of functionality that are considered essential or “core” are treated as plugins and dynamically loaded on server startup. Actual services are dynamically started and stopped as needed. Bravo’s core does not even provide Minecraft services by default.
The reason for this extreme plugin approach is that Bravo was designed to be easily totally convertible; in theory, a proper set of configuration files and external plugins can completely change Bravo’s behavior.
Versioning¶
Bravo’s version numbers are not very complex. Here’s a quick breakdown.
Major version numbers indicate the core structure of Bravo. A major version bump probably means that lots of modules changed names, or that something significant was added. In practice, this probably means that an entirely new set of protocols was added. (The next major version bump will probably be for InfiniCraft support.)
Minor version numbers are for changes to interfaces or any other change which means that external code relying on Bravo’s API will have to be updated.
Patchlevel version numbers aren’t currently used, but probably will signify that the release is a bugfix-only release with no significant change in functionality.
The hope of all of this is that, given a series of releases with the same major and minor, plugins do not have to be changed.
Administrator Topics¶
The following topics are meant for those wishing to run a Bravo server. Topics such as installation, configuration, and troubleshooting are covered here. No software development background is necessary.
How to administer Bravo¶
While Bravo is not a massively complex piece of software on its own, the plugins and features that are available in Bravo can be overwhelming and daunting. This page is a short but comprehensive overview for new administrators looking to set up and run Bravo instances.
Configuration¶
Bravo uses a single configuration file, bravo.ini, for all of its settings.
The file is in standard INI format. Note that this is not the extended INI
format of Windows 32-bit configuration settings, nor the format of PHP’s
configuration files. Specifically, bravo.ini is parsed and written using
Python’s ConfigParser
class.
An example configuration file is provided as bravo.ini.example
,
and is a good starting point for new configurations.
bravo.ini
should live in one of three locations:
- /etc/bravo
- ~/.bravo
- The working directory
All three locations will be checked, in that order, and more-recently-loaded
configurations will override configurations in previous directories. For
sanity purposes, it is highly encouraged to either use /etc/bravo
if running as root, or ~/.bravo
if running as a normal user.
The configuration file is divided up into sections. Each section starts
with a name, like [section name]
, and only ends when another section
starts, or at the end of the file.
A note on lists¶
Bravo uses long lists of named plugins, and has special facilities for handling them.
If an option takes a list of choices, then the choices should be comma-separated. They may be on the same line, or multiple lines; spaces do not matter much. (As an aside, spaces matter inside plugin names, but Bravo’s plugin collection uses only underscores, not spaces, so this should not matter. If it does, bug your plugin authors to fix their code.)
Additionally, to simplify plugin naming, many plugin configuration options support wildcards. Currently, the “*” wildcard is supported. A “*” anywhere in an option list will be internally expanded to all of the available choices for that option.
The special notation “-” before a name will forcibly remove that name from a list.
Putting everything together, an example set of configurations might look like this:
some_option = first, second, third
some_newline_option = first, second,
third, fourth
some_wildcard_option = *
some_picky_option = *, -fifth
another_picky_option = -fifth, -sixth, *
a_weird_but_valid_option = seventh, -seventh
General settings¶
These settings apply to all of Bravo. This section is named [bravo]
.
- fancy_console
- Whether to enable the fancy console in standalone mode. This setting will be overridden if the fancy console cannot be set up; e.g. on Win32 systems.
- ampoule
- Whether asynchronous chunk generators will be used. This can result in massive improvements to Bravo’s latency and responsiveness, and defaults to enabled. This setting will be overridden if Ampoule cannot be found.
World settings¶
These settings only apply to a specific world. Worlds are created by starting
the section of the configuration with “world”; an example world section might
start with [world example]
.
- port
- Which port to run on. Must be a number between 0 and 65535. Note that ports below 1024 are typically privileged and cannot be bound by non-root users.
- host
- The hostname to bind to. Defaults to no hostname, which is usually correct for most people. If you don’t know what this is, you don’t need it.
- url
- The path to the folder to use for loading and saving world data. Must be a valid URL.
- serializer
- Which serializer to use for saving worlds. Currently, the “anvil” serializers is provided for compatibility with modern MC clients and servers.
- seed
- A numeric seed to use for terrain generation. If omitted, the seed will be generated when the world is created. This option only affects new worlds; existing worlds already have a seed.
Plugin Data Files¶
Plugins have a standardized per-world storage. Only a few of the plugins that ship with Bravo use this storage. Each plugin has complete autonomy over its data files, but the file name varies depending on the serializer used to store the world. For example, when using the Alpha and Beta world serializers, the file name is <plugin>.dat, where <plugin> is the name of the plugin.
Bravo worlds have per-world IP ban lists. The IP ban lists are stored under the plugin name “banned_ips”, with one IP address per line.
Warps and homes are stored in hey0 CSV format, in “warps” and “homes”.
Plugins¶
Bravo is highly configurable and extensible. The plugins shipped with Bravo are listed here, for convenience.
Packs¶
Beta¶
The Beta plugin pack, called “beta”, provides all of Bravo’s Beta compatibility in one single line of configuration.
Terrain generators¶
The following terrain generators may be added to the generators
setting
in your bravo.ini
under the [world]
section. The order in which
these appear in the list is not important.
Beaches¶
Generates simple beaches.
Beaches are areas of sand around bodies of water. This generator will form beaches near all bodies of water regardless of size or composition; it will form beaches at large seashores and frozen lakes. It will even place beaches on one-block puddles.
Boring¶
Generates boring slabs of flat stone.
Grass¶
Grows grass on exposed dirt.
Caves¶
Carves caves and seams out of terrain.
Cliffs¶
Generates sheer cliffs.
Complex¶
Generates islands of stone and other ridiculous things.
Erosion¶
Erodes stone surfaces into dirt.
Float¶
Rips chunks out of the map, to create surreal chunks of floating land.
Safety¶
Generates terrain features essential for the safety of clients, such as the indestructible bedrock at Y = 0.
Warning
Removing this generator will permit players to dig through the bottom of the world.
Simplex¶
Generates organic-looking, continuously smooth terrain.
Saplings¶
Plants saplings at relatively silly places around the map.
Note
This generator only places saplings, and is not responsible for the
growth of trees over time. The trees
automaton should be used for
ensuring that trees will grow.
Ore¶
Places ores and clay.
Watertable¶
Creates a flat water table half-way up the map (Y = 64).
Automatons¶
Automatons are simple tasks which examine and update the world as the world loads and displays data to players. They are able to do periodic or delayed work to keep the world properly. (The mental image of small robotic gardeners roving across the hills and valleys trimming grass and dusting trees is quite compelling and adorable!)
Automatons marked with (Beta) provide Beta compatibility and should probably be enabled.
- lava: Enable physics for placed lava springs. (Beta)
- trees: Turn planted saplings into trees. (Beta)
- water: Enable physics for placed water springs. (Beta)
Seasons¶
Bravo’s years are 360 days long, with each day being 20 minutes long. For
those who would like seasons, the following seasons be added to the
seasons
setting in your bravo.ini
under the [world]
section.
Winter¶
Causes water to freeze, and snow to be placed on certain block types. Winter starts on the first day of the year.
Spring¶
Thaws frozen water and removes snow as that was placed during Winter. Spring starts on the 90th day of the the year.
Hooks¶
Hooks are small pluggable pieces of code used to add event-driven functionality to Bravo.
Build hooks¶
Hooks marked with (Beta) provide Beta compatibility and should probably be enabled.
- alpha_sand_gravel: Make sand and gravel fall as if affected by gravity. (Beta)
- bravo_snow: Make snow fall as if affected by gravity.
- build: Enable placement of blocks from inventory onto the terrain. (Beta)
- redstone: Enable physics for placed redstone. (Beta)
- tile: Register tiles. Required for signs, furnaces, chests, etc. (Beta)
- tracks: Align minecart tracks. (Beta)
Dig hooks¶
- alpha_sand_gravel: Make sand and gravel fall as if affected by gravity. (Beta)
- alpha_snow: Destroy snow when it is dug or otherwise disturbed. (Beta)
- bravo_snow: Make snow fall as if affected by gravity.
- give: Spawn pickups for blocks and items destroyed by digging. (Beta)
- lava: Enable physics for lava. (Beta)
- redstone: Enable physics for redstone. (Beta)
- torch: Destroy torches that are not attached to walls or floors. (Beta)
- tracks: Align minecart tracks. (Beta)
- water: Enable physics for water. (Beta)
Troubleshooting¶
Configuring¶
When I connect to the server, the client gets an “End of Stream” error and the server log says something about “ConsoleRPCProtocol”.
You are connecting to the wrong port.
Bravo always runs an RPC console by default. This console isn’t directly accessible from clients. In order to connect a client, you must configure a world and connect to that world. See the example bravo.ini configuration file for an example of how to configure a world.
My world is snowy. I didn’t want this.
In bravo.ini, change your
seasons
list to exclude winter. A possible incantation might be the following:seasons = *, -winter
Errors¶
I get lots of RuntimeErrors from Exocet.
Upgrade to a newer Bravo which doesn’t use Exocet.
I have an error involving construct!
Install Construct. It is a required package.
I have an error involving JSON!
If you update to a newer Bravo, you won’t need JSON support.
I have an error involving IRC/AMP/ListOf!
Your Twisted is too old. You really do need Twisted 11.0 or newer.
I have an error ``TypeError: an integer is required`` when starting Bravo!
Your Twisted is too old. You really do need Twisted 11.0 or newer.
I am running as root on a Unix system and twistd cannot find ``bravo.service``. What’s going on?
For security reasons, twistd doesn’t look in non-system directories as root. If you insist on running as root, try an incantation like the following, setting
PYTHONPATH
:# PYTHONPATH=. twistd -n bravo
But seriously, stop running as root.
Help!¶
If you are having a hard time figuring something out, encountered a bug, or have ideas, feel free to reach out to the community in one of several different ways:
- IRC: #Bravo on FreeNode
- Post to our issue tracker.
- Speak up over our mailing list.
Web Service¶
Bravo comes with a simple web service which can be used to monitor the status of your server.
Configuration¶
Only one web service can be defined; it uses the configuration key [web]
and has only one parameter, port
, specifying the port on which to listen.
An example configuration snippet might look like this:
[web]
port = 8080
Developer Topics¶
The following topics are of general use to those wishing to modify or understand the Bravo source code. These topics are completely unecessary for those who are only interested in running or administering a Bravo server.
Extending Bravo¶
Bravo is designed to be highly extensible. This document is a short guide to the basics of writing extension code for Bravo.
Asynchronous Ideas¶
Bravo, being built on Twisted, has inherited most of the concepts of asynchronous control flow from Twisted, and uses them liberally. Nearly every plugin method is permitted to return a Deferred in place of their actual return value.
The Good, the Bad, and the Ugly¶
There are a lot of modules in the standard library. Some of them should not be used in Bravo.
The following modules are blacklisted because they conflict with, or are slow compared to, Twisted’s own systems:
These modules are bad. All of them duplicate functionality available in Twisted, and do it in ways that can interfere with Twisted’s ability to do things in a speedy manner. Do not use them under any circumstances.
asyncore
multiprocessing
socket
subprocess
thread
threading
These modules are ugly. They can quite easily corrupt memory or cause server crashes, and should be used with extreme caution and very good reasons. If you don’t know exactly what you are doing, don’t use these.
ctypes
gc
imp
inspect
Parameters¶
Hooks should accept a single named parameter, factory
, which will be
provided when the hook is loaded.
The Flexibility of Commands¶
Bravo’s command interface is designed to feel like a regular class instead of a specialized plugin, while still providing lots of flexibility to authors. Let’s look at a simple plugin:
class Hello(object):
"""
Say hello to the world.
"""
implements(IChatCommand)
def chat_command(self, username, parameters):
greeting = "Hello, %s!" % username
yield greeting
name = "hello"
aliases = tuple()
usage = ""
This command is a simple greeter which merely echoes a salutation to its
caller. It is an IChatCommand
, so it only works in the in-game chat, but
that should not be a problem, since there is an internal, invisible adaptation
from IChatCommand
to IConsoleCommand
. This means that chat commands
are also valid console commands, without any action on your part! Pretty cool,
huh?
So, how does this plugin actually work? Well, nearly every line of this plugin
is required. The first thing you’ll notice is that this plugin has a class
docstring. Docstrings on commands are required; the docstring is used to
provide help text. As with all chat commands, this plugin
implements(IChatCommand)
, which lets it be discovered as a command.
The plugin implements the required chat_command(username, parameters)
,
which will be called when a player uses the command. An interesting thing to
note is that this plugin yields its return value; commands may return any
iterable of lines, including a generator!
Finally, the plugin finishes with more required interface attributes: a name which will be used to call the command, a (possibly empty) list of aliases which can also be used to call the command, and a (possibly empty) usage string.
Noise¶
Bravo, like all Minecraft terrain generators, relies heavily on randomness to generate its terrain. In order to understand some of the design decisions in the terrain generator, it is required to understand noise and its various properties.
Probability¶
Noise’s probability distribution is not even, equal, or normal. It is symmetric about 0, meaning that the absolute value of noise has all of the same relative probabilities as the entire range of noise.
When binned into a histogram with 100 bins, a few bins become very large.
Bin | Probability |
0.00 | 2.6150% |
0.49 | 2.2262% |
0.59 | 1.8274% |
0.43 | 1.8248% |
0.42 | 1.7888% |
0.58 | 1.5939% |
0.48 | 1.5194% |
0.41 | 1.5118% |
0.18 | 1.4715% |
0.24 | 1.4366% |
0.54 | 1.4072% |
0.22 | 1.3825% |
0.50 | 1.3786% |
0.44 | 1.3696% |
0.26 | 1.3680% |
Core¶
These modules comprise the core functionality of Bravo.
beta
– Minecraft Beta¶
Protocols and factories for Minecraft Beta, the Mojang-authored Minecraft which everybody knows and loves.
Packets¶
Protocols¶
Factories¶
blocks
– Block descriptions¶
The blocks
module contains descriptions of blocks.
-
class
bravo.blocks.
Block
(slot, name, secondary=0, drop=None, replace=0, ratio=1, quantity=1, dim=16, breakable=True, orientation=None, vanishes=False)[source]¶ Bases:
object
A model for a block.
There are lots of rules and properties specific to different types of blocks. This class encapsulates those properties in a singleton-style interface, allowing many blocks to be referenced in one location.
The basic idea of this class is to provide some centralized data and information about blocks, in order to abstract away as many special cases as possible. In general, if several blocks all have some special behavior, then it may be worthwhile to store data describing that behavior on this class rather than special-casing it in multiple places.
Parameters: - slot (int) – The index of this block. Must be globally unique.
- name (str) – A common name for this block.
- secondary (int) – The metadata/damage/secondary attribute for this block. Defaults to zero.
- drop (tuple) – The type of block that should be dropped when an instance of this block is destroyed. Defaults to the block value, to drop instances of this same type of block. To indicate that this block does not drop anything, set to air (0, 0).
- replace (int) – The type of block to place in the map when instances of this block are destroyed. Defaults to air.
- ratio (float) – The probability of this block dropping a block on destruction.
- quantity (int) – The number of blocks dropped when this block is destroyed.
- dim (int) – How much light dims when passing through this kind of block. Defaults to 16 = opaque block.
- breakable (bool) – Whether this block is diggable, breakable, bombable, explodeable, etc. Only a few blocks actually genuinely cannot be broken, so the default is True.
- orientation (tuple) – The orientation data for a block. See
orientable()
for an explanation. The data should be in standard face order. - vanishes (bool) – Whether this block vanishes, or is replaced by, another block when built upon.
-
face
(metadata)[source]¶ Retrieve the face for given metadata corresponding to an orientation, or None if the metadata is invalid for this block.
This method only returns valid data for orientable blocks; check
orientable()
first.
-
orientable
()[source]¶ Whether this block can be oriented.
Orientable blocks are positioned according to the face on which they are built. They may not be buildable on all faces. Blocks are only orientable if their metadata can be used to directly and uniquely determine the face against which they were built.
Ladders are orientable, signposts are not.
Return type: bool Returns: True if this block can be oriented, False if not.
-
orientation
(face)[source]¶ Retrieve the metadata for a certain orientation, or None if this block cannot be built against the given face.
This method only returns valid data for orientable blocks; check
orientable()
first.
-
bravo.blocks.
armor_boots
= (301, 305, 309, 313, 317)¶ List of slots of boots.
-
bravo.blocks.
armor_chestplates
= (299, 303, 307, 311, 315)¶ List of slots of chestplates.
Note that slot 303 (chainmail chestplate) is a chestplate, even though it is not normally obtainable.
-
bravo.blocks.
armor_helmets
= (86, 298, 302, 306, 310, 314)¶ List of slots of helmets.
Note that slot 86 (pumpkin) is a helmet.
-
bravo.blocks.
armor_leggings
= (300, 304, 308, 312, 316)¶ List of slots of leggings.
-
bravo.blocks.
blocks
= {0: Block((0, 0) 'air': unbreakable, transparent), 1: Block((1, 0) 'stone': drops 1 (key (4, 0), rate 100.00%)), 2: Block((2, 0) 'grass': drops 1 (key (3, 0), rate 100.00%)), 3: Block((3, 0) 'dirt'), 4: Block((4, 0) 'cobblestone'), 5: Block((5, 0) 'wood'), 'wooden-door-block': Block((64, 0) 'wooden-door-block': drops 1 (key (324, 0), rate 100.00%)), 7: Block((7, 0) 'bedrock': unbreakable), 8: Block((8, 0) 'water': unbreakable, translucent (3)), 9: Block((9, 0) 'spring': unbreakable, translucent (3)), 10: Block((10, 0) 'lava': unbreakable, transparent), 11: Block((11, 0) 'lava-spring': unbreakable, transparent), 12: Block((12, 0) 'sand'), 13: Block((13, 0) 'gravel': drops 1 (key (318, 0), rate 10.00%)), 14: Block((14, 0) 'gold-ore'), 15: Block((15, 0) 'iron-ore'), 16: Block((16, 0) 'coal-ore': drops 1 (key (263, 0), rate 100.00%)), 17: Block((17, 3) 'jungle-log': drops 1 (key (17, 0), rate 100.00%)), 18: Block((18, 3) 'jungle-leaf': translucent (1), drops 1 (key (6, 0), rate 100.00%)), 19: Block((19, 0) 'sponge'), 20: Block((20, 0) 'glass': transparent, drops 1 (key (0, 0), rate 100.00%)), 21: Block((21, 0) 'lapis-lazuli-ore': drops 6 (key (351, 4), rate 100.00%)), 22: Block((22, 0) 'lapis-lazuli-block'), 23: Block((23, 0) 'dispenser'), 24: Block((24, 0) 'sandstone'), 25: Block((25, 0) 'note-block'), 26: Block((26, 0) 'bed-block': drops 1 (key (355, 0), rate 100.00%)), 'redstone-ore': Block((73, 0) 'redstone-ore': drops 5 (key (331, 0), rate 100.00%)), 28: Block((28, 0) 'detector-rail'), 29: Block((29, 0) 'sticky-piston'), 30: Block((30, 0) 'spider-web'), 31: Block((31, 0) 'tall-grass'), 32: Block((32, 0) 'shrub'), 33: Block((33, 0) 'piston'), 35: Block((35, 15) 'black-wool': drops 1 (key (35, 0), rate 100.00%)), 6: Block((6, 3) 'jungle-sapling': transparent, drops 1 (key (6, 0), rate 100.00%)), 38: Block((38, 0) 'rose': transparent), 39: Block((39, 0) 'brown-mushroom': transparent), 40: Block((40, 0) 'red-mushroom': transparent), 'rose': Block((38, 0) 'rose': transparent), 42: Block((42, 0) 'iron'), 43: Block((43, 0) 'double-step'), 44: Block((44, 3) 'cobblestone-step': transparent, drops 1 (key (44, 0), rate 100.00%)), 45: Block((45, 0) 'brick'), 46: Block((46, 0) 'tnt'), 47: Block((47, 0) 'bookshelf'), 48: Block((48, 0) 'mossy-cobblestone'), 49: Block((49, 0) 'obsidian'), 50: Block((50, 0) 'torch': transparent), 'wood': Block((5, 0) 'wood'), 52: Block((52, 0) 'mob-spawner': transparent, drops 1 (key (0, 0), rate 100.00%)), 53: Block((53, 0) 'wooden-stairs': transparent), 54: Block((54, 0) 'chest'), 55: Block((55, 0) 'redstone-wire': transparent), 56: Block((56, 0) 'diamond-ore': drops 1 (key (264, 0), rate 100.00%)), 57: Block((57, 0) 'diamond-block'), 58: Block((58, 0) 'workbench'), 'gravel': Block((13, 0) 'gravel': drops 1 (key (318, 0), rate 10.00%)), 'spider-web': Block((30, 0) 'spider-web'), 61: Block((61, 0) 'furnace'), 62: Block((62, 0) 'burning-furnace': drops 1 (key (61, 0), rate 100.00%)), 63: Block((63, 0) 'signpost': transparent, drops 1 (key (323, 0), rate 100.00%)), 64: Block((64, 0) 'wooden-door-block': drops 1 (key (324, 0), rate 100.00%)), 65: Block((65, 0) 'ladder': transparent), 66: Block((66, 0) 'tracks': transparent), 'sapling': Block((6, 0) 'sapling': transparent), 68: Block((68, 0) 'wall-sign': transparent, drops 1 (key (323, 0), rate 100.00%)), 69: Block((69, 0) 'lever': transparent), 70: Block((70, 0) 'stone-plate': transparent), 71: Block((71, 0) 'iron-door-block': drops 1 (key (330, 0), rate 100.00%)), 72: Block((72, 0) 'wooden-plate': transparent), 73: Block((73, 0) 'redstone-ore': drops 5 (key (331, 0), rate 100.00%)), 74: Block((74, 0) 'glowing-redstone-ore': drops 5 (key (331, 0), rate 100.00%)), 75: Block((75, 0) 'redstone-torch-off': transparent), 76: Block((76, 0) 'redstone-torch': transparent), 77: Block((77, 0) 'stone-button': transparent), 78: Block((78, 0) 'snow'), 79: Block((79, 0) 'ice': translucent (3), becomes 9, drops 1 (key (0, 0), rate 100.00%)), 80: Block((80, 0) 'snow-block'), 81: Block((81, 0) 'cactus': transparent), 82: Block((82, 0) 'clay': drops 4 (key (337, 0), rate 100.00%)), 83: Block((83, 0) 'reed': transparent, drops 1 (key (338, 0), rate 100.00%)), 84: Block((84, 0) 'jukebox'), 'iron-ore': Block((15, 0) 'iron-ore'), 86: Block((86, 0) 'pumpkin'), 87: Block((87, 0) 'brimstone'), 88: Block((88, 0) 'slow-sand'), 89: Block((89, 0) 'lightstone': drops 1 (key (348, 0), rate 100.00%)), 90: Block((90, 0) 'portal': transparent), 91: Block((91, 0) 'jack-o-lantern'), 92: Block((92, 0) 'cake-block': transparent), 93: Block((93, 0) 'redstone-repeater-off': transparent, drops 1 (key (356, 0), rate 100.00%)), 94: Block((94, 0) 'redstone-repeater-on': transparent, drops 1 (key (356, 0), rate 100.00%)), 95: Block((95, 0) 'locked-chest'), 96: Block((96, 0) 'trapdoor'), 97: Block((97, 0) 'hidden-silverfish': drops 1 (key (0, 0), rate 100.00%)), 98: Block((98, 0) 'stone-brick'), 99: Block((99, 0) 'huge-brown-mushroom': drops 2 (key (39, 0), rate 100.00%)), 100: Block((100, 0) 'huge-red-mushroom': drops 2 (key (40, 0), rate 100.00%)), 101: Block((101, 0) 'iron-bars'), 102: Block((102, 0) 'glass-pane'), 103: Block((103, 0) 'melon'), 104: Block((104, 0) 'pumpkin-stem': drops 3 (key (361, 0), rate 100.00%)), 105: Block((105, 0) 'melon-stem': drops 3 (key (362, 0), rate 100.00%)), 106: Block((106, 0) 'vine'), 107: Block((107, 0) 'fence-gate'), 'diamond-ore': Block((56, 0) 'diamond-ore': drops 1 (key (264, 0), rate 100.00%)), 'glowing-redstone-ore': Block((74, 0) 'glowing-redstone-ore': drops 5 (key (331, 0), rate 100.00%)), 'tall-grass': Block((31, 0) 'tall-grass'), 111: Block((111, 0) 'lily-pad': drops 1 (key (0, 0), rate 100.00%)), 112: Block((112, 0) 'nether-brick'), 'crops': Block((59, 0) 'crops': transparent), 'sand': Block((12, 0) 'sand'), 115: Block((115, 0) 'nether-wart-block': drops 1 (key (372, 0), rate 100.00%)), 'clay': Block((82, 0) 'clay': drops 4 (key (337, 0), rate 100.00%)), 'lever': Block((69, 0) 'lever': transparent), 'double-step': Block((43, 0) 'double-step'), 'bed-block': Block((26, 0) 'bed-block': drops 1 (key (355, 0), rate 100.00%)), 129: Block((129, 0) 'emerald-ore'), 'workbench': Block((58, 0) 'workbench'), 'orange-wool': Block((35, 1) 'orange-wool': drops 1 (key (35, 0), rate 100.00%)), 'hidden-silverfish': Block((97, 0) 'hidden-silverfish': drops 1 (key (0, 0), rate 100.00%)), 'fence': Block((85, 0) 'fence': transparent), 'dark-green-wool': Block((35, 13) 'dark-green-wool': drops 1 (key (35, 0), rate 100.00%)), 'spring': Block((9, 0) 'spring': unbreakable, translucent (3)), 'torch': Block((50, 0) 'torch': transparent), 'vine': Block((106, 0) 'vine'), 109: Block((109, 0) 'stone-brick-stairs'), 'sponge': Block((19, 0) 'sponge'), 'redstone-repeater-off': Block((93, 0) 'redstone-repeater-off': transparent, drops 1 (key (356, 0), rate 100.00%)), 'melon': Block((103, 0) 'melon'), 'iron-bars': Block((101, 0) 'iron-bars'), 110: Block((110, 0) 'mycelium': drops 1 (key (3, 0), rate 100.00%)), 'cactus': Block((81, 0) 'cactus': transparent), 'sticky-piston': Block((29, 0) 'sticky-piston'), 'huge-red-mushroom': Block((100, 0) 'huge-red-mushroom': drops 2 (key (40, 0), rate 100.00%)), 'brown-mushroom': Block((39, 0) 'brown-mushroom': transparent), 27: Block((27, 0) 'powered-rail'), 'shrub': Block((32, 0) 'shrub'), 'birch-log': Block((17, 2) 'birch-log': drops 1 (key (17, 0), rate 100.00%)), 113: Block((113, 0) 'nether-brick-fence'), 'blue-wool': Block((35, 11) 'blue-wool': drops 1 (key (35, 0), rate 100.00%)), 114: Block((114, 0) 'nether-brick-stairs'), 'ice': Block((79, 0) 'ice': translucent (3), becomes 9, drops 1 (key (0, 0), rate 100.00%)), 108: Block((108, 0) 'brick-stairs'), 'piston': Block((33, 0) 'piston'), 'pine-log': Block((17, 1) 'pine-log': drops 1 (key (17, 0), rate 100.00%)), 'nether-wart-block': Block((115, 0) 'nether-wart-block': drops 1 (key (372, 0), rate 100.00%)), 'lightstone': Block((89, 0) 'lightstone': drops 1 (key (348, 0), rate 100.00%)), 'stone-step': Block((44, 0) 'stone-step': transparent), 'cake-block': Block((92, 0) 'cake-block': transparent), 'dirt': Block((3, 0) 'dirt'), 'pumpkin': Block((86, 0) 'pumpkin'), 'red-wool': Block((35, 14) 'red-wool': drops 1 (key (35, 0), rate 100.00%)), 'water': Block((8, 0) 'water': unbreakable, translucent (3)), 'step': Block((44, 0) 'step': transparent), 'jungle-leaf': Block((18, 3) 'jungle-leaf': translucent (1), drops 1 (key (6, 0), rate 100.00%)), 'nether-brick': Block((112, 0) 'nether-brick'), 37: Block((37, 0) 'flower': transparent), 'emerald-ore': Block((129, 0) 'emerald-ore'), 'stone': Block((1, 0) 'stone': drops 1 (key (4, 0), rate 100.00%)), 'brown-wool': Block((35, 12) 'brown-wool': drops 1 (key (35, 0), rate 100.00%)), 'jungle-sapling': Block((6, 3) 'jungle-sapling': transparent, drops 1 (key (6, 0), rate 100.00%)), 'normal-leaf': Block((18, 0) 'normal-leaf': translucent (1), drops 1 (key (6, 0), rate 100.00%)), 'leaves': Block((18, 0) 'leaves': translucent (1), drops 1 (key (6, 0), rate 11.11%)), 'cyan-wool': Block((35, 9) 'cyan-wool': drops 1 (key (35, 0), rate 100.00%)), 'tracks': Block((66, 0) 'tracks': transparent), 59: Block((59, 0) 'crops': transparent), 'fence-gate': Block((107, 0) 'fence-gate'), 41: Block((41, 0) 'gold'), 'wooden-stairs': Block((53, 0) 'wooden-stairs': transparent), 'powered-rail': Block((27, 0) 'powered-rail'), 'jukebox': Block((84, 0) 'jukebox'), 'yellow-wool': Block((35, 4) 'yellow-wool': drops 1 (key (35, 0), rate 100.00%)), 'magenta-wool': Block((35, 2) 'magenta-wool': drops 1 (key (35, 0), rate 100.00%)), 'detector-rail': Block((28, 0) 'detector-rail'), 'normal-sapling': Block((6, 0) 'normal-sapling': transparent), 'stone-stairs': Block((67, 0) 'stone-stairs': transparent), 'diamond-block': Block((57, 0) 'diamond-block'), 133: Block((133, 0) 'emerald-block'), 'brimstone': Block((87, 0) 'brimstone'), 'melon-stem': Block((105, 0) 'melon-stem': drops 3 (key (362, 0), rate 100.00%)), 'log': Block((17, 0) 'log'), 'brick-stairs': Block((108, 0) 'brick-stairs'), 'snow-block': Block((80, 0) 'snow-block'), 'trapdoor': Block((96, 0) 'trapdoor'), 'lava-spring': Block((11, 0) 'lava-spring': unbreakable, transparent), 'red-mushroom': Block((40, 0) 'red-mushroom': transparent), 'light-blue-wool': Block((35, 3) 'light-blue-wool': drops 1 (key (35, 0), rate 100.00%)), 51: Block((51, 0) 'fire': transparent), 'bedrock': Block((7, 0) 'bedrock': unbreakable), 'pine-sapling': Block((6, 1) 'pine-sapling': transparent, drops 1 (key (6, 0), rate 100.00%)), 'lily-pad': Block((111, 0) 'lily-pad': drops 1 (key (0, 0), rate 100.00%)), 'brick': Block((45, 0) 'brick'), 'mossy-cobblestone': Block((48, 0) 'mossy-cobblestone'), 'jungle-log': Block((17, 3) 'jungle-log': drops 1 (key (17, 0), rate 100.00%)), 'fire': Block((51, 0) 'fire': transparent), 'signpost': Block((63, 0) 'signpost': transparent, drops 1 (key (323, 0), rate 100.00%)), 'glass': Block((20, 0) 'glass': transparent, drops 1 (key (0, 0), rate 100.00%)), 'reed': Block((83, 0) 'reed': transparent, drops 1 (key (338, 0), rate 100.00%)), 'lime-wool': Block((35, 5) 'lime-wool': drops 1 (key (35, 0), rate 100.00%)), 'bookshelf': Block((47, 0) 'bookshelf'), 'gold': Block((41, 0) 'gold'), 'wall-sign': Block((68, 0) 'wall-sign': transparent, drops 1 (key (323, 0), rate 100.00%)), 'normal-log': Block((17, 0) 'normal-log'), 'tnt': Block((46, 0) 'tnt'), 'pine-leaf': Block((18, 1) 'pine-leaf': translucent (1), drops 1 (key (6, 0), rate 100.00%)), 'wool': Block((35, 0) 'wool'), 'birch-sapling': Block((6, 2) 'birch-sapling': transparent, drops 1 (key (6, 0), rate 100.00%)), 60: Block((60, 0) 'soil': transparent, drops 1 (key (3, 0), rate 100.00%)), 'jack-o-lantern': Block((91, 0) 'jack-o-lantern'), 'wooden-plate': Block((72, 0) 'wooden-plate': transparent), 'air': Block((0, 0) 'air': unbreakable, transparent), 'iron': Block((42, 0) 'iron'), 'dispenser': Block((23, 0) 'dispenser'), 'grass': Block((2, 0) 'grass': drops 1 (key (3, 0), rate 100.00%)), 'redstone-wire': Block((55, 0) 'redstone-wire': transparent), 'black-wool': Block((35, 15) 'black-wool': drops 1 (key (35, 0), rate 100.00%)), 'cobblestone-step': Block((44, 3) 'cobblestone-step': transparent, drops 1 (key (44, 0), rate 100.00%)), 'gold-ore': Block((14, 0) 'gold-ore'), 'huge-brown-mushroom': Block((99, 0) 'huge-brown-mushroom': drops 2 (key (39, 0), rate 100.00%)), 'white-wool': Block((35, 0) 'white-wool'), 'stone-button': Block((77, 0) 'stone-button': transparent), 'soil': Block((60, 0) 'soil': transparent, drops 1 (key (3, 0), rate 100.00%)), 'locked-chest': Block((95, 0) 'locked-chest'), 'glass-pane': Block((102, 0) 'glass-pane'), 'redstone-torch': Block((76, 0) 'redstone-torch': transparent), 'iron-door-block': Block((71, 0) 'iron-door-block': drops 1 (key (330, 0), rate 100.00%)), 'light-gray-wool': Block((35, 8) 'light-gray-wool': drops 1 (key (35, 0), rate 100.00%)), 'nether-brick-fence': Block((113, 0) 'nether-brick-fence'), 'stone-brick': Block((98, 0) 'stone-brick'), 'purple-wool': Block((35, 10) 'purple-wool': drops 1 (key (35, 0), rate 100.00%)), 'birch-leaf': Block((18, 2) 'birch-leaf': translucent (1), drops 1 (key (6, 0), rate 100.00%)), 'coal-ore': Block((16, 0) 'coal-ore': drops 1 (key (263, 0), rate 100.00%)), 'nether-brick-stairs': Block((114, 0) 'nether-brick-stairs'), 'sandstone': Block((24, 0) 'sandstone'), 'snow': Block((78, 0) 'snow'), 'lava': Block((10, 0) 'lava': unbreakable, transparent), 'stone-brick-stairs': Block((109, 0) 'stone-brick-stairs'), 'chest': Block((54, 0) 'chest'), 'gray-wool': Block((35, 7) 'gray-wool': drops 1 (key (35, 0), rate 100.00%)), 'mycelium': Block((110, 0) 'mycelium': drops 1 (key (3, 0), rate 100.00%)), 'furnace': Block((61, 0) 'furnace'), 'wooden-step': Block((44, 2) 'wooden-step': transparent, drops 1 (key (44, 0), rate 100.00%)), 'pink-wool': Block((35, 6) 'pink-wool': drops 1 (key (35, 0), rate 100.00%)), 'emerald-block': Block((133, 0) 'emerald-block'), 'ladder': Block((65, 0) 'ladder': transparent), 'stone-plate': Block((70, 0) 'stone-plate': transparent), 'cobblestone': Block((4, 0) 'cobblestone'), 'flower': Block((37, 0) 'flower': transparent), 'portal': Block((90, 0) 'portal': transparent), 'pumpkin-stem': Block((104, 0) 'pumpkin-stem': drops 3 (key (361, 0), rate 100.00%)), 'slow-sand': Block((88, 0) 'slow-sand'), 'lapis-lazuli-ore': Block((21, 0) 'lapis-lazuli-ore': drops 6 (key (351, 4), rate 100.00%)), 'lapis-lazuli-block': Block((22, 0) 'lapis-lazuli-block'), 'note-block': Block((25, 0) 'note-block'), 'redstone-repeater-on': Block((94, 0) 'redstone-repeater-on': transparent, drops 1 (key (356, 0), rate 100.00%)), 67: Block((67, 0) 'stone-stairs': transparent), 'mob-spawner': Block((52, 0) 'mob-spawner': transparent, drops 1 (key (0, 0), rate 100.00%)), 'redstone-torch-off': Block((75, 0) 'redstone-torch-off': transparent), 'sandstone-step': Block((44, 1) 'sandstone-step': transparent, drops 1 (key (44, 0), rate 100.00%)), 'obsidian': Block((49, 0) 'obsidian'), 'burning-furnace': Block((62, 0) 'burning-furnace': drops 1 (key (61, 0), rate 100.00%)), 85: Block((85, 0) 'fence': transparent)}¶ A dictionary of
Block
objects.This dictionary can be indexed by slot number or block name.
-
bravo.blocks.
items
= {'': Item((387, 0) ''), 'wooden-door': Item((324, 0) 'wooden-door'), 379: Item((379, 0) ''), 'emerald': Item((388, 0) 'emerald'), 'compass': Item((345, 0) 'compass'), 'blaze-rod': Item((369, 0) 'blaze-rod'), 'chainmail-leggings': Item((304, 0) 'chainmail-leggings'), 'paper': Item((339, 0) 'paper'), 'glass-bottle': Item((374, 0) 'glass-bottle'), 'shears': Item((359, 0) 'shears'), 'cooked-porkchop': Item((320, 0) 'cooked-porkchop'), 'fermented-spider-eye': Item((376, 0) 'fermented-spider-eye'), 261: Item((261, 0) 'bow'), 'sugar-cane': Item((338, 0) 'sugar-cane'), 'slimeball': Item((341, 0) 'slimeball'), 'purple-dye': Item((351, 5) 'purple-dye'), 'chainmail-helmet': Item((302, 0) 'chainmail-helmet'), 348: Item((348, 0) 'glowstone-dust'), 'magma-cream': Item((378, 0) 'magma-cream'), 'diamond-chestplate': Item((311, 0) 'diamond-chestplate'), 349: Item((349, 0) 'raw-fish'), 'chirp-music-disc': Item((2259, 0) 'chirp-music-disc'), 'cocoa-beans': Item((351, 3) 'cocoa-beans'), 'wooden-sword': Item((268, 0) 'wooden-sword'), 'string': Item((287, 0) 'string'), 'pink-dye': Item((351, 9) 'pink-dye'), 346: Item((346, 0) 'fishing-rod'), 'pumpkin-seeds': Item((361, 0) 'pumpkin-seeds'), 'melon-slice': Item((360, 0) 'melon-slice'), 'snowball': Item((332, 0) 'snowball'), 'flint': Item((318, 0) 'flint'), 'iron-helmet': Item((306, 0) 'iron-helmet'), 'dye': Item((351, 0) 'dye'), 'magenta-dye': Item((351, 13) 'magenta-dye'), 'diamond-pickaxe': Item((278, 0) 'diamond-pickaxe'), 'bread': Item((297, 0) 'bread'), 'iron-boots': Item((309, 0) 'iron-boots'), 'leather-chestplate': Item((299, 0) 'leather-chestplate'), 'iron-door': Item((330, 0) 'iron-door'), 'diamond-shovel': Item((277, 0) 'diamond-shovel'), 'raw-porkchop': Item((319, 0) 'raw-porkchop'), 'leather': Item((334, 0) 'leather'), 'gold-chestplate': Item((315, 0) 'gold-chestplate'), 'gold-sword': Item((283, 0) 'gold-sword'), 'charcoal': Item((263, 1) 'charcoal'), 'green-music-disc': Item((2257, 0) 'green-music-disc'), 'rotten-flesh': Item((367, 0) 'rotten-flesh'), 'blocks-music-disc': Item((2258, 0) 'blocks-music-disc'), 'ghast-tear': Item((370, 0) 'ghast-tear'), 'arrow': Item((262, 0) 'arrow'), 361: Item((361, 0) 'pumpkin-seeds'), 'iron-chestplate': Item((307, 0) 'iron-chestplate'), 'water-bucket': Item((326, 0) 'water-bucket'), 'iron-pickaxe': Item((257, 0) 'iron-pickaxe'), 'cooked-fish': Item((350, 0) 'cooked-fish'), 'bone': Item((352, 0) 'bone'), 'diamond-leggings': Item((312, 0) 'diamond-leggings'), 363: Item((363, 0) 'raw-beef'), 'blaze-powder': Item((377, 0) 'blaze-powder'), 'mine-cart': Item((328, 0) 'mine-cart'), 'leather-leggings': Item((300, 0) 'leather-leggings'), 'bone-meal': Item((351, 15) 'bone-meal'), 'raw-beef': Item((363, 0) 'raw-beef'), 'ink-sac': Item((351, 0) 'ink-sac'), 'sign': Item((323, 0) 'sign'), 'diamond-axe': Item((279, 0) 'diamond-axe'), 366: Item((366, 0) 'cooked-chicken'), 'storage-minecart': Item((342, 0) 'storage-minecart'), 'redstone': Item((331, 0) 'redstone'), 'stone-sword': Item((272, 0) 'stone-sword'), 'wooden-axe': Item((271, 0) 'wooden-axe'), 'stone-axe': Item((275, 0) 'stone-axe'), 'paintings': Item((321, 0) 'paintings'), 'clock': Item((347, 0) 'clock'), 'milk': Item((335, 0) 'milk'), 'gold-boots': Item((317, 0) 'gold-boots'), 'clay-brick': Item((336, 0) 'clay-brick'), 'boat': Item((333, 0) 'boat'), 'gold-nugget': Item((371, 0) 'gold-nugget'), 'far-music-disc': Item((2260, 0) 'far-music-disc'), 364: Item((364, 0) 'steak'), 'diamond-sword': Item((276, 0) 'diamond-sword'), 373: Item((373, 0) 'potions'), 'redstone-repeater': Item((356, 0) 'redstone-repeater'), 'stone-hoe': Item((291, 0) 'stone-hoe'), 'nether-wart': Item((372, 0) 'nether-wart'), 'wheat': Item((296, 0) 'wheat'), 'light-blue-dye': Item((351, 12) 'light-blue-dye'), 'powered-minecart': Item((343, 0) 'powered-minecart'), 384: Item((384, 0) ''), 2257: Item((2257, 0) 'green-music-disc'), 2256: Item((2256, 0) 'gold-music-disc'), 376: Item((376, 0) 'fermented-spider-eye'), 2258: Item((2258, 0) 'blocks-music-disc'), 2259: Item((2259, 0) 'chirp-music-disc'), 'cookie': Item((357, 0) 'cookie'), 'ender-pearl': Item((368, 0) 'ender-pearl'), 'green-dye': Item((351, 2) 'green-dye'), 314: Item((314, 0) 'gold-helmet'), 'diamond-boots': Item((313, 0) 'diamond-boots'), 'steak': Item((364, 0) 'steak'), 'leather-boots': Item((301, 0) 'leather-boots'), 'gold-helmet': Item((314, 0) 'gold-helmet'), 'lapis-lazuli': Item((351, 4) 'lapis-lazuli'), 'bow': Item((261, 0) 'bow'), 'gray-dye': Item((351, 8) 'gray-dye'), 'clay-balls': Item((337, 0) 'clay-balls'), 'seeds': Item((295, 0) 'seeds'), 'yellow-dye': Item((351, 11) 'yellow-dye'), 2260: Item((2260, 0) 'far-music-disc'), 'potions': Item((373, 0) 'potions'), 'fishing-rod': Item((346, 0) 'fishing-rod'), 256: Item((256, 0) 'iron-shovel'), 257: Item((257, 0) 'iron-pickaxe'), 258: Item((258, 0) 'iron-axe'), 259: Item((259, 0) 'flint-and-steel'), 260: Item((260, 0) 'apple'), 'apple': Item((260, 0) 'apple'), 262: Item((262, 0) 'arrow'), 263: Item((263, 0) 'coal'), 264: Item((264, 0) 'diamond'), 265: Item((265, 0) 'iron-ingot'), 266: Item((266, 0) 'gold-ingot'), 267: Item((267, 0) 'iron-sword'), 268: Item((268, 0) 'wooden-sword'), 269: Item((269, 0) 'wooden-shovel'), 270: Item((270, 0) 'wooden-pickaxe'), 271: Item((271, 0) 'wooden-axe'), 272: Item((272, 0) 'stone-sword'), 273: Item((273, 0) 'stone-shovel'), 274: Item((274, 0) 'stone-pickaxe'), 275: Item((275, 0) 'stone-axe'), 276: Item((276, 0) 'diamond-sword'), 277: Item((277, 0) 'diamond-shovel'), 278: Item((278, 0) 'diamond-pickaxe'), 279: Item((279, 0) 'diamond-axe'), 280: Item((280, 0) 'stick'), 281: Item((281, 0) 'bowl'), 282: Item((282, 0) 'mushroom-soup'), 283: Item((283, 0) 'gold-sword'), 284: Item((284, 0) 'gold-shovel'), 285: Item((285, 0) 'gold-pickaxe'), 286: Item((286, 0) 'gold-axe'), 287: Item((287, 0) 'string'), 288: Item((288, 0) 'feather'), 289: Item((289, 0) 'sulphur'), 290: Item((290, 0) 'wooden-hoe'), 291: Item((291, 0) 'stone-hoe'), 292: Item((292, 0) 'iron-hoe'), 293: Item((293, 0) 'diamond-hoe'), 294: Item((294, 0) 'gold-hoe'), 295: Item((295, 0) 'seeds'), 296: Item((296, 0) 'wheat'), 297: Item((297, 0) 'bread'), 298: Item((298, 0) 'leather-helmet'), 299: Item((299, 0) 'leather-chestplate'), 300: Item((300, 0) 'leather-leggings'), 301: Item((301, 0) 'leather-boots'), 302: Item((302, 0) 'chainmail-helmet'), 303: Item((303, 0) 'chainmail-chestplate'), 304: Item((304, 0) 'chainmail-leggings'), 305: Item((305, 0) 'chainmail-boots'), 306: Item((306, 0) 'iron-helmet'), 307: Item((307, 0) 'iron-chestplate'), 308: Item((308, 0) 'iron-leggings'), 309: Item((309, 0) 'iron-boots'), 310: Item((310, 0) 'diamond-helmet'), 311: Item((311, 0) 'diamond-chestplate'), 312: Item((312, 0) 'diamond-leggings'), 313: Item((313, 0) 'diamond-boots'), 'feather': Item((288, 0) 'feather'), 315: Item((315, 0) 'gold-chestplate'), 'diamond-helmet': Item((310, 0) 'diamond-helmet'), 317: Item((317, 0) 'gold-boots'), 'gold-ingot': Item((266, 0) 'gold-ingot'), 319: Item((319, 0) 'raw-porkchop'), 320: Item((320, 0) 'cooked-porkchop'), 321: Item((321, 0) 'paintings'), 322: Item((322, 0) 'golden-apple'), 'diamond': Item((264, 0) 'diamond'), 324: Item((324, 0) 'wooden-door'), 325: Item((325, 0) 'bucket'), 326: Item((326, 0) 'water-bucket'), 327: Item((327, 0) 'lava-bucket'), 328: Item((328, 0) 'mine-cart'), 329: Item((329, 0) 'saddle'), 330: Item((330, 0) 'iron-door'), 331: Item((331, 0) 'redstone'), 332: Item((332, 0) 'snowball'), 'iron-leggings': Item((308, 0) 'iron-leggings'), 334: Item((334, 0) 'leather'), 335: Item((335, 0) 'milk'), 336: Item((336, 0) 'clay-brick'), 337: Item((337, 0) 'clay-balls'), 338: Item((338, 0) 'sugar-cane'), 318: Item((318, 0) 'flint'), 340: Item((340, 0) 'book'), 'stick': Item((280, 0) 'stick'), 342: Item((342, 0) 'storage-minecart'), 343: Item((343, 0) 'powered-minecart'), 344: Item((344, 0) 'egg'), 345: Item((345, 0) 'compass'), 'sulphur': Item((289, 0) 'sulphur'), 347: Item((347, 0) 'clock'), 'lava-bucket': Item((327, 0) 'lava-bucket'), 'gold-shovel': Item((284, 0) 'gold-shovel'), 350: Item((350, 0) 'cooked-fish'), 351: Item((351, 0) 'dye'), 352: Item((352, 0) 'bone'), 353: Item((353, 0) 'sugar'), 354: Item((354, 0) 'cake'), 355: Item((355, 0) 'bed'), 356: Item((356, 0) 'redstone-repeater'), 357: Item((357, 0) 'cookie'), 358: Item((358, 0) 'map'), 359: Item((359, 0) 'shears'), 360: Item((360, 0) 'melon-slice'), 316: Item((316, 0) 'gold-leggings'), 362: Item((362, 0) 'melon-seeds'), 'saddle': Item((329, 0) 'saddle'), 'bucket': Item((325, 0) 'bucket'), 365: Item((365, 0) 'raw-chicken'), 'bed': Item((355, 0) 'bed'), 333: Item((333, 0) 'boat'), 368: Item((368, 0) 'ender-pearl'), 369: Item((369, 0) 'blaze-rod'), 370: Item((370, 0) 'ghast-tear'), 371: Item((371, 0) 'gold-nugget'), 372: Item((372, 0) 'nether-wart'), 'iron-axe': Item((258, 0) 'iron-axe'), 374: Item((374, 0) 'glass-bottle'), 375: Item((375, 0) 'spider-eye'), 'cake': Item((354, 0) 'cake'), 377: Item((377, 0) 'blaze-powder'), 378: Item((378, 0) 'magma-cream'), 'raw-chicken': Item((365, 0) 'raw-chicken'), 380: Item((380, 0) ''), 381: Item((381, 0) ''), 382: Item((382, 0) ''), 383: Item((383, 0) ''), 'stone-pickaxe': Item((274, 0) 'stone-pickaxe'), 'iron-hoe': Item((292, 0) 'iron-hoe'), 386: Item((386, 0) ''), 387: Item((387, 0) ''), 388: Item((388, 0) 'emerald'), 'wooden-hoe': Item((290, 0) 'wooden-hoe'), 'gold-pickaxe': Item((285, 0) 'gold-pickaxe'), 'iron-ingot': Item((265, 0) 'iron-ingot'), 'gold-hoe': Item((294, 0) 'gold-hoe'), 323: Item((323, 0) 'sign'), 'chainmail-chestplate': Item((303, 0) 'chainmail-chestplate'), 'cyan-dye': Item((351, 6) 'cyan-dye'), 'mushroom-soup': Item((282, 0) 'mushroom-soup'), 'stone-shovel': Item((273, 0) 'stone-shovel'), 'light-gray-dye': Item((351, 7) 'light-gray-dye'), 'glowstone-dust': Item((348, 0) 'glowstone-dust'), 'sugar': Item((353, 0) 'sugar'), 'bowl': Item((281, 0) 'bowl'), 'iron-shovel': Item((256, 0) 'iron-shovel'), 'normal-coal': Item((263, 0) 'normal-coal'), 'gold-leggings': Item((316, 0) 'gold-leggings'), 'book': Item((340, 0) 'book'), 385: Item((385, 0) ''), 'spider-eye': Item((375, 0) 'spider-eye'), 'iron-sword': Item((267, 0) 'iron-sword'), 'gold-music-disc': Item((2256, 0) 'gold-music-disc'), 'map': Item((358, 0) 'map'), 'lime-dye': Item((351, 10) 'lime-dye'), 'diamond-hoe': Item((293, 0) 'diamond-hoe'), 'golden-apple': Item((322, 0) 'golden-apple'), 'chainmail-boots': Item((305, 0) 'chainmail-boots'), 'leather-helmet': Item((298, 0) 'leather-helmet'), 'wooden-shovel': Item((269, 0) 'wooden-shovel'), 'gold-axe': Item((286, 0) 'gold-axe'), 'wooden-pickaxe': Item((270, 0) 'wooden-pickaxe'), 'raw-fish': Item((349, 0) 'raw-fish'), 'cooked-chicken': Item((366, 0) 'cooked-chicken'), 'flint-and-steel': Item((259, 0) 'flint-and-steel'), 367: Item((367, 0) 'rotten-flesh'), 'melon-seeds': Item((362, 0) 'melon-seeds'), 'coal': Item((263, 0) 'coal'), 339: Item((339, 0) 'paper'), 'orange-dye': Item((351, 14) 'orange-dye'), 'red-dye': Item((351, 1) 'red-dye'), 'egg': Item((344, 0) 'egg'), 341: Item((341, 0) 'slimeball')}¶ A dictionary of
Item
objects.This dictionary can be indexed by slot number or block name.
-
bravo.blocks.
unstackable
= (268, 269, 270)¶ List of fuel blocks and items maped to burn time
chunk
– Chunk data structures¶
The chunk
module holds the data structures required to track and update
block data in chunks.
entity
– Entities¶
The entity
module contains entity classes.
furnace
– Furnace Tile¶
The Furnace
tile has method changed(factory, coords)
where
coords
is tuple (bigx, smallx, bigz, smallz, y)
- coordinates of the
furnace which inventory was updated.
# inform content of furnace was probably changed
d = factory.world.request_chunk(bigx, bigz)
@d.addCallback
def on_change(chunk):
furnace = self.get_furnace_tile(chunk, (x, y, z))
if furnace is not None:
furnace.changed(factory, coords)
Furnace.changed()
method checks if current furnace shall start to burn:
it must have source item, fuel and must have valid recipe. If it meets the
requirements Furnace
schedules burn()
method with LoopingCall
for every .5 second.
At every burn()
call it:
- increases cooktime timer and checks if item shall be crafted on this iteration;
- decreases fuel counter and burns next fuel item if needed;
- if there is no need to burn next fuel item because crafted slot is full or source slot is empty it stops the LoopingCall;
- sends progress bars updates to all players that have this furnace’s window opened.
ibravo
– Interfaces¶
The ibravo
module holds the interfaces required to implement plugins and
hooks.
Interface Bases¶
These are the base interface classes for Bravo. Plugin developers probably will not inherit from these; they are used purely to express common plugin functionality.
-
class
bravo.ibravo.
IBravoPlugin
[source]¶ Bases:
zope.interface.Interface
Interface for plugins.
This interface stores common metadata used during plugin discovery.
-
class
bravo.ibravo.
ISortedPlugin
[source]¶ Bases:
bravo.ibravo.IBravoPlugin
Parent interface for sorted plugins.
Sorted plugins have an innate and automatic ordering inside lists thanks to the ability to advertise their dependencies.
Plugins¶
-
class
bravo.ibravo.
IAutomaton
[source]¶ Bases:
bravo.ibravo.IBravoPlugin
An automaton.
Automatons are given blocks from chunks which interest them, and may do processing on those blocks.
-
class
bravo.ibravo.
IChatCommand
[source]¶ Bases:
bravo.ibravo.ICommand
Interface for chat commands.
Chat commands are invoked from the chat inside clients, so they are always called by a specific client.
This interface is specifically designed to exist comfortably side-by-side with IConsoleCommand.
-
class
bravo.ibravo.
IConsoleCommand
[source]¶ Bases:
bravo.ibravo.ICommand
Interface for console commands.
Console commands are invoked from a console or some other location with two defining attributes: Access restricted to superusers, and no user issuing the command. As such, no access control list applies to them, but they must be given usernames to operate on explicitly.
-
class
bravo.ibravo.
IRecipe
[source]¶ Bases:
bravo.ibravo.IBravoPlugin
A description for creating materials from other materials.
-
class
bravo.ibravo.
ISeason
[source]¶ Bases:
bravo.ibravo.IBravoPlugin
Seasons are transformational stages run during certain days to emulate an environment.
-
class
bravo.ibravo.
ISerializer
[source]¶ Bases:
bravo.ibravo.IBravoPlugin
Class that understands how to serialize several different kinds of objects to and from disk-friendly formats.
Implementors of this interface are expected to provide a uniform implementation of their serialization technique.
-
class
bravo.ibravo.
ITerrainGenerator
[source]¶ Bases:
bravo.ibravo.ISortedPlugin
Interface for terrain generators.
-
class
bravo.ibravo.
IWorldResource
[source]¶ Bases:
bravo.ibravo.IBravoPlugin
,twisted.web.resource.IResource
Interface for a world specific web resource.
Hooks¶
-
class
bravo.ibravo.
IPreBuildHook
[source]¶ Bases:
bravo.ibravo.ISortedPlugin
Hook for actions to be taken before a block is placed.
-
class
bravo.ibravo.
IPostBuildHook
[source]¶ Bases:
bravo.ibravo.ISortedPlugin
Hook for actions to be taken after a block is placed.
-
class
bravo.ibravo.
IDigHook
[source]¶ Bases:
bravo.ibravo.ISortedPlugin
Hook for actions to be taken after a block is dug up.
-
class
bravo.ibravo.
ISignHook
[source]¶ Bases:
bravo.ibravo.ISortedPlugin
Hook for actions to be taken after a sign is updated.
This hook fires both on sign creation and sign editing.
-
class
bravo.ibravo.
IUseHook
[source]¶ Bases:
bravo.ibravo.ISortedPlugin
Hook for actions to be taken when a player interacts with an entity.
Each plugin needs to specify a list of entity types it is interested in in advance, and it will only be called for those.
inventory
– Inventories¶
The inventory
module contains all kinds of windows and window parts
like inventory, crafting and storage slots.
Generally to create a window you must create a Window
object (of specific class
derived from Window
) and pass arguments like: window ID, player’s inventory,
slot’s or tile’s inventory, coordinates etc.
Generic construction (never use in your code :)
window = Window( id, Inventory(), Workbench(), ...)
Please note that player’s inventory window is a special case. It is created when user logins and stays always opened. You probably will never have to create it.
def authenticated(self):
BetaServerProtocol.authenticated(self)
# Init player, and copy data into it.
self.player = yield self.factory.world.load_player(self.username)
...
# Init players' inventory window.
self.inventory = InventoryWindow(self.player.inventory)
...
Every windows have own class. For instanse, to create a workbench window:
i = WorkbenchWindow(self.wid, self.player.inventory)
Furnace:
bigx, smallx, bigz, smallz, y = coords
furnace = self.chunks[x, y].tiles[(smallx, y, smallz)]
window = FurnaceWindow(self.wid, self.player.inventory, furnace.inventory, coords)
-
class
bravo.inventory.
Inventory
[source]¶ Bases:
bravo.inventory.SerializableSlots
The class represents Player’s inventory
-
add
(item, quantity)[source]¶ Attempt to add an item to the inventory.
Parameters: item (tuple) – a key representing the item Returns: quantity of items that did not fit inventory
-
location
– Locations¶
The location
module contains objects for tracking and analyzing locations.
plugin
– Plugin loader¶
The plugin
module implements a sophisticated, featureful plugin loader
with interface-based discovery.
-
bravo.plugin.
expand_names
(plugins, names)[source]¶ Given a list of names, expand wildcards and discard disabled names.
Used to implement * and - options in plugin lists.
Parameters: - plugins (dict) – plugins to use for expansion
- names (list) – names to examine
Returns: a list of filtered plugin names
-
bravo.plugin.
get_plugins
(interface, package)[source]¶ Lazily find objects in a package which implement a given interface.
This is a rewrite of Twisted’s
twisted.plugin.getPlugins
which searches for implementations of interfaces rather than providers.Parameters: - interface (interface) – the interface to match against
- package (str) – the name of the package to search
-
bravo.plugin.
retrieve_named_plugins
(interface, names, **kwargs)[source]¶ Look up a list of plugins by name.
Plugins are returned in the same order as their names.
Parameters: - interface (interface) – the interface to use
- names (list) – plugins to find
- parameters (dict) – parameters to pass into the plugins
Returns: a list of plugins
Raises: PluginException – no plugins could be found for the given interface
-
bravo.plugin.
retrieve_plugins
(interface, **kwargs)[source]¶ Look up all plugins for a certain interface.
If the plugin cache is enabled, this function will not attempt to reload plugins from disk or discover new plugins.
Parameters: - interface (interface) – the interface to use
- parameters (dict) – parameters to pass into the plugins
Returns: a dict of plugins, keyed by name
Raises: PluginException – no plugins could be found for the given interface
-
bravo.plugin.
retrieve_sorted_plugins
(interface, names, **kwargs)[source]¶ Look up a list of plugins, sorted by interdependencies.
Parameters: parameters (dict) – parameters to pass into the plugins
-
bravo.plugin.
sort_plugins
(plugins)[source]¶ Make a sorted list of plugins by dependency.
If the list cannot be arranged into a DAG, an error will be raised. This usually means that a cyclic dependency was found.
Raises: PluginException – cyclic dependency detected
-
bravo.plugin.
verify_plugin
(interface, plugin)[source]¶ Plugin interface verification.
This function will call
verifyObject()
andvalidateInvariants()
on the plugins passed to it.The primary purpose of this wrapper is to do logging, but it also permits code to be slightly cleaner, easier to test, and callable from other modules.
stdio
– Console support¶
The stdio
module provides a non-blocking, interactive console for
administration, diagnostics, and debugging of running servers.
world
– Worlds¶
Auxiliary¶
Modules which do not contribute directly to the functionality of Bravo.
simplex
– Simplex noise generation¶
-
bravo.simplex.
octaves2
(x, y, count)[source]¶ Generate fractal octaves of noise.
Summing increasingly scaled amounts of noise with itself creates fractal clouds of noise.
Parameters: Returns: Scaled fractal noise
-
bravo.simplex.
octaves3
(x, y, z, count)[source]¶ Generate fractal octaves of noise.
Parameters: Returns: Scaled fractal noise
-
bravo.simplex.
offset2
(x, y, xoffset, yoffset, octaves=1)[source]¶ Generate an offset noise difference field.
Parameters: Returns: Difference of noises
-
bravo.simplex.
simplex2
(x, y)[source]¶ Generate simplex noise at the given coordinates.
This particular implementation has very high chaotic features at normal resolution; zooming in by a factor of 16x to 256x is going to yield more pleasing results for most applications.
The gradient field must be seeded prior to calling this function; call
reseed()
first.Parameters: Returns: simplex noise
Raises: Exception – the gradient field is not seeded
-
bravo.simplex.
simplex3
(x, y, z)[source]¶ Generate simplex noise at the given coordinates.
This is a 3-dimensional flavor of
simplex2()
; all of the same caveats apply.The gradient field must be seeded prior to calling this function; call
reseed()
first.Parameters: Returns: simplex noise
Raises: Exception – the gradient field is not seeded or you broke the function somehow
utilities
– Helper functions¶
The utilities
package is the standard home for shared functions which many
modules may use. The spirit of utilities
is also to isolate sections of
critical code so that unit tests can be used to ensure a minimum of bugginess.
Automaton Helpers¶
-
bravo.utilities.automatic.
column_scan
(automaton, chunk)[source]¶ Utility function which provides a chunk scanner which only examines the tallest blocks in the chunk. This can be useful for automatons which only care about sunlit or elevated areas.
This method can be used directly in automaton classes to provide scan().
-
bravo.utilities.automatic.
naive_scan
(automaton, chunk)[source]¶ Utility function which can be used to implement a naive, slow, but thorough chunk scan for automatons.
This method is designed to be directly useable on automaton classes to provide the scan() interface.
This function depends on implementation details of
Chunk
.
Chat Formatting¶
Colorizers.
-
bravo.utilities.chat.
complete
(sentence, possibilities)[source]¶ Perform completion on a string using a list of possible strings.
Returns a single string containing all possibilities.
Coordinate Handling¶
Utilities for coordinate handling and munging.
-
bravo.utilities.coords.
adjust_coords_for_face
(coords, face)[source]¶ Adjust a set of coords according to a face.
The face is a standard string descriptor, such as “+x”.
The “noop” face is supported.
-
bravo.utilities.coords.
split_coords
(x, z)[source]¶ Split a pair of coordinates into chunk and subchunk coordinates.
Parameters: Returns: a tuple of the X chunk, X subchunk, Z chunk, and Z subchunk
Data Packing¶
More affectionately known as “bit-twiddling.”
-
bravo.utilities.bits.
grouper
(n, iterable, fillvalue=None)[source]¶ grouper(3, ‘ABCDEFG’, ‘x’) –> ABC DEF Gxx
-
bravo.utilities.bits.
pack_nibbles
(a)[source]¶ Pack pairs of nibbles into bytes.
Bytes are returned as characters.
Parameters: a (array) – nibbles to pack Returns: packed nibbles as a string of bytes
-
bravo.utilities.bits.
unpack_nibbles
(l)[source]¶ Unpack bytes into pairs of nibbles.
Nibbles are half-byte quantities. The nibbles unpacked by this function are returned as unsigned numeric values.
>>> unpack_nibbles("a") [6, 1] >>> unpack_nibbles("nibbles") [6, 14, 6, 9, 6, 2, 6, 2, 6, 12, 6, 5, 7, 3]
Parameters: l (list) – bytes Returns: list of nibbles
Decorators¶
General decorators for a variety of purposes.
Geometry¶
Simple pixel graphics helpers.
-
bravo.utilities.geometry.
gen_close_point
(point1, point2)[source]¶ Retrieve the first integer set of coordinates on the line from the first point to the second point.
The set of coordinates corresponding to the first point will not be retrieved.
Scheduling¶
-
class
bravo.utilities.temporal.
PendingEvent
[source]¶ Bases:
object
An event which will happen at some point.
Structurally, this could be thought of as a poor man’s upside-down DeferredList; it turns a single callback/errback into a broadcast which fires many multiple Deferreds.
This code came from Epsilon and should go into Twisted at some point.
-
bravo.utilities.temporal.
split_time
(timestamp)[source]¶ Turn an MC timestamp into hours and minutes.
The time is calculated by interpolating the MC clock over the standard 24-hour clock.
Parameters: timestamp (int) – MC timestamp, in the range 0-24000 Returns: a tuple of hours and minutes on the 24-hour clock
-
bravo.utilities.temporal.
timestamp_from_clock
(clock)[source]¶ Craft an int-sized timestamp from a clock.
More precisely, the size of the timestamp is 4 bytes, and the clock must be an implementor of IReactorTime. twisted.internet.reactor and twisted.internet.task.Clock are the primary suspects.
This function’s timestamps are millisecond-accurate.
Spatial Hashes¶
-
class
bravo.utilities.spatial.
Block2DSpatialDict
[source]¶ Bases:
bravo.utilities.spatial.SpatialDict
Class for tracking blocks in the XZ-plane.
-
class
bravo.utilities.spatial.
Block3DSpatialDict
[source]¶ Bases:
bravo.utilities.spatial.SpatialDict
Class for tracking blocks in the XZ-plane.
-
class
bravo.utilities.spatial.
SpatialDict
[source]¶ Bases:
object
,UserDict.DictMixin
A spatial dictionary, for accelerating spatial lookups.
This particular class is a template for specific spatial dictionaries; in order to make it work, subclass it and add
key_for_bucket()
.
Trigonometry¶
-
bravo.utilities.maths.
circling
(x, y, r)[source]¶ Generate the points of the filled integral circle of the given radius around the given coordinates.
-
bravo.utilities.maths.
clamp
(x, low, high)[source]¶ Clamp or saturate a number to be no lower than a minimum and no higher than a maximum.
Implemented as its own function simply because it’s so easy to mess up when open-coded.
-
bravo.utilities.maths.
morton2
(x, y)[source]¶ Create a Morton number by interleaving the bits of two numbers.
This can be used to map 2D coordinates into the integers.
Inputs will be masked off to 16 bits, unsigned.
-
bravo.utilities.maths.
rotated_cosine
(x, y, theta, lambd)[source]¶ Evaluate a rotated 3D sinusoidal wave at a given point, angle, and wavelength.
The function used is:
This function has a handful of useful properties; it has a local minimum at f(0, 0) and oscillates infinitely betwen 0 and 1.
Parameters: Returns: float of f(x, y)
Tools¶
A handful of utilities are distributed with Bravo, in the tools directory.
Chunkbench¶
Chunkbench is a script that tests terrain generation speed.
Jsondump¶
Jsondump pretty-prints a JSON file.
NBTdump¶
NBTdump pretty-prints an NBT file.
Noiseview¶
Noiseview creates a picture of simplex noise, using Bravo’s builtin noise generator.
parser-cli¶
parser-cli parses and pretty-prints raw Alpha packets.