predicate;
40 | private final int requiredRepetitions;
41 | private int currentRepetitions = 0;
42 |
43 | /**
44 | * Creates a new RepeatedKeywordPredicate using the given predicate that
45 | * must match at least the given number of repetitions.
46 | *
47 | *
48 | * Note: The match counter is increased for the first match, so this
49 | * predicate will return true for all matching elements if
50 | * requiredRepetitions is set to 1.
51 | *
52 | *
53 | * @param predicate The filter used to check the input.
54 | * @param requiredRepetitions The required number of consecutive matches
55 | * before this predicate will pass any tests. Must be > 1.
56 | */
57 | public RepeatedKeywordPredicate(Predicate predicate, int requiredRepetitions) {
58 | this.predicate = requireNonNull(predicate, "predicate");
59 | if (requiredRepetitions <= 0) {
60 | throw new IllegalArgumentException("requiredRepetitions cannot be zero or less");
61 | }
62 | this.requiredRepetitions = requiredRepetitions;
63 | }
64 |
65 | @Override
66 | public boolean test(T t) {
67 | if (this.predicate.test(t)) {
68 | this.currentRepetitions++;
69 | } else {
70 | this.currentRepetitions = 0;
71 | }
72 | return this.currentRepetitions >= this.requiredRepetitions;
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/source/plugin/inventory/creating.rst:
--------------------------------------------------------------------------------
1 | ==================
2 | Inventory Creation
3 | ==================
4 |
5 |
6 | Building free form inventories
7 | ==============================
8 |
9 | You can build inventories by either joining two inventories together using `union(inventory)`
10 | or building a new inventory from scratch or based on other inventories:
11 |
12 | .. note::
13 | Free form inventories **cannot** be opened by a player. To show the inventory to a player a ViewableInventory is needed.
14 |
15 | .. code-block:: java
16 |
17 | // Basic indexed Inventory
18 | public static Inventory buildIndexedInventory(int capacity) {
19 | return Inventory.builder().slots(capacity).completeStructure().plugin(this.pluginContainer).build();
20 | }
21 |
22 | // Basic grid Inventory
23 | public static Inventory buildIndexedInventory(int x, int y) {
24 | return Inventory.builder().grid(x, y).completeStructure().plugin(this.pluginContainer).build();
25 | }
26 |
27 | // Combined inventories
28 | public static Inventory buildIndexedInventory(Inventory base, int additionalCapacity) {
29 | return Inventory.builder().inventory(base).slots(additionalCapacity).completeStructure().plugin(this.pluginContainer).build();
30 | }
31 |
32 | // Inventory with carrier and identity
33 | public static Inventory buildIndexedInventory(int capacity) {
34 | return Inventory.builder().slots(capacity).completeStructure()
35 | .plugin(this.pluginContainer)
36 | .identity(uuid)
37 | .carrier(carrier)
38 | .build();
39 | }
40 |
41 | Building viewable inventories
42 | =============================
43 |
44 | To build a viewable inventory you need to follow the strict structure of a `ContainerType`.
45 | Completing the structure on en empty structure will attempt to replicate the vanilla inventory.
46 | Completing the structure on an incomplete structure will fill the rest with empty dummy slots.
47 |
48 | .. code-block:: java
49 |
50 | // Simple 3x3 inventory - looks like a Dropper
51 | public ViewableInventory simpleThreeByThree() {
52 | return ViewableInventory.builder().type(ContainerTypes.GENERIC_3X3).completeStructure().plugin(this.plugin).build();
53 | }
54 |
55 | // To replicate vanilla behaviour of an inventory. e.g. anvil provide no structure
56 | public ViewableInventory vanillaAnvil() {
57 | return ViewableInventory.builder().type(ContainerTypes.ANVIL).completeStructure().plugin(this.plugin).build();
58 | }
59 |
60 | // Chest 9x3 View of 3 other 3x3 inventories
61 | public ViewableInventory threeByThreeByThree() {
62 | Inventory i1 = Inventory.builder().grid(3, 3).completeStructure().plugin(this.pluginContainer).build();
63 | Inventory i2 = Inventory.builder().grid(3, 3).completeStructure().plugin(this.pluginContainer).build();
64 | Inventory i3 = Inventory.builder().grid(3, 3).completeStructure().plugin(this.pluginContainer).build();
65 | return ViewableInventory.builder().type(ContainerTypes.GENERIC_9X3)
66 | .grid(i1.slots(), Vector2i.from(3, 3), Vector2i.from(0, 0))
67 | .grid(i2.slots(), Vector2i.from(3, 3), Vector2i.from(3, 0))
68 | .grid(i3.slots(), Vector2i.from(3, 3), Vector2i.from(6, 0))
69 | .completeStructure().plugin(this.plugin).build();
70 | }
71 |
--------------------------------------------------------------------------------
/source/plugin/metrics.rst:
--------------------------------------------------------------------------------
1 | ==================
2 | Metrics Collection
3 | ==================
4 |
5 | .. warning::
6 | These docs were written for SpongeAPI 7 and are likely out of date.
7 | `If you feel like you can help update them, please submit a PR! `__
8 |
9 | .. javadoc-import::
10 | org.spongepowered.api.Sponge
11 | org.spongepowered.api.plugin.PluginContainer
12 | org.spongepowered.api.util.metric.MetricsConfigManager
13 |
14 | Collection of metrics from servers that use your plugin can be an incredibly useful tool for knowing what direction
15 | to take your plugin in. However, the :doc:`/ore/guidelines` (under External Connections) state that plugins may only
16 | collect metrics if informed consent has been granted. Such consent must be **opt-in**, metrics collection must be off
17 | by default.
18 |
19 | To simplify gathering consent, Sponge provides an API that allow plugins to check for this consent in a central way.
20 |
21 | Metrics collection consent is on a per-plugin basis. Plugins **must not** assume that consent for one plugin means
22 | consent for all.
23 |
24 | Obtaining Consent
25 | =================
26 |
27 | In order to gain consent from server owners, plugins may request that server owners enable metrics. This can be
28 | of the form of a message on startup instructing the players that they can enable metrics by updating the configuration
29 | option in configuration files. SpongeForge and SpongeVanilla also provide the ``/sponge metrics enable``
30 | command.
31 |
32 | Plugins **may** prompt server owners to run the command or allow for a "one click" enable in game.
33 |
34 | .. warning::
35 | Plugins **may not** run the ``/sponge metrics enable`` command without a server owner's informed
36 | consent. Doing so will cause a plugin to be rejected from the Ore platform.
37 |
38 | .. note::
39 | The ``/sponge metrics`` command is only guaranteed to exist on the ``SpongeForge`` and ``SpongeVanilla`` server
40 | implementations. Other implementations, such as ``Lantern``, may not include this command.
41 |
42 | Checking for Consent
43 | ====================
44 |
45 | The :javadoc:`MetricsConfigManager` allows you to determine if your plugin has gained consent to send metrics. This
46 | can either be injected into your plugin class, or obtained via :javadoc:`Sponge#getMetricsConfigManager()` object
47 | on demand.
48 |
49 | **Every time** your plugin wishes to send metrics, you must check the
50 | :javadoc:`MetricsConfigManager#getCollectionState(PluginContainer)`, supplying the :javadoc:`PluginContainer` of
51 | your plugin. Metrics must only be sent if this returns ``Tristate#TRUE`` for your plugin.
52 |
53 | The following example shows how to use field injections to get the ``MetricsConfigManager`` and the
54 | ``PluginContainer`` for your plugin, and uses those to determine whether consent to send metrics has been obtained.
55 |
56 | **Example**
57 |
58 | .. code-block:: java
59 |
60 | import com.google.inject.Inject;
61 | import org.spongepowered.api.plugin.PluginContainer;
62 | import org.spongepowered.api.util.metric.MetricsConfigManager;
63 |
64 | @Inject
65 | private PluginContainer container;
66 |
67 | @Inject
68 | private MetricsConfigManager metricsConfigManager;
69 |
70 | public boolean hasConsent() {
71 | return this.metricsConfigManager.getCollectionState(this.container).asBoolean();
72 | }
73 |
--------------------------------------------------------------------------------
/source/ore/routes/deploy-version.rst:
--------------------------------------------------------------------------------
1 | ======================
2 | Deploy Project Version
3 | ======================
4 |
5 | **POST /api/v1/projects/:pluginId/versions/:version**
6 |
7 | Deploys a new version for the specified project. The body should be sent as ``multipart/form-data`` with the fields
8 | shown below. Returns a JSON representation of the deployed version.
9 |
10 | +-------------+-----------+----------------------------------------------------------------+
11 | | Name | Data Type | Description |
12 | +=============+===========+================================================================+
13 | | apiKey | String | An Ore deployment key obtained through the Ore settings. |
14 | +-------------+-----------+----------------------------------------------------------------+
15 | | channel | String | The channel the version should be in. |
16 | +-------------+-----------+----------------------------------------------------------------+
17 | | recommended | Boolean | If this version should be set as the recommended version. |
18 | | | | Defaults to true. |
19 | +-------------+-----------+----------------------------------------------------------------+
20 | | forumPost | Boolean | Whether a forum post should be created or not. If no value is |
21 | | | | specified, it will default to the project's setting. Optional. |
22 | +-------------+-----------+----------------------------------------------------------------+
23 | | changelog | String | A changelog to include for this version. Optional. |
24 | +-------------+-----------+----------------------------------------------------------------+
25 | | pluginFile | File | The plugin file to upload. |
26 | +-------------+-----------+----------------------------------------------------------------+
27 | | pluginSig | File | A signature of the plugin file. |
28 | +-------------+-----------+----------------------------------------------------------------+
29 |
30 | **Example curl usage:**
31 |
32 | .. code-block:: bash
33 |
34 | curl -F "apiKey=string" -F "apiKey=string" -F "channel=string" -F "recommended=boolean" \
35 | -F "forumPost=boolean" -F "changelog=string" -F pluginFile=@localPluginFile \
36 | -F pluginSig=@localpluginSig https://ore.spongepowered.org/api/v1/projects/:pluginId/versions/:version
37 |
38 | **Example output:**
39 |
40 | .. code-block:: json
41 |
42 | {
43 | "id": 1226,
44 | "createdAt": "2018-02-08 18:41:36.917",
45 | "name": "1.1",
46 | "dependencies": [{
47 | "pluginId": "spongeapi",
48 | "version": "7.1.0"
49 | }],
50 | "pluginId": "auction",
51 | "channel": {
52 | "name": "Release",
53 | "color": "#009600"
54 | },
55 | "fileSize": 11441,
56 | "md5": "d169809b0eda0e5d49bc60d5f69f097b",
57 | "staffApproved": false,
58 | "href": "/ewoutvs_/Auction/versions/1.1",
59 | "tags": [{
60 | "id": 13,
61 | "name": "Sponge",
62 | "data": "7.1.0",
63 | "backgroundColor": "#F7Cf0D",
64 | "foregroundColor": "#000000"
65 | }],
66 | "downloads": 26,
67 | "author": "ewoutvs_"
68 | }
69 |
--------------------------------------------------------------------------------
/source/server/management/plugins.rst:
--------------------------------------------------------------------------------
1 | ==================
2 | Installing Plugins
3 | ==================
4 |
5 | What Are Plugins
6 | ================
7 |
8 | Plugins are files written in Java that change the way the server works, generally adding features. They allow server
9 | owners to do a lot of modifications, such as adding an economy system, managing teleports and permissions, etc.
10 |
11 | Finding Plugins
12 | ===============
13 |
14 | .. warning::
15 | Do not download plugins from untrustworthy sources! Malicious plugins can be used to give others unauthorized access
16 | to your server or computer.
17 |
18 | SpongePowered currently runs the `Ore platform `_ to make it easy for plugin developers
19 | and users to distribute and download plugins. Alternatively, you can search for plugins on the
20 | `SpongePowered forums `_.
21 |
22 | Installation
23 | ============
24 |
25 | SpongeForge
26 | ~~~~~~~~~~~
27 |
28 | In order to install plugins, place them into the ``/mods/`` folder of your game or server directory. If your download
29 | came in a .zip file, then you may need to extract it to find a .jar file inside.
30 |
31 | You can also place your plugins inside the ``/mods/plugins/`` subfolder or even set a custom folder in the
32 | :doc:`global.conf<../getting-started/configuration/sponge-conf>` file via the ``plugins-dir`` setting. SpongeForge will
33 | automatically search these folders for plugins. Please note that plugins which make use of ``Mixins`` *must* reside
34 | inside the ``mods`` folder.
35 |
36 | SpongeVanilla
37 | ~~~~~~~~~~~~~
38 |
39 | .. note::
40 | For consistency between SpongeForge and SpongeVanilla, plugins are stored in the mods directory on SpongeVanilla.
41 |
42 | In order to install plugins, place them into the ``/mods/`` folder of your game or server directory. If your download
43 | came in a .zip file, then you may need to extract it to find a .jar file inside.
44 |
45 | You can also place your plugins inside the ``/mods/plugins/`` subfolder or even set a custom folder in the
46 | :doc:`global.conf<../getting-started/configuration/sponge-conf>` file via the ``plugins-dir`` setting. SpongeVanilla
47 | will automatically search these folders for plugins. Please note that plugins which make use of ``Mixins`` *must* reside
48 | inside the ``mods`` folder.
49 |
50 | Common Problems
51 | ===============
52 |
53 | If you are having problems with a plugin, consider the following things:
54 |
55 | * Is the plugin compatible with your Minecraft version? While Sponge tries to keep old plugins working, this is
56 | sometimes not possible. In most cases, plugins based on a stable release should continue functioning without being
57 | updated. Please note that plugins might stop working if you switch to a different major version of the API, since
58 | major versions contain breaking changes. Refer to our :doc:`versioning scheme <../../contributing/versioning>` for
59 | more information.
60 | * Do you run a current Java version? Sponge is built for Java 8 and is known to trigger a bug in the JRE 1.8.0_20, so
61 | make sure you use a version newer than that.
62 | * The plugin may be outdated. Is there a newer version of the plugin?
63 | * Does the plugin need a specific implementation and/or build of Sponge? Some plugins may bypass the Sponge API, or
64 | otherwise rely on details that change between versions or platforms. Check at the site you downloaded it from.
65 |
--------------------------------------------------------------------------------
/source/versions/legacy-versions.rst:
--------------------------------------------------------------------------------
1 | =============================
2 | Older Versions of SpongeForge
3 | =============================
4 |
5 | .. note::
6 |
7 | Our versioning policy was updated in October 2018. **Prior to** SpongeAPI 7.1, the following information applies.
8 | See :doc:`filenames` for information on newer versions.
9 |
10 | The format of the SpongeForge download filename is:
11 | ``spongeforge----BETA-.jar``
12 |
13 | +----------------------+-----------------------------------------------------------------------------------------------+
14 | | ``MCVersion`` | The Minecraft version. Only clients compatible with this version can connect. |
15 | +----------------------+-----------------------------------------------------------------------------------------------+
16 | | ``ForgeBuild`` | The Forge build that SpongeForge is built against and is guaranteed to be compatible |
17 | +----------------------+-----------------------------------------------------------------------------------------------+
18 | | ``SpongeAPIVersion`` | The version of SpongeAPI implemented by this file. This is what Sponge plugins depend on. |
19 | +----------------------+-----------------------------------------------------------------------------------------------+
20 | | ``SpongeBuildId`` | The build number of Sponge. This is what you should supply when reporting bugs or seeking |
21 | | | support. |
22 | +----------------------+-----------------------------------------------------------------------------------------------+
23 |
24 | The Forge Build in the filename specifies the version of Forge this version of SpongeForge used during development and
25 | testing. The two versions are guaranteed to work without any issues. We **tend** to use the latest *Recommended Build*
26 | of Forge for this purpose.
27 |
28 | .. note::
29 |
30 | Normal Forge mods can usually run on any build of Forge for a given Minecraft version (e.g. 1.12.2) without any
31 | problem. However, SpongeForge needs to access, among other things, internal parts of Forge, which most mods
32 | shouldn’t be touching, let alone modifying as Sponge does. Since Forge is free to change their internal code
33 | whenever they want to, its normal guarantee of backwards-compatibility doesn’t apply to SpongeForge. Feel free to
34 | use more recent versions of Forge than the one used for SpongeForge, but we can't always guarantee compatibility.
35 |
36 | .. warning::
37 |
38 | When investigating crash issues, you can freely try newer versions of Forge than listed on the SpongeForge Jar.
39 | However, it is recommended to also check with the matching version, to make sure your issue is not related to a
40 | version mismatch.
41 | Even though there will be no guarantee of compatibility, please report any breakage to the issue tracker, so that
42 | SpongeForge can be updated.
43 |
44 | Example
45 | -------
46 |
47 | SpongeForge Jar files will always follow this naming scheme, to allow you to easily identify compatibility.
48 |
49 | For example, the file name ``spongeforge-1.12.2-2705-7.1.0-BETA-3442.jar`` is compatible with Minecraft version
50 | ``1.12.2``, was built with Forge ``14.23.4.2705`` (Build ``2705``), provides SpongeAPI ``7.1.0`` and was build number
51 | ``3442`` of SpongeForge.
52 |
--------------------------------------------------------------------------------
/source/contributing/implementation/debugging/testing.rst:
--------------------------------------------------------------------------------
1 | =======================
2 | Testing Plugins or Mods
3 | =======================
4 |
5 | .. note::
6 | The changes made by your PR determines whether you need to provide a testing plugin or a testing mod. Any changes
7 | to the API require a testing *plugin*, and any changes to implementation need a testing *mod*. Test plugin will
8 | refer to both for the remainder of this article.
9 |
10 | Testing is an integral part of any software development project. Supplying a test plugin accomplishes two goals:
11 |
12 | 1. Testing
13 |
14 | A test plugin demonstrates you have tested your changes, but it also provides others with the ability to check the
15 | current changes as well as future changes.
16 |
17 | #. Documentation
18 |
19 | A well-commented test plugin provides details not necessarily required in PR documentation. Furthermore, comments
20 | in a PR generally last until the PR is merged. Comments in a program last as long as the code remains. They should
21 | not provide all of the documentation. Instead, well-commented code supports and completes the documentation.
22 |
23 | .. tip::
24 | A good understanding of :doc:`/plugin/index` provides a solid foundation for writing test plugins. Plugin
25 | requirements apply to test plugins, such as :doc:`/plugin/plugin-identifier` and :doc:`/plugin/logging`.
26 |
27 | You should provide a test plugin when you are contributing new or modified feature(s) to the API or implementation. The
28 | plugin is simply a class added to the package ``org.spongepowered.test``, which is found in the
29 | ``SpongeCommon/testplugins/src/main/java/org/spongepowered/test/`` directory. The PR for the contributions should
30 | include the test plugin.
31 |
32 | It is essential that test plugins do not change the game when not intended. As a result, a command should toggle the
33 | plugin functionality. Be sure not to confuse this with **excluding** the test plugins in the build process. A setting
34 | in ``SpongeCommon/gradle/implementation.gradle`` can exclude test plugins from the resulting jar file. However, a
35 | command must toggle the functionality of the test plugin whether or not test plugins get included in a jar file or not.
36 |
37 | .. note::
38 | ``@Plugin`` will automatically register your plugin with Sponge, but it will not allow it to be toggled.
39 |
40 | The following code demonstrates registering your plugin and allowing it to be toggled:
41 |
42 | .. code-block:: java
43 |
44 | private boolean registered = false;
45 |
46 | @Listener
47 | public void onInit(GameInitializationEvent event) {
48 | Sponge.getCommandManager().register(this,
49 | CommandSpec.builder().executor((source, context) -> {
50 | if (this.registered) {
51 | this.registered = false;
52 | Sponge.getEventManager().unregisterListeners(this.listener);
53 | } else {
54 | this.registered = true;
55 | Sponge.getEventManager().registerListeners(this, this.listener);
56 | }
57 | return CommandResult.success();
58 | }).build(), "flowerPotTest");
59 | }
60 |
61 |
62 | .. note::
63 | JUnit is used on a limited basis and primarily for internal purposes. Generally speaking, JUnit is useful for
64 | testing without a player. However, the best practice is not to use JUnit unless you have agreement from a Sponge
65 | staff member.
66 |
--------------------------------------------------------------------------------
/source/plugin/project/version-numbers.rst:
--------------------------------------------------------------------------------
1 | Version Numbers
2 | ===============
3 |
4 | Your plugin needs a unique version number in order to allow humans to find out which version of a plugin is the
5 | successor of the other. There are plenty of versioning schemes that you could use for your own plugin. In the following
6 | part, we explain a few concepts with their pros and cons.
7 |
8 | Sponge recommends using a version identifier that consists of either two or three numeric version parts separated with
9 | a ``.`` and additional label appended with a hyphen ``-`` such as ``3.1`` or ``1.0.3-API7`` similar to SemVer.
10 | Start with ``1.x`` if your plugin is ready. Start with ``0.x`` if your plugin is not yet ready or unstable.
11 |
12 | .. note::
13 |
14 | While Sponge recommends using the above versioning scheme, plugin authors are free to choose their own. Please keep
15 | in mind that your users have to deal with a multitude of versioning schemes, so keep it simple.
16 |
17 | SemVer
18 | ------
19 |
20 | `SemVer `_ is a commonly used semantic versioning scheme. It consists of three numeric blocks that
21 | are separated by dots and additional labels which are appended using hyphens. The three numeric blocks make up
22 | the ``MAJOR``, ``MINOR`` and ``PATCH`` version parts.
23 |
24 | * A change in the **MAJOR** version indicates that you made incompatible API changes. Rewriting large parts of your
25 | plugin or the entire plugin would also count as incompatible changes.
26 | * A change in **MINOR** version indicates that a feature has been added without breaking backward compatibility.
27 | * A change in the **PATCH** version indicates that some bugs have been fixed.
28 |
29 | The labels can be used to mark builds as pre-releases or contain build metadata such as the supported Minecraft version.
30 | If you increase one part of the version, then you will set the following parts back to zero. Using this strategy you
31 | can find the latest version by comparing the version blocks with each other; however, this scheme does not contain any
32 | information about the release order for versions which differ in two version number blocks. Example: Version ``1.0.9``
33 | would be released after ``1.0.8``, but version ``1.1.0`` could be released before, after or even at the same time as
34 | either of them.
35 |
36 | .. note::
37 |
38 | The SpongeAPI uses this versioning scheme.
39 |
40 | **Examples**
41 |
42 | * ``0.1.0``
43 | * ``1.0.0``
44 | * ``1.1.0-SNAPSHOT``
45 | * ``3.12.21-API7``
46 |
47 | **Pros**
48 |
49 | * Easy to read and understand
50 |
51 | **Cons**
52 |
53 | * Mostly API oriented so the terms don't really apply if you don't provide an API in your plugin.
54 |
55 | Timestamp
56 | ---------
57 |
58 | This is a less commonly used versioning scheme, but it is also a very simple one, as it does not contain any additional
59 | information in the version numbers. It does not matter which separators you use (if any) or which date and time parts
60 | you include. However, we recommend ordering date and time parts in descending order of duration like ``YYYY-MM-DD``.
61 | If you sort your files alphabetically, please make sure that the order would be the same as the version order. It is
62 | also possible to add a build qualifier or a build number.
63 |
64 | **Examples**
65 |
66 | * ``18.01.31``
67 | * ``v2018-05-29.1``
68 | * ``2018.01.13-SNAPHOT``
69 |
70 | **Pros**
71 |
72 | * Easy to read and understand
73 |
74 | **Cons**
75 |
76 | * Does not contain any information about compatibility.
77 |
78 | Other
79 | -----
80 |
81 | You can read more about Software versioning and versioning schemes
82 | `online `_.
83 |
--------------------------------------------------------------------------------
/tools/code-checker/src/main/java/org/spongepowered/docs/tools/codeblock/OnOffKeywordPredicate.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of SpongeAPI, licensed under the MIT License (MIT).
3 | *
4 | * Copyright (c) SpongePowered
5 | * Copyright (c) contributors
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 | package org.spongepowered.docs.tools.codeblock;
26 |
27 | import java.util.function.Predicate;
28 |
29 | /**
30 | * Predicate that will filter the content based on the preceding on and off
31 | * keywords. Entries that match the on keyword will pass the filter. Entries
32 | * that match the off keyword will be removed.
33 | *
34 | * @param The type of data this predicate deals this.
35 | */
36 | public class OnOffKeywordPredicate implements Predicate {
37 |
38 | private final Predicate onKeyword;
39 | private final Predicate offKeyword;
40 | private boolean status = false;
41 |
42 | /**
43 | * Creates an new OnOffKeywordPredicate that will return all entries that
44 | * were tested while this instances was on. The initial status will be off.
45 | *
46 | * @param onKeyword The predicate used to decide to start letting entries
47 | * throughout.
48 | * @param offKeyword The predicate used to decide to stop letting entries
49 | * throughout.
50 | */
51 | public OnOffKeywordPredicate(Predicate onKeyword, Predicate offKeyword) {
52 | this(onKeyword, offKeyword, false);
53 | }
54 |
55 | /**
56 | * Creates an new OnOffKeywordPredicate that will return all entries that
57 | * were tested while this instances was on.
58 | *
59 | * @param onKeyword The predicate used to decide to start letting entries
60 | * throughout.
61 | * @param offKeyword The predicate used to decide to stop letting entries
62 | * throughout.
63 | * @param initialStatus The initial status of this filter.
64 | */
65 | public OnOffKeywordPredicate(Predicate onKeyword, Predicate offKeyword, boolean initialStatus) {
66 | this.onKeyword = onKeyword;
67 | this.offKeyword = offKeyword;
68 | this.status = initialStatus;
69 | }
70 |
71 | @Override
72 | public boolean test(T t) {
73 | if (this.status) {
74 | if (this.offKeyword.test(t)) {
75 | this.status = false;
76 | }
77 | } else {
78 | if (this.onKeyword.test(t)) {
79 | this.status = true;
80 | }
81 | }
82 | return this.status;
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/source/plugin/economy/practices.rst:
--------------------------------------------------------------------------------
1 | ==========================
2 | Economy API Best Practices
3 | ==========================
4 |
5 | .. javadoc-import::
6 | org.spongepowered.api.service.economy.transaction.ResultType
7 | org.spongepowered.api.service.economy.transaction.TransactionResult
8 |
9 | The Economy API tries to be abstract enough to give economy plugins flexibility in how they operate.
10 | In order to give economy plugins as much control as possible, plugins consuming the Economy API should
11 | follow some guidelines when working with it:
12 |
13 | Withdrawing money
14 | =================
15 |
16 | Plugins should *not* check if an account has enough money before attempting to withdraw it. While this may
17 | sound counter-intuitive, it allows economy plugins to fully control how they handle negative balances.
18 |
19 | By checking yourself if the account has enough money, you prevent the economy plugin from (potentially) allowing a
20 | negative balance. For example, one economy plugin might want to allow negative balances to admins, or players with a
21 | certain permission. By performing the check yourself, you take this power away from the economy plugin.
22 |
23 | This code illustrates what **not** to do:
24 |
25 | .. code-block:: java
26 |
27 | import java.math.BigDecimal;
28 |
29 | import org.spongepowered.api.event.cause.Cause;
30 | import org.spongepowered.api.event.cause.EventContext;
31 | import org.spongepowered.api.event.cause.EventContextKeys;
32 | import org.spongepowered.api.service.economy.EconomyService;
33 | import org.spongepowered.api.service.economy.account.Account;
34 |
35 | PluginContainer plugin = ...;
36 | EconomyService service = ...;
37 | Account account = ...;
38 | BigDecimal requiredAmount = BigDecimal.valueOf(20);
39 | EventContext eventContext = EventContext.builder().add(EventContextKeys.PLUGIN, plugin).build();
40 |
41 | // BAD: Don't perform this check
42 | if (account.getBalance(service.defaultCurrency()).compareTo(requiredAmount) < 0) {
43 | // You don't have enough money!
44 | } else {
45 | // The account has enough, let's withdraw some cash!
46 | account.withdraw(service.defaultCurrency(), requiredAmount, Cause.of(eventContext, plugin));
47 | }
48 |
49 |
50 | Instead of this, the best thing to do is simply withdraw the amount you need, and check the :javadoc:`ResultType` of
51 | the returned :javadoc:`TransactionResult`. An economy plugin which doesn't want to allow negative balances will simply
52 | return :javadoc:`ResultType#ACCOUNT_NO_FUNDS`, or :javadoc:`ResultType#FAILED` in this case.
53 |
54 | Here's how you **should** withdraw money:
55 |
56 | .. code-block:: java
57 |
58 | import org.spongepowered.api.event.cause.Cause;
59 | import org.spongepowered.api.event.cause.EventContext;
60 | import org.spongepowered.api.event.cause.EventContextKeys;
61 | import org.spongepowered.api.service.economy.transaction.ResultType;
62 | import org.spongepowered.api.service.economy.transaction.TransactionResult;
63 |
64 | PluginContainer plugin = ...;
65 | EconomyService service = ...;
66 | Account account = ...;
67 | BigDecimal requiredAmount = BigDecimal.valueOf(20);
68 | EventContext eventContext = EventContext.builder().add(EventContextKeys.PLUGIN, plugin).build();
69 |
70 | TransactionResult result = account.withdraw(service.getDefaultCurrency(), requiredAmount,
71 | Cause.of(eventContext, plugin));
72 | if (result.result() == ResultType.SUCCESS) {
73 | // Success!
74 | } else if (result.result() == ResultType.FAILED || result.result() == ResultType.ACCOUNT_NO_FUNDS) {
75 | // Something went wrong!
76 | } else {
77 | // Handle other conditions
78 | }
79 |
--------------------------------------------------------------------------------