Skip to content

Commit

Permalink
Example: FailOnSaberClash
Browse files Browse the repository at this point in the history
  • Loading branch information
Auros committed Oct 26, 2021
1 parent 43efeef commit b09f963
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 21 deletions.
12 changes: 0 additions & 12 deletions [1] FailOnSaberClash/Installers/FailOnSaberClashCoreInstaller.cs

This file was deleted.

21 changes: 21 additions & 0 deletions [1] FailOnSaberClash/Installers/FailPlayerInstaller.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using FailOnSaberClash.Managers;
using Zenject;

namespace FailOnSaberClash.Installers
{
// This is our installer. It is one of the ways we can communicate to Zenject what to run and how to instantiate our classes.
internal class FailPlayerInstaller : Installer
{
public override void InstallBindings()
{
// We are registering our manager class so it can work when the player is in a level. Let's break down what's happening here.

// Container | We access the current container. This is defined in one of the base classes that Installer inherits.
// BindInterfacesTo<ClashFailManager> | We tell the container to bind the type (ClashFailManager)'s interfaces (ITickable) to the container.
// Zenject now knows that it's an ITickable and will call it's Tick method, allowing us to run code every frame.
// AsSingle() | This registers it as a single instance inside this container. Meaning, you can ensure that only one of this object will exist at a time.

Container.BindInterfacesTo<ClashFailManager>().AsSingle();
}
}
}
39 changes: 39 additions & 0 deletions [1] FailOnSaberClash/Managers/ClashFailManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using UnityEngine;
using Zenject;

namespace FailOnSaberClash.Managers
{
// We inherit ITickable so we can process stuff each frame. This is very similar to the player loop Update()
// method in Unity, and they should be treated similarly.
internal class ClashFailManager : ITickable
{
private readonly SaberClashChecker _saberClashChecker;
private readonly StandardLevelGameplayManager _standardLevelGameplayManager;

// The SaberClashChecker is a class the base game uses to... well... detect saber clashes. By putting it in the constructor
// of this class, we are saying that this class has a dependency on the SaberClashChecker. Zenject recognizes this and when instantiating
// our class, will fill all the dependencies in the constructor. To get a list of dependencies from the base game that you can use, go to https://container.project-sira.tech
//
// The same logic above can be applied to the StandardLevelGameplayManager
public ClashFailManager(SaberClashChecker saberClashChecker, StandardLevelGameplayManager standardLevelGameplayManager)
{
// We store the SaberClashChecker and StandardLevelGameplayManager in their own private variable within our class so we can use them elsewhere.
_saberClashChecker = saberClashChecker;
_standardLevelGameplayManager = standardLevelGameplayManager;
}

// This method gets called every frame. Similar to Update(), you shouldn't do expensive operations inside of this method.
public void Tick()
{
// This is where we check to see if the sabers are clashing. The base game uses this method to calculate where
// to spawn the sparkle effects. We can ALSO use it to fail the level when they class.
if (_saberClashChecker.AreSabersClashing(out Vector3 _))
{
// We want to emulate what happens when you fail a level, so
// we call a method which triggers the level failed sequence.
_standardLevelGameplayManager.HandleGameEnergyDidReach0();
}
}
}
}
8 changes: 4 additions & 4 deletions [1] FailOnSaberClash/Plugin.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
using FailOnSaberClash.Installers;
using IPA;
using SiraUtil.Zenject;
using IPALogger = IPA.Logging.Logger;

namespace FailOnSaberClash
{
[Plugin(RuntimeOptions.DynamicInit)]
public class Plugin
{
[Init]
public Plugin(IPALogger logger, Zenjector zenjector)
public Plugin(Zenjector zenjector)
{
zenjector.UseLogger(logger);
zenjector.Install<FailOnSaberClashCoreInstaller>(Location.App);
// We will install it into the Standard Player (Solo and Party mode).
// We don't want to touch campaigns, multiplayer, or the tutorial.
zenjector.Install<FailPlayerInstaller>(Location.StandardPlayer);
}
}
}
13 changes: 13 additions & 0 deletions [1] FailOnSaberClash/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Fail on Saber Clash

Complexity: Simple

Made on Beat Saber Version: 1.18.2

Made on SiraUtil Version: 3.0.0

Authored by: [Auros](https://github.com/Auros)

## Description

This tutorial goes over the very basic example of how you can leverage using Zenject within a Beat Saber mod. This mod/example causes the current player to fail the level when their sabers "clash" (touch each other).
11 changes: 6 additions & 5 deletions [1] FailOnSaberClash/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
"$schema": "https://raw.githubusercontent.com/bsmg/BSIPA-MetadataFileSchema/master/Schema.json",
"id": "FailOnSaberClash",
"name": "FailOnSaberClash",
"author": "auros",
"version": "3.0.0",
"description": "",
"gameVersion": "1.18.1",
"author": "SIRA",
"version": "1.0.0",
"description": "Fails the level when the sabers touch.",
"gameVersion": "1.18.2",
"dependsOn": {
"BSIPA": "^4.2.0"
"BSIPA": "^4.2.0",
"SiraUtil": "^3.0.0"
}
}

0 comments on commit b09f963

Please sign in to comment.