Skip to content

MesterNetwork/PartyGames

Repository files navigation

Structure

The project is divided into two parts: the core API and the plugin for Mester Network.

Core API

The core API is located in pgame-api. It is responsible for any game-related logic, such as loading the world, keeping track of players, handling game events etc.

By itself it does not contain any minigames, they have to be registered by external plugins.

Dependencies

  • AdvancedSlimePaper for MC 1.21.11

Plugin

The plugin is located in pgame-plugin. It's the Party Games plugin for Mester Network and contains the specific minigames for that server and other non-game related logic, including a leveling system.

Dependencies

  • WorldEdit 7.3.10
  • PlaceholderAPI 2.11.6

API Usage

Including the API as dependency

To include the API as a dependency, add the following to your build.gradle.kts:

dependencies {
    compileOnly(project(":pgame-api"))
}

Or if you're working in a different project, compile the API, copy pgame-api/build/libs/pgame-api--all.jar into your project's libs folder and add it as a dependency.

dependencies {
    compileOnly(files("libs/pgame-api-<version>-all.jar"))
}

Next, add PartyGamesCore as a dependency in your paper-plugin.yml:

dependencies:
  server:
    PartyGamesCore:
      load: BEFORE
      required: true
      join-classpath: true

Registering minigames

To register a minigame, create a class that extends ˙Minigame`.

The base structure of a minigame class is as follows:

class MyMinigame(
    game: Game,
) : Minigame(game, "minigame_name")

Don't deviate from this structure, it's important for the PartyGamesCore plugin to work properly. The minigame's name can be anything you want, the convention is one word, using underscores for spaces. It is also case-insensitive so " minigame_name" and "Minigame_Name" are the same and will result in an error when both are registered.

Next, you need to override name, description and start.

name is a Component and serves as a display name for the minigame. It is shown when the minigame is about to begin.

description is also a Component and serves as a description for the minigame.

start is a function that is executed when the minigame begins. You can use it to initialize the minigame, give items to the players, summon mobs, etc.

Here is an example of a simple minigame that gives a stone to every player when the minigame begins:

class MyMinigame(
    game: Game,
) : Minigame(game, "my_minigame") {
    override fun start() {
        super.start()
        for (player in game.onlinePlayers) {
            player.inventory.addItem(Material.STONE.createItem(1))
        }
    }

    override val name = Component.text("My Minigame")
    override val description = Component.text("This is a minigame!")
}

To extend the functionality of the minigame, you can override event functions such as handlePlayerInteract or handleBlockBreak. To view a full list of events, see the Minigame class.

Listening to more events

If you want to add more events to the minigame, you can extend the Minigame class and override the event functions.

For example, you might want to listen to the BlockBreakBlockEvent. To do that, first extend the PartyGamesListener file with the new event:

@EventHandler
fun onBlockBreakBlock(event: BlockBreakBlockEvent) {
    // to access the minigame, you can use the getMinigameFromWorld function, which takes a World object and returns a nullable Minigame
    // this also means that the event you're listening to MUST have a way to get the world it's happening in
    val minigame = getMinigameFromWorld(event.block.world)
    minigame?.handleBlockBreakBlock(event) // the question mark is used to only call the function if the minigame is not null
}

Then, add this new function to the Minigame class:

open fun handleBlockBreakBlock(event: BlockBreakBlockEvent) {}

By marking the function as open, you can override it in your custom minigame class.

Registering bundles

The API makes a distinction between singular minigames and bundles. A bundle is a collection of at least one minigame, and this is what's actually playable.

To register a bundle, you first need to register your minigames.

In your plugin's onEnable function, first get the PartyGamesCore instance:

val core = PartyGamesCore.getInstance()

Then, register your minigames:

core.gameRegistry.registerMinigame(
    this, // plugin
    MyMinigame::class.qualifiedName!!, // className
    "my_minigame", // name
    listOf(
        // worlds
        MinigameWorld("my_minigame", org.bukkit.util.Vector(0.5, 63.0, 0.5)),
    ),
)

Let's break this down:

  • this is the JavaPlugin instance of your plugin.
  • MyMinigame::class.qualifiedName!! is the fully qualified name of your minigame class. (something like info.mester.network.testminigame.MyMinigame)
  • "my_minigame" is the name of your minigame. This HAS to be the same name you used in your minigame class.

The final parameter is a list of MinigameWorld objects. Each MinigameWorld object has a name and a startPos property. You can think of tese worlds as the "maps" for your minigame. So if you specify more worlds, the API will randomly pick one of them to load your minigame in, essentially providing multiple map layouts for the same minigame. The name property is the name of the AdvancedSlimePaper world for the map, and the startPos is the starting position of the minigame. This is where players will spawn when the minigame begins.

By itself, this minigame is not yet playable, as it is not part of a bundle. You can provide a registerAs parameter to this function to register the minigame as a bundle.

core.gameRegistry.registerMinigame(
    this,
    MyMinigame::class.qualifiedName!!,
    "my_minigame",
    listOf(
        MinigameWorld("my_minigame", org.bukkit.util.Vector(0.5, 63.0, 0.5)),
    ),
    "My Minigame", // registerAs
)

The registerAs parameter is the user-friendly display name for the bundle. If you use register a minigame like this, a bundle with the same name as the minigame will be created automatically.

Alternatively, you can register a bundle manually:

core.gameRegistry.registerBundle(
    this, // plugin
    listOf("my_minigame"), // minigames
    "my_bundle", // name
    "My Bundle", // displayName
)

This will create a bundle with the name "my_bundle" and use only the "my_minigame" as its minigames. This is mostly useful if you want to register a bundle that contains multiple minigames.

Starting a game

To start a game, you need to get the PartyGamesCore instance:

val core = PartyGamesCore.getInstance()

Then, you can start a game using the startGame function:

core.gameRegistry.startGame(players, "my_bundle")

The players parameter is a list of Player objects, and the bundleName parameter is the name of the bundle to start the game in.

This immediately starts the game. If the bundle contains multiple minigames, their order will be randomly selected.

The test-minigame project contains examples of how to write minigames in Kotlin and Java.

Creating the minigame worlds

Before a minigame can be started, you need to register the worlds you specified in the worlds parameter of registerMinigame with AdvancedSlimePaper.

Join the ASP server with the core plugin and your custom plugin, then for each world you want to use, run the following command:

/swm create <world name> file

This will create a new, empty world with the name you specified. The world file will be saved in <server's root> /slime_worlds/.slime

Now you can enter this world with /swm goto <world name> and start building it to your liking. The world is periodically auto-saved, but you can always manually save with /swm save <world name>. To go back to the main world, use /swm goto world.

About

Paper plugin responsible for the party games minigame

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors