Compare commits
No commits in common. "main" and "1.0.0" have entirely different histories.
13 changed files with 174 additions and 679 deletions
28
.vscode/settings.json
vendored
28
.vscode/settings.json
vendored
|
|
@ -1,28 +0,0 @@
|
|||
{
|
||||
"cSpell.words": [
|
||||
"allmaps",
|
||||
"anavoi",
|
||||
"Behaviour",
|
||||
"currentmap",
|
||||
"Dont",
|
||||
"Gaboule",
|
||||
"gamemode",
|
||||
"GBSU",
|
||||
"gmenu",
|
||||
"hlapi",
|
||||
"maplist",
|
||||
"netstandard",
|
||||
"Newtonsoft",
|
||||
"playercount",
|
||||
"protontricks",
|
||||
"rotationconfig",
|
||||
"serverip",
|
||||
"serverpassword",
|
||||
"serverport",
|
||||
"vsync",
|
||||
"winecfg",
|
||||
"WINEDLLOVERRIDES",
|
||||
"winhttp",
|
||||
"ZeroTier"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
using GB.Core;
|
||||
using GB.Networking.Utils;
|
||||
using GB.Platform.Lobby;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GBSU.Addons;
|
||||
|
||||
public class GBSUClient : MonoBehaviour
|
||||
{
|
||||
public static void JoinServer(string serverip, int serverport)
|
||||
{
|
||||
if (!Helper.hosting)
|
||||
{
|
||||
LobbyManager.Instance.LobbyStates.IP = serverip;
|
||||
LobbyManager.Instance.LobbyStates.Port = serverport;
|
||||
LobbyManager.Instance.LobbyStates.CurrentState = LobbyState.State.Ready | LobbyState.State.InGame;
|
||||
LobbyManager.Instance.LocalBeasts.SetupNetMemberContext(true);
|
||||
MonoSingleton<Global>.Instance.UNetManager.LaunchClient(serverip, serverport);
|
||||
}
|
||||
else
|
||||
{
|
||||
GBSUGui.PushError("You are currently hosting a game! Please stop your server before attempting to join.");
|
||||
}
|
||||
}
|
||||
|
||||
// this method should be used when something has went wrong
|
||||
// because players can just use the escape menu to exit
|
||||
public static void DisconnectFromServer()
|
||||
{
|
||||
GBNetUtils.DisconnectSelf(false);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using BepInEx;
|
||||
using CoreNet.Config;
|
||||
using GB.Config;
|
||||
using GB.Core;
|
||||
using GB.Game;
|
||||
using GB.Platform.Lobby;
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
|
||||
#pragma warning disable IDE0051 // Private member is unused
|
||||
|
|
@ -11,13 +14,31 @@ namespace GBSU.Addons;
|
|||
public class GBSUGui : MonoBehaviour
|
||||
{
|
||||
private bool menu_shown;
|
||||
private static bool error_shown;
|
||||
//private string _currentMap;
|
||||
public Rect gmenu = new(Screen.width / 2, 0, 385f, 690f);
|
||||
public Rect error_dialog = new(Screen.width / 2, 0, 520f, 175f);
|
||||
private static string error_msg = "Unknown error!";
|
||||
public Rect gmenu = new(Screen.width / 2, 0, 385f, 590f);
|
||||
|
||||
readonly IInputSystem inputSystem = UnityInput.Current;
|
||||
string serverip = null;
|
||||
int serverport = 0;
|
||||
string currentmap;
|
||||
string _internalCurrentState;
|
||||
Traverse _internalCurrentStateTraverse;
|
||||
int vsync_switch;
|
||||
bool hosting = false;
|
||||
private void Start()
|
||||
{
|
||||
if (CommandLineParser.Instance.KeyExists("-ip"))
|
||||
{
|
||||
serverip = CommandLineParser.Instance.GetValueForKey("-ip", true);
|
||||
}
|
||||
if (CommandLineParser.Instance.KeyExists("-port"))
|
||||
{
|
||||
int.TryParse(CommandLineParser.Instance.GetValueForKey("-port", true), out serverport);
|
||||
}
|
||||
|
||||
_internalCurrentStateTraverse = Traverse.Create(nameof(GameManagerNew)).Field("internalCurrentState");
|
||||
vsync_switch = QualitySettings.vSyncCount;
|
||||
}
|
||||
private void Update()
|
||||
{
|
||||
if (inputSystem.GetKeyDown(KeyCode.RightShift))
|
||||
|
|
@ -25,6 +46,9 @@ public class GBSUGui : MonoBehaviour
|
|||
//Plugin.Log.LogInfo("Toggling GBSU menu...");
|
||||
ToggleMenu();
|
||||
}
|
||||
|
||||
currentmap = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
|
||||
_internalCurrentState = _internalCurrentStateTraverse.GetValue() as string;
|
||||
}
|
||||
|
||||
private void ToggleMenu()
|
||||
|
|
@ -46,66 +70,53 @@ public class GBSUGui : MonoBehaviour
|
|||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||
|
||||
GUILayout.Label($@"==Guide==
|
||||
Set CLI arguments: -ip, -port (optionally -maplist)
|
||||
CLI arguments have to be set to join or host: -ip, -port, -servername, -serverpassword
|
||||
|
||||
[Hosting]
|
||||
1. Create a config in Gang Beasts_Data/Config/Rotation/config.json
|
||||
2. Press the 'Host' button while in the Main Menu
|
||||
2.Press the 'Host' button while in the Main Menu.
|
||||
|
||||
[Joining]
|
||||
1. Go to Online
|
||||
2. Press the 'Join' button");
|
||||
2. Press the 'Join' button.");
|
||||
if (GUI.Button(new Rect(320f, 10f, 55f, 30f), "KILL"))
|
||||
{
|
||||
Application.Quit(0);
|
||||
}
|
||||
if (GUI.Button(new Rect(320f, 45f, 55f, 30f), "Menu"))
|
||||
{
|
||||
Helper.SwitchToMenu();
|
||||
}
|
||||
if (Helper.serverip != null)
|
||||
if (serverip != null && serverport != default)
|
||||
{
|
||||
if (GUI.Button(new Rect(20f, 260f, 170f, 30f), "Host"))
|
||||
{
|
||||
if (LobbyManager.Instance.LobbyStates.SelfState == LobbyState.Game.Menu)
|
||||
{
|
||||
if (File.Exists(Helper.GameConfigPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
GBSUServer.StartServer();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PushError("Looks like you've caught a bug! Please send your log file to us :)\n" + e);
|
||||
GBSUServer.StopServer();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PushError(@$"No config.json could be found in {Helper.RotationFolderPath}
|
||||
Make sure to download a file from the examples given and rename it to config.json.
|
||||
{Helper.FilesInRotationDir()}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PushError("Please stay on the main menu to begin hosting. Tip: You might need to exit your lobby.");
|
||||
hosting = true;
|
||||
|
||||
AudioListener.volume = 0; // mute game audio
|
||||
|
||||
Plugin.AddServerComp(); // add custom GBSU server component
|
||||
|
||||
RotationConfig gameConfig = GBConfigLoader.LoadRotationConfig("config.json", true); // load rotation config from Config/Rotation/config.json
|
||||
ServerConfig serverConfig = NetConfigLoader.LoadServerConfig(); // load default server config, becauuse it can be overrided by args like -ip and -port
|
||||
MonoSingleton<Global>.Instance.UNetManager.LaunchServer(serverConfig); // launch the server with the server config
|
||||
MonoSingleton<Global>.Instance.UNetManager.GetComponent<GameManagerNew>().ChangeRotationConfig(gameConfig, 0); // set server's rotationconfig
|
||||
}
|
||||
}
|
||||
if (GUI.Button(new Rect(195f, 260f, 170f, 30f), "Join"))
|
||||
{
|
||||
if (LobbyManager.Instance.LobbyStates.SelfState == LobbyState.Game.Online)
|
||||
{
|
||||
GBSUClient.JoinServer(Helper.serverip, Helper.serverport);
|
||||
}
|
||||
else
|
||||
{
|
||||
PushError("Failed to join lobby! Please select the Online option in-game before joining.");
|
||||
if (!hosting && serverip != null && serverport != 0)
|
||||
{
|
||||
LobbyManager.Instance.LobbyStates.IP = serverip;
|
||||
LobbyManager.Instance.LobbyStates.Port = serverport;
|
||||
LobbyManager.Instance.LobbyStates.CurrentState = LobbyState.State.Ready | LobbyState.State.InGame;
|
||||
LobbyManager.Instance.LocalBeasts.SetupNetMemberContext(true);
|
||||
MonoSingleton<Global>.Instance.UNetManager.LaunchClient(serverip, serverport);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GUI.Button(new Rect(20f, 295f, 170f, 30f), "Cap FPS to 60"))
|
||||
{
|
||||
Application.targetFrameRate = 60;
|
||||
|
|
@ -116,49 +127,33 @@ Make sure to download a file from the examples given and rename it to config.jso
|
|||
}
|
||||
if (GUI.Button(new Rect(20f, 330f, 170f, 30f), "Toggle VSync"))
|
||||
{
|
||||
Helper.FlipVSync();
|
||||
}
|
||||
if (Helper.hosting)
|
||||
{
|
||||
if (GUI.Button(new Rect(195f, 330f, 170f, 30f), "Stop server"))
|
||||
if (vsync_switch == 0)
|
||||
{
|
||||
GBSUServer.StopServer();
|
||||
vsync_switch = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vsync_switch = 0;
|
||||
}
|
||||
|
||||
QualitySettings.vSyncCount = vsync_switch;
|
||||
}
|
||||
|
||||
GUI.Label(new Rect(20f, 365f, 365f, 400f), $@"
|
||||
|
||||
Current map: {UnityEngine.SceneManagement.SceneManager.GetActiveScene().name}
|
||||
|
||||
GUI.Label(new Rect(20f, 365f, 365f, 400f), $@"Current map: {currentmap}
|
||||
Lobby State: {LobbyManager.Instance.LobbyStates.SelfState}
|
||||
VSync: {QualitySettings.vSyncCount}
|
||||
Game State: {_internalCurrentState}
|
||||
Vsync: {QualitySettings.vSyncCount}
|
||||
Target FPS: {Application.targetFrameRate}
|
||||
{UpdateScoreDisplay()}
|
||||
|
||||
|
||||
Made with <3 by anavoi at Gaboule Community
|
||||
Free and open-source software under GPLv3.
|
||||
Our source code is available at git.gaboule.com/Gaboule/GBSU
|
||||
Please refer to the documentation for more information.");
|
||||
Made with <3 by anavoi at Gaboule Community (gaboule.com)");
|
||||
|
||||
GUI.DragWindow(new Rect(0, 0, 10000, 10000));
|
||||
}
|
||||
|
||||
private void ShowError(int window)
|
||||
{
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||
|
||||
GUILayout.Label(error_msg);
|
||||
|
||||
if (GUI.Button(new Rect(420f, 135f, 85f, 30f), "Close"))
|
||||
{
|
||||
error_shown = false;
|
||||
}
|
||||
|
||||
GUI.DragWindow(new Rect(0, 0, 10000, 10000));
|
||||
}
|
||||
private string UpdateScoreDisplay()
|
||||
{
|
||||
if (Helper.hosting)
|
||||
if (hosting)
|
||||
{
|
||||
string scoreString = "Score:\n";
|
||||
foreach (var pair in Plugin.GameScore)
|
||||
|
|
@ -170,25 +165,11 @@ Please refer to the documentation for more information.");
|
|||
return null;
|
||||
}
|
||||
|
||||
public static void PushError(string message)
|
||||
{
|
||||
Plugin.Log.LogError(message);
|
||||
|
||||
// Push this error to the UI
|
||||
error_msg = message;
|
||||
error_shown = true;
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
if (menu_shown)
|
||||
{
|
||||
gmenu = GUILayout.Window(121, gmenu, ShowOurWindow, $"{MyPluginInfo.PLUGIN_NAME} [{MyPluginInfo.PLUGIN_VERSION}]");
|
||||
}
|
||||
|
||||
if (error_shown)
|
||||
{
|
||||
error_dialog = GUILayout.Window(122, error_dialog, ShowError, "An error occurred!");
|
||||
gmenu = GUILayout.Window(121, gmenu, ShowOurWindow, $"{Plugin.PluginName} [{Plugin.PluginVersion}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,3 @@
|
|||
using CoreNet.Config;
|
||||
using GB.Config;
|
||||
using GB.Core;
|
||||
using GB.Game;
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
|
|
@ -26,45 +23,12 @@ public class GBSUServer : MonoBehaviour
|
|||
//_gmInit = AccessTools.Method(typeof(GameMode), "Init");
|
||||
localSingleGang = Traverse.Create(nameof(GameMode)).Field("localSingleGang");
|
||||
gameTimer = Traverse.Create(nameof(GameMode)).Field("timer");
|
||||
|
||||
AudioListener.volume = 0; // mute game audio
|
||||
}
|
||||
void SetLocalGangToOff()
|
||||
{
|
||||
localSingleGang?.SetValue(false);
|
||||
localSingleGang.SetValue(false);
|
||||
}
|
||||
|
||||
public static void StartServer()
|
||||
{
|
||||
if (!Helper.hosting)
|
||||
{
|
||||
Helper.hosting = true;
|
||||
|
||||
Plugin.AddServerComp(); // add custom GBSU server component
|
||||
|
||||
RotationConfig gameConfig = GBConfigLoader.LoadRotationConfig(null); // the argument doesn't matter as we do stuff in the method
|
||||
ServerConfig serverConfig = NetConfigLoader.LoadServerConfig(); // load default server config, because it can be overridden by args like -ip and -port
|
||||
MonoSingleton<Global>.Instance.UNetManager.LaunchServer(serverConfig); // launch the server with the server config
|
||||
MonoSingleton<Global>.Instance.UNetManager.GetComponent<GameManagerNew>().ChangeRotationConfig(gameConfig, 0); // set server's rotationconfig
|
||||
}
|
||||
}
|
||||
|
||||
public static void StopServer()
|
||||
{
|
||||
// WIP: At the moment the only way to stop the server is to exit/kill the game
|
||||
Helper.hosting = false;
|
||||
|
||||
AudioListener.volume = Helper.saved_volume; // restore volume
|
||||
|
||||
// stop network listener
|
||||
MonoSingleton<Global>.Instance.UNetManager.StopServer();
|
||||
|
||||
// destroy GBSU server comp
|
||||
Plugin.DestroyServerComp();
|
||||
|
||||
// go back to main menu
|
||||
Helper.SwitchToMenu();
|
||||
}
|
||||
/*
|
||||
public string GetRemainingRoundTime()
|
||||
{
|
||||
|
|
|
|||
102
Addons/Helper.cs
102
Addons/Helper.cs
|
|
@ -1,21 +1,9 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using GB.Core;
|
||||
using GB.Networking.Utils;
|
||||
using GB.Platform.Lobby;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Analytics;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace GBSU.Addons;
|
||||
public class Helper
|
||||
{
|
||||
public static string RotationFolderPath = BepInEx.Paths.BepInExRootPath + "/config/GBSU/";
|
||||
public static string GameConfigPath = RotationFolderPath + "config.json";
|
||||
public static string serverip = null;
|
||||
public static int serverport = 5999;
|
||||
public static bool hosting = false;
|
||||
public static float saved_volume;
|
||||
public static void DisableAnalytics()
|
||||
{
|
||||
// Try disabling analytics https://docs.unity3d.com/ScriptReference/Analytics.Analytics-deviceStatsEnabled.html
|
||||
|
|
@ -26,93 +14,7 @@ public class Helper
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Plugin.Log.LogWarning("Failed to disable analytics: " + e.Message);
|
||||
Plugin.Log.LogInfo("Failed to disable analytics: " + e.Message);
|
||||
}
|
||||
}
|
||||
public static void CreateRotationFolder()
|
||||
{
|
||||
try
|
||||
{
|
||||
Plugin.Log.LogInfo("Creating rotation folder at " + RotationFolderPath);
|
||||
Directory.CreateDirectory(RotationFolderPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Plugin.Log.LogError("Could not create rotation folder path: " + e.Message);
|
||||
}
|
||||
}
|
||||
public static string FilesInRotationDir()
|
||||
{
|
||||
// https://stackoverflow.com/a/14877330
|
||||
DirectoryInfo d = new(RotationFolderPath);
|
||||
FileInfo[] files = d.GetFiles();
|
||||
int number = files.Length;
|
||||
|
||||
// no files?
|
||||
if (number == 0)
|
||||
{
|
||||
return @"No files were found in the directory.";
|
||||
}
|
||||
else
|
||||
{
|
||||
string names = "";
|
||||
|
||||
foreach (FileInfo file in files)
|
||||
{
|
||||
names = file.Name + " " + names;
|
||||
}
|
||||
|
||||
return $"There are {number} files: {names}";
|
||||
}
|
||||
}
|
||||
|
||||
public static void FlipVSync()
|
||||
{
|
||||
if (QualitySettings.vSyncCount == 0)
|
||||
{
|
||||
QualitySettings.vSyncCount = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
QualitySettings.vSyncCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static void CheckCustomRotationPath()
|
||||
{
|
||||
// Did the host request to use their own rotation config path?
|
||||
if (CommandLineParser.Instance.KeyExists("-maplist"))
|
||||
{
|
||||
GameConfigPath = CommandLineParser.Instance.GetValueForKey("-maplist");
|
||||
Plugin.Log.LogInfo("Set custom rotation config path at " + GameConfigPath);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SwitchToMenu()
|
||||
{
|
||||
if (hosting)
|
||||
{
|
||||
GBSUGui.PushError("Please press the Stop server button instead!");
|
||||
}
|
||||
else
|
||||
{
|
||||
// uhm, time to panic!
|
||||
|
||||
// let's begin by disconnecting if theres an active connection
|
||||
try
|
||||
{
|
||||
GBNetUtils.DisconnectSelf(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Plugin.Log.LogWarning("Couldn't disconnect from server:\n" + e);
|
||||
}
|
||||
|
||||
// go back to main menu
|
||||
SceneManager.LoadScene(Global.MENU_SCENE_NAME);
|
||||
|
||||
// make sure our lobby state is menu
|
||||
LobbyManager.Instance.LobbyStates.SelfState = LobbyState.Game.Menu;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<AssemblyName>GBSU</AssemblyName>
|
||||
<Product>Gang Beasts Server Utility</Product>
|
||||
<Version>1.1.0</Version>
|
||||
<Version>1.0.0</Version>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<RestoreAdditionalProjectSources>
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
<PackageReference Include="BepInEx.PluginInfoProps" Version="2.*" />
|
||||
<PackageReference Include="UnityEngine.Modules" Version="2020.3.5" IncludeAssets="compile" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.2" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
|
@ -42,8 +42,5 @@
|
|||
<Reference Include="UnityEngine.CoreModule">
|
||||
<HintPath>ref/UnityEngine.CoreModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json.dll">
|
||||
<HintPath>ref/Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using GB.Config;
|
||||
using GBSU.Addons;
|
||||
using HarmonyLib;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GBSU.Patches;
|
||||
|
||||
[HarmonyPatch]
|
||||
class ConfigLoaderPatch
|
||||
{
|
||||
[HarmonyPatch(typeof(GBConfigLoader), "LoadRotationConfig")]
|
||||
private static bool Prefix(ref RotationConfig __result)
|
||||
{
|
||||
string text = ""; // contents of file
|
||||
|
||||
Plugin.Log.LogInfo("Loading custom rotation config...");
|
||||
|
||||
// Reading from file
|
||||
try
|
||||
{
|
||||
text = File.ReadAllText(Helper.GameConfigPath);
|
||||
Plugin.Log.LogDebug("Provided rotation config:\n" + text);
|
||||
RotationConfig rc = JsonConvert.DeserializeObject<RotationConfig>(text);
|
||||
__result = rc;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
GBSUGui.PushError("Couldn't read game config file. A few details:\n" + e);
|
||||
}
|
||||
|
||||
return false; // skip
|
||||
}
|
||||
}
|
||||
|
|
@ -50,6 +50,7 @@ class HandleScorePatch
|
|||
Plugin.Log.LogDebug("Done processing all scores!");
|
||||
}
|
||||
|
||||
Plugin.Log.LogInfo("Not letting HandleScore run...");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
179
Plugin.cs
179
Plugin.cs
|
|
@ -1,108 +1,71 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using BepInEx;
|
||||
using BepInEx.Logging;
|
||||
using GBSU.Addons;
|
||||
using HarmonyLib;
|
||||
using HarmonyLib.Tools;
|
||||
using UnityEngine;
|
||||
|
||||
#pragma warning disable IDE0051 // Private member is unused
|
||||
|
||||
namespace GBSU;
|
||||
|
||||
[BepInPlugin(MyPluginInfo.PLUGIN_GUID, MyPluginInfo.PLUGIN_NAME, MyPluginInfo.PLUGIN_VERSION)]
|
||||
[BepInProcess("Gang Beasts.exe")]
|
||||
public class Plugin : BaseUnityPlugin
|
||||
{
|
||||
public static Dictionary<string, int> GameScore = [];
|
||||
private static GameObject _gbsuCompContainer;
|
||||
internal static ManualLogSource Log;
|
||||
|
||||
public static GameObject GBSUCompContainer
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_gbsuCompContainer == null)
|
||||
{
|
||||
_gbsuCompContainer = new GameObject("GBSUSingletons");
|
||||
}
|
||||
|
||||
return _gbsuCompContainer;
|
||||
}
|
||||
set
|
||||
{
|
||||
Destroy(_gbsuCompContainer);
|
||||
_gbsuCompContainer = value;
|
||||
}
|
||||
}
|
||||
private void Awake()
|
||||
{
|
||||
// Plugin startup logic
|
||||
Log = base.Logger;
|
||||
Log.LogInfo($"\n------\nPlugin {MyPluginInfo.PLUGIN_NAME} [{MyPluginInfo.PLUGIN_VERSION}] is loaded!\n------\n");
|
||||
|
||||
HarmonyFileLog.Enabled = true;
|
||||
var harmony = new Harmony(MyPluginInfo.PLUGIN_GUID);
|
||||
harmony.PatchAll(Assembly.GetExecutingAssembly());
|
||||
|
||||
GBSUCompInit();
|
||||
|
||||
Helper.DisableAnalytics(); // thank me later
|
||||
|
||||
// create server config path
|
||||
Helper.CreateRotationFolder();
|
||||
|
||||
Log.LogDebug("Server game config should be found at " + Helper.GameConfigPath);
|
||||
|
||||
// Parse CLI arguments
|
||||
if (CommandLineParser.Instance.KeyExists("-ip"))
|
||||
{
|
||||
Helper.serverip = CommandLineParser.Instance.GetValueForKey("-ip", false);
|
||||
}
|
||||
else
|
||||
{
|
||||
GBSUGui.PushError("Couldn't find the -ip CLI argument. Please refer to the documentation.");
|
||||
}
|
||||
if (CommandLineParser.Instance.KeyExists("-port"))
|
||||
{
|
||||
int.TryParse(CommandLineParser.Instance.GetValueForKey("-port", false), out Helper.serverport);
|
||||
}
|
||||
|
||||
// "-maplist" CLI
|
||||
Helper.CheckCustomRotationPath();
|
||||
|
||||
// store app volume in a variable to restore it if needed
|
||||
Helper.saved_volume = AudioListener.volume;
|
||||
}
|
||||
|
||||
private static void GBSUCompInit()
|
||||
{
|
||||
// Create a container that wont lose our objects
|
||||
GBSUCompContainer = new GameObject("GBSUSingletons");
|
||||
DontDestroyOnLoad(GBSUCompContainer);
|
||||
GBSUCompContainer.hideFlags = HideFlags.DontUnloadUnusedAsset;
|
||||
GBSUCompContainer.AddComponent<GBSUGui>();
|
||||
}
|
||||
|
||||
public static void AddServerComp()
|
||||
{
|
||||
DestroyServerComp();
|
||||
Log.LogDebug("Adding GBSUServer component");
|
||||
GBSUCompContainer.AddComponent<GBSUServer>();
|
||||
}
|
||||
|
||||
public static void DestroyServerComp()
|
||||
{
|
||||
Component[] comps = GBSUCompContainer.GetComponents(typeof(Component));
|
||||
foreach (var comp in comps)
|
||||
{
|
||||
Log.LogDebug("iterating thru singleton comps");
|
||||
if (comp is GBSUServer)
|
||||
{
|
||||
Log.LogDebug("GBSUServer component was found! Destroying it");
|
||||
Destroy(comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using BepInEx;
|
||||
using BepInEx.Logging;
|
||||
using GBSU.Addons;
|
||||
using HarmonyLib;
|
||||
using HarmonyLib.Tools;
|
||||
using UnityEngine;
|
||||
|
||||
#pragma warning disable IDE0051 // Private member is unused
|
||||
|
||||
namespace GBSU;
|
||||
|
||||
[BepInPlugin(PluginGUID, PluginName, PluginVersion)]
|
||||
[BepInProcess("Gang Beasts.exe")]
|
||||
public class Plugin : BaseUnityPlugin
|
||||
{
|
||||
public static Dictionary<string, int> GameScore = [];
|
||||
private static GameObject _gbsuCompContainer;
|
||||
internal static ManualLogSource Log;
|
||||
|
||||
public static GameObject GBSUCompContainer
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_gbsuCompContainer == null)
|
||||
{
|
||||
_gbsuCompContainer = new GameObject("GBSUSingletons");
|
||||
}
|
||||
|
||||
return _gbsuCompContainer;
|
||||
}
|
||||
set
|
||||
{
|
||||
Destroy(_gbsuCompContainer);
|
||||
_gbsuCompContainer = value;
|
||||
}
|
||||
}
|
||||
private void Awake()
|
||||
{
|
||||
// Plugin startup logic
|
||||
Log = base.Logger;
|
||||
Log.LogInfo($"\n------\nPlugin {PluginName} [{PluginVersion}] is loaded!\n------\n");
|
||||
|
||||
HarmonyFileLog.Enabled = true;
|
||||
var harmony = new Harmony(PluginGUID);
|
||||
harmony.PatchAll(Assembly.GetExecutingAssembly());
|
||||
|
||||
GBSUCompInit();
|
||||
|
||||
Helper.DisableAnalytics(); // thank me later
|
||||
}
|
||||
|
||||
private static void GBSUCompInit()
|
||||
{
|
||||
// Create a container that wont lose our objects
|
||||
GBSUCompContainer = new GameObject("GBSUSingletons");
|
||||
DontDestroyOnLoad(GBSUCompContainer);
|
||||
GBSUCompContainer.hideFlags = HideFlags.DontUnloadUnusedAsset;
|
||||
GBSUCompContainer.AddComponent<GBSUGui>();
|
||||
}
|
||||
|
||||
public static void AddServerComp()
|
||||
{
|
||||
GBSUCompContainer.AddComponent<GBSUServer>();
|
||||
}
|
||||
|
||||
public const string PluginGUID = "com.gaboule.plugins.gbsu";
|
||||
public const string PluginName = "Gang Beasts Server Utility";
|
||||
public const string PluginVersion = "1.0.0";
|
||||
}
|
||||
|
|
|
|||
67
README.md
67
README.md
|
|
@ -1,55 +1,55 @@
|
|||
# GBSU (Gang Beasts Server Utility)
|
||||
This mod allows you to connect to a Gang Beasts server in recent versions (through LAN or Internet) by utilizing developer methods found in the game assembly.
|
||||
This mod allows you to connect to a Gang Beast server in recent versions (through LAN or Internet) by utilizing developer methods found in the game assembly.
|
||||
|
||||
**NOTICE: This is not a "Cement" mod, and we don't want to be affiliated with their developers. This mod is standalone, and will work best on its own!**
|
||||
|
||||
# Features
|
||||
- LAN (Ethernet switches at LAN parties) and Online (port forwarding, ZeroTier, Wireguard) multiplayer
|
||||
- LAN (ethernet switches at LAN parties) and Online (port forwarding, Zerotier, Wireguard) multiplayer
|
||||
- Custom score handling made by the server (we don't want to use the game's score handler)
|
||||
|
||||
# Installation
|
||||
1. Check your game version in the "Settings" menu in-game. If the version is **1.17.39_WS_8af7688**, we fully support it.
|
||||
2. Check whether your game is Mono or IL2CPP: Go to 'Gang Beasts_Data'
|
||||
- If you have a folder called `MonoBleedingEdge` or the `Gang Beasts_Data/Managed` folder contains a file called 'Assembly-CSharp.dll': your game is **Mono**. Continue to [Mono instructions](#mono).
|
||||
- If you have a il2cpp_data folder: your game is **IL2CPP**. Continue to [IL2CPP instructions](#il2cpp).
|
||||
The mod is made for the game version **1.17.39_WS_8af7688** running on Unity **v2020.3.5.8426922** (check your version in the Settings menu in-game)
|
||||
Other versions *MIGHT* work with the mod. Try at your own risk.*
|
||||
|
||||
1. Check whether your game is Mono or IL2CPP: Go to 'Gang Beasts_Data'
|
||||
- If you have a il2cpp_data folder: your game is **IL2CPP**
|
||||
- If you have a folder called `MonoBleedingEdge` or the `Gang Beasts_Data/Managed` folder contains a file called 'Assembly-CSharp.dll': your game is **Mono**
|
||||
|
||||
2. **Follow the instructions based on the game type:**
|
||||
|
||||
## Mono
|
||||
1. [Download the latest **BepInEx 5 stable** release for Mono x64](https://github.com/BepInEx/BepInEx/releases). As of March 2025, we recommend getting `BepInEx_win_x64_5.4.23.2.zip`
|
||||
2. Extract the zip file contents into your root game folder (where the Gang Beasts.exe file is, and not in the 'Gang Beasts_Data' folder!)
|
||||
Go to https://github.com/BepInEx/BepInEx/releases and get the latest stable release for Mono x64 (on Windows).
|
||||
|
||||
1. As of March 2025, what we recommend doing is getting `BepInEx_win_x64_5.4.23.2.zip`.
|
||||
2. Extract the zip file contents into your root game folder (not in the 'Gang Beasts_Data' folder!)
|
||||
3. Launch the game once.
|
||||
4. Get the mod from our [releases page](https://git.gaboule.com/Gaboule/GBSU/releases).
|
||||
4. Get the mod from our releases page.
|
||||
5. Put the .dll file in the `BepInEx/plugins` folder.
|
||||
6. Launch the game with launch arguments `-ip 1.2.3.4` and `-port 5999` with the IP address and port of the server you want to host or connect to.
|
||||
- To set those arguments on Steam, [please refer to this guide](https://help.steampowered.com/en/faqs/view/7D01-D2DD-D75E-2955).
|
||||
7. You're good to go! Learn how to use the mod in [usage](#usage).
|
||||
7. You're good to go! Learn how to use the mod in [usage](#usage)
|
||||
|
||||
## IL2CPP
|
||||
**WIP**: You're currently out of luck! The mod doesn't support your game version at the moment. It will be ported to MelonLoader in the future. Try downgrading your game by getting older versions in Steam Betas or by using [DepotDownloader](https://github.com/SteamRE/DepotDownloader).
|
||||
**WIP**: The mod will be ported to MelonLoader and recent game versions in the future.
|
||||
|
||||
# Usage
|
||||
Press `Right Shift` to open the mod GUI. Because of how the game is made, you need to be very careful when executing the steps else you will need to restart it. (will be fixed in future versions)
|
||||
|
||||
## Server (host)
|
||||
### Setting up the server
|
||||
1. Open the `BepInEx` folder in the "server" game instance files.
|
||||
2. Create a `GBSU` folder in `config`.
|
||||
3. Download the [one of the config files](https://git.gaboule.com/Gaboule/GBSU/src/branch/main/docs/configs) and place it inside the `GBSU` folder.
|
||||
4. Rename the file to `config.json`
|
||||
|
||||
**Tip: your config file can also be anywhere else! Use the -maplist argument followed by the path to the file,** for example `-ip 192.168.1.2 -port 5999 -maplist "/home/user/mycustomconfig.json"`
|
||||
|
||||
### Configuring your custom server settings
|
||||
* If you set `"random": true`, the map order will be randomized.
|
||||
* Some maps may have different names in-game compared to their actual titles. Make sure to refer to the [`allmaps` configs](https://git.gaboule.com/Gaboule/GBSU/src/branch/main/docs/configs) for the map names.
|
||||
|
||||
### Launching the server
|
||||
Once the config file is in place, host your server by pressing the **Host** button in the mod menu. Don't pay attention to what's displayed on the game. It will be an infinite loading screen after the first round.
|
||||
1. Open the mod menu and press **Host** while you're in the main menu.
|
||||
2. Don't pay attention to what's displayed on the game. It will be an infinite loading screen after the first round.
|
||||
|
||||
## Client (player)
|
||||
1. In the game menu, choose **Online**.
|
||||
2. If you're planning to team up with friends, make sure your server config is set to the `gang` gamemode and choose a shared color. Otherwise, use a different color than your friends.
|
||||
2. Make sure to use a different color than your friends.
|
||||
3. Open the mod menu and press **Join**.
|
||||
|
||||
# Known Issues
|
||||
- Scores tab on the server is expected be wrong. This is a temporary implementation and the scores will be reworked.
|
||||
- The server is not headless.
|
||||
- If you want to play on your server, you need to launch a different game instance. It is not possible to connect to the server after launching it at the moment.
|
||||
- Getting the current scene isn't the most efficient way at the moment.
|
||||
|
||||
|
||||
# Troubleshooting
|
||||
## I press the Host/Join button and nothing works!
|
||||
1. Make sure you're in Online mode if you're **joining** a server.
|
||||
|
|
@ -64,19 +64,8 @@ On Steam, simply put `WINEDLLOVERRIDES="winhttp.dll=n,b" %command%` in your laun
|
|||
|
||||
If it's still not working, try using `winecfg` for your prefix or `protontricks` and go to the libraries tab in Wine Configuration. Simply add `winhttp` as an override and check if it's correctly set as "native, then builtin" (or "n,b").
|
||||
|
||||
# Known issues
|
||||
- This mode uses the game's netcode. It is poorly made, and you get noticeable latency on localhost (RTT is 10ms). It seems that there's no client-side prediction.
|
||||
- The custom score handler only tracks through colors, and is only visible on the host side.
|
||||
|
||||
# Contact us
|
||||
## Need help?
|
||||
Ask us on [Matrix](https://matrix.to/#/#gbsu:gaboule.com).
|
||||
|
||||
## Feature requests or bug reports
|
||||
Want a new feature? Found a bug? [Open an issue!](https://git.gaboule.com/Gaboule/GBSU/issues) Please note that a Gaboule account is currently required. This will change once Forgejo supports federation. Alternatively, feel free to reach out to us for general feedback or questions.
|
||||
|
||||
# Developer information
|
||||
- The mod is made for BepInEx 5
|
||||
- The targeted Unity version is `2020.3.5f1`
|
||||
- The TFM is `netstandard2.0`
|
||||
- The mod is built using .NET SDK `9.0.304`
|
||||
- The mod is built using .NET SDK `9.0.103`
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
{
|
||||
"random": true,
|
||||
"games": [
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "rooftop"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "ring"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "blimp"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "containers"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "elevators"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "girders"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "gondola"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "grind"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "incinerator"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "ring"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "towers"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "train"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "trucks"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "aquarium"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "billboard"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "buoy"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "chute"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "billboard"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "lighthouse"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "subway"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "vents"
|
||||
},
|
||||
{
|
||||
"mode": "gang",
|
||||
"map": "wheel"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
{
|
||||
"random": true,
|
||||
"games": [
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "rooftop"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "ring"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "blimp"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "containers"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "elevators"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "girders"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "gondola"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "grind"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "incinerator"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "ring"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "towers"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "train"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "trucks"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "aquarium"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "billboard"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "buoy"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "chute"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "billboard"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "lighthouse"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "subway"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "vents"
|
||||
},
|
||||
{
|
||||
"mode": "melee",
|
||||
"map": "wheel"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"random": true,
|
||||
"games": [
|
||||
{
|
||||
"mode": "waves",
|
||||
"map": "rooftop"
|
||||
},
|
||||
{
|
||||
"mode": "waves",
|
||||
"map": "incinerator"
|
||||
},
|
||||
{
|
||||
"mode": "waves",
|
||||
"map": "subway"
|
||||
},
|
||||
{
|
||||
"mode": "waves",
|
||||
"map": "grind"
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue