Skip to content

Latest commit

 

History

History
347 lines (263 loc) · 16.4 KB

USAGE.md

File metadata and controls

347 lines (263 loc) · 16.4 KB

Introduction

This repository consists of several Java libraries. Most of which are intended for use by other Java software. They are available in the Maven Central Repositories which allows for easily importing the library into your build automation software of choice.

Tip: GitHub has a handy Table of Contents feature available by clicking the list icon on the top left of this document.

Logging

The libraries maintained in this repository utilize the SLF4J logging framework. It provides no logging implementation by default, meaning that logs will be silently ignored. To enable logging, you must add a logging implementation to your class path which is typically done by adding the implementation to your project's dependencies in Maven or Gradle. Popular implementations include Logback, log4j2, slf4j-simple, and SLF4J's adapter for the built-in java.util.logging framework.

Receiver javadoc

The Receiver library is the main library of the project. It allows your video game (or modification) to receive effect requests from a streamer using the Crowd Control desktop application. The set of effects supported by your game is known as your "Effect Pack." Effect packs are written in C# and loaded into the Crowd Control desktop app. The desktop app then communicates with your game which receives messages through the receiver library.

Testing of effect packs is generally performed using the Crowd Control SDK.

Installation

Maven

Add to the dependencies section of your pom.xml file:

<dependency>
    <groupId>dev.qixils.crowdcontrol</groupId>
    <artifactId>crowd-control-receiver</artifactId>
    <version>3.9.1</version>
</dependency>
Gradle

Add to the dependencies section of your build.gradle file:

compileOnly 'dev.qixils.crowdcontrol:crowd-control-receiver:3.9.1'

Or, if using Kotlin (build.gradle.kts):

compileOnly("dev.qixils.crowdcontrol:crowd-control-receiver:3.9.1")

Usage

To start, you must create a CrowdControl class using one of the two builder methods. This differs depending on which Crowd Control connection type you wish to use. The two connection types are outlined below.

You will also need to create a .cs file which holds a list of all of your available effects as well as information about how the Crowd Control desktop app should connect to your application. Example files for each connector type are provided below.

Client Mode

This builder corresponds with the default SimpleTCPConnector used by Crowd Control. In this mode, the library runs as a client, meaning it receives commands from a central server that it connects to. This central server is (usually) the streamer's Crowd Control desktop application running on a local port.

To use this connector type, use the Crowd Control client builder:

import dev.qixils.crowdcontrol.CrowdControl;
// [...]
String ip = this.getIP(); // this should ideally be configurable by the streamer
CrowdControl crowdControl = CrowdControl.client()
        .ip(ip)
        .port(58429) // this should match what's in your .cs file
        .build();

You must also use the SimpleTCPConnector type inside your effect pack's C# file that gets loaded into the Crowd Control app. Example:

using System;
using System.Collections.Generic;
using CrowdControl.Common;

namespace CrowdControl.Games.Packs
{
    public class VideoGameNameHere : SimpleTCPPack
    {
        public override string Host => "127.0.0.1";

        public override ushort Port => 58429;

        public VideoGameNameHere(IPlayer player, Func<CrowdControlBlock, bool> responseHandler, Action<object> statusUpdateHandler) : base(player, responseHandler, statusUpdateHandler) { }

        // The first three fields of the Game constructor will be assigned to you by the Crowd Control staff.
        // For more information, join the Discord server: https://discord.gg/DhnfpEqmtn
        public override Game Game => new Game(999, "Video Game Name Here", "VideoGameNameHere", "PC", ConnectorType.SimpleTCPConnector);

        // Define all effects used in your effect pack here
        public override List<Effect> Effects => new List<Effect>
        {
            // define "Miscellaneous" folder of effects
            new Effect("Miscellaneous", "miscellaneous", ItemKind.Folder),

            // define effects inside this folder
            new Effect("Display Name 1", "effect_key_1", "miscellaneous"),
            new Effect("Display Name 2", "effect_key_2", "miscellaneous"),
        };
    }
}

Server Mode

This builder corresponds with the SimpleTCPClientConnector. In this mode, the library runs as a server, meaning it can establish connections with multiple clients (streamers) and process effects for each streamer individually. This may be ideal for multiplayer game servers like Minecraft.

To use this connector type, use the Crowd Control server builder:

import dev.qixils.crowdcontrol.CrowdControl;
// [...]
String password = this.getPassword(); // this should ideally be configurable by the server host
CrowdControl crowdControl = CrowdControl.server()
        .password(password)
        .port(58429) // this should match what's in your .cs file
        .build();

You must also define several variables inside your effect pack's C# file that gets loaded into the Crowd Control app. Example:

using System;
using System.Collections.Generic;
using ConnectorLib;
using CrowdControl.Common;
using CrowdControl.Games.Packs;
using ConnectorType = CrowdControl.Common.ConnectorType;

namespace CrowdControl.Games.Packs
{
    public class VideoGameNameHere : SimpleTCPPack<SimpleTCPClientConnector>
    {
        public override string Host => "127.0.0.1";

        public override ushort Port => 58429;

        public override ISimpleTCPPack.AuthenticationType AuthenticationMode => ISimpleTCPPack.AuthenticationType.SimpleTCPSendKey;

        public override ISimpleTCPPack.DigestAlgorithm AuthenticationHashMode => ISimpleTCPPack.DigestAlgorithm.SHA_512;

        public VideoGameNameHere(IPlayer player, Func<CrowdControlBlock, bool> responseHandler, Action<object> statusUpdateHandler) : base(player, responseHandler, statusUpdateHandler) { }

        // The first three fields of the Game constructor will be assigned to you by the Crowd Control staff.
        // For more information, join the Discord server: https://discord.gg/DhnfpEqmtn
        public override Game Game => new Game(999, "Video Game Name Here", "VideoGameNameHere", "PC", ConnectorType.SimpleTCPClientConnector);

        // Define all effects used in your effect pack here
        public override List<Effect> Effects => new List<Effect>
        {
            // define "Miscellaneous" folder of effects
            new Effect("Miscellaneous", "miscellaneous", ItemKind.Folder),

            // define effects inside this folder
            new Effect("Display Name 1", "effect_key_1", "miscellaneous"),
            new Effect("Display Name 2", "effect_key_2", "miscellaneous"),
        };
    }
}

General Usage

Once you've created your CrowdControl instance, you can start registering handlers for each of your effects.

Registering Individual Handlers

Two overloaded methods are provided for registering an effect handler. You can either provide a Function<Request,Response> which is a function that takes in a Request and returns a Response, or a Consumer<Request> which takes in a Request and returns nothing. As these functions are called on an asynchronous thread, the latter is usually used for effects that require an action to be run on the main thread. It is expected that Consumer<Request> handlers will eventually call Response#send to manually issue a Response to the requesting client.

Registering Handler Classes

Those who prefer working with annotated methods can use #registerHandlers(Object) to automatically register effect handlers for every appropriately annotated method inside a class. All methods that are annotated with @Subscribe; return Response, Response.Builder, or Void (for synchronous effects that will manually call Response#send); have a single parameter that accepts only Request; and are public will be registered as effect handlers.

For more information, please view the method's javadocs.

Registering Checks

Checks are functions that are called every time a Request is received which may or may not have knowledge of the Request. They are used to prevent the execution of effects if your game has not yet loaded or if your players have not yet connected. These can be registered using #registerCheck(Supplier<CheckResult>) and #registerCheck(Function<Request,CheckResult>)

Further Reading

The documentation for all classes and methods may be found here.

Example

An example project integrating the receiver library can be found here.

Sender javadoc

The Sender library allows you to simulate the Crowd Control desktop application by sending effect requests to a video game server or clients. This was primarily developed as an internal tool to test the Receiver library, though it can be used for numerous other applications.

Installation

Maven

Add to the dependencies section of your pom.xml file:

<dependency>
    <groupId>dev.qixils.crowdcontrol</groupId>
    <artifactId>crowd-control-sender</artifactId>
    <version>3.9.1</version>
</dependency>
Gradle

Add to the dependencies section of your build.gradle file:

compileOnly 'dev.qixils.crowdcontrol:crowd-control-sender:3.9.1'

Or, if using Kotlin (build.gradle.kts):

compileOnly("dev.qixils.crowdcontrol:crowd-control-sender:3.9.1")

Usage

This section assumes you have read the above documentation for the Receiver library and are familiar with the two different types of TCP connectors.

To create a server for the SimpleTCPConnector, you should instantiate a new SimulatedServer. For creating a client (or several) for the SimpleTCPClientConnector, you should instantiate a new SimulatedClient. Both of these classes implement StartableService which holds all the important methods for working with these simulated services.

To start the service, you must call the #start method on your service. For clients, you may call the #autoStart method to automatically reconnect to the server when the connection is lost.

Requests may be dispatched to connected services using the #sendRequest method. For the server, this will return a Flux of Fluxes of Responses which correspond to the Responses received from the connected clients. The client will return a single Flux of Responses.

The Response Fluxes will emit a Response each time one corresponding to the Request is received from the connected service, and it will complete upon a Response indicating that the effect has finished executing. It may also error if the effect times out or the connected service disconnects before completion.

Before sending Requests, you should ensure that the effect being requested is known to be available by checking the result of #isEffectAvailable. If the server states that an effect does not exist, then it will be marked as unavailable and the #sendRequest method will throw an EffectUnavailableException if you try to use it.

Further Reading

The documentation for all classes and methods may be found here.