- Fixed toggling time running mode - Fixed closing popups - Added support for pressing the buttons on a popup - Added error handling to Main.Init() - Automatically closing the beta message in the test plugin - Fixed Game.EnterGame() causing a crash in the game
209 lines
6.2 KiB
C#
209 lines
6.2 KiB
C#
using System;
|
|
using System.Reflection;
|
|
using HarmonyLib;
|
|
|
|
using RobocraftX;
|
|
using RobocraftX.GUI;
|
|
using RobocraftX.GUI.MyGamesScreen;
|
|
using RobocraftX.Multiplayer;
|
|
using Svelto.ECS;
|
|
using Svelto.ECS.Experimental;
|
|
using Techblox.GameSelection;
|
|
|
|
using TechbloxModdingAPI.Engines;
|
|
using TechbloxModdingAPI.Utility;
|
|
|
|
namespace TechbloxModdingAPI.App
|
|
{
|
|
public class GameMenuEngine : IFactoryEngine
|
|
{
|
|
public WrappedHandler<MenuEventArgs> EnterMenu;
|
|
|
|
public WrappedHandler<MenuEventArgs> ExitMenu;
|
|
public IEntityFactory Factory { set; private get; }
|
|
|
|
public string Name => "TechbloxModdingAPIGameInfoGameEngine";
|
|
|
|
public bool isRemovable => false;
|
|
|
|
public EntitiesDB entitiesDB { set; private get; }
|
|
|
|
public GameMenuEngine()
|
|
{
|
|
MenuEnteredEnginePatch.EnteredExitedMenu = () =>
|
|
{
|
|
if (IsInMenu)
|
|
EnterMenu.Invoke(this, new MenuEventArgs { });
|
|
else
|
|
ExitMenu.Invoke(this, new MenuEventArgs { });
|
|
};
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
}
|
|
|
|
public void Ready()
|
|
{
|
|
MenuEnteredEnginePatch.IsInMenu = true; // At first it uses ActivateMenu(), then GoToMenu() which is patched
|
|
MenuEnteredEnginePatch.EnteredExitedMenu();
|
|
}
|
|
|
|
// game functionality
|
|
|
|
public bool IsInMenu => MenuEnteredEnginePatch.IsInMenu;
|
|
|
|
public Game[] GetMyGames()
|
|
{
|
|
EntityCollection<MyGameDataEntityStruct> mgsevs = entitiesDB.QueryEntities<MyGameDataEntityStruct>(MyGamesScreenExclusiveGroups.MyGames);
|
|
var mgsevsB = mgsevs.ToBuffer().buffer;
|
|
Game[] games = new Game[mgsevs.count];
|
|
for (int i = 0; i < mgsevs.count; i++)
|
|
{
|
|
Utility.Logging.MetaDebugLog($"Found game named {mgsevsB[i].GameName}");
|
|
games[i] = new Game(mgsevsB[i].ID);
|
|
}
|
|
return games;
|
|
}
|
|
|
|
public bool CreateMyGame(EGID id, string path = "", uint thumbnailId = 0, string gameName = "", string creatorName = "", string description = "", long createdDate = 0L)
|
|
{
|
|
EntityInitializer eci = Factory.BuildEntity<MyGameDataEntityDescriptor_DamnItFJWhyDidYouMakeThisInternal>(id);
|
|
eci.Init(new MyGameDataEntityStruct
|
|
{
|
|
SavedGamePath = new ECSString(path),
|
|
ThumbnailId = thumbnailId,
|
|
GameName = new ECSString(gameName),
|
|
CreatorName = new ECSString(creatorName),
|
|
GameDescription = new ECSString(description),
|
|
CreatedDate = createdDate,
|
|
});
|
|
// entitiesDB.PublishEntityChange<MyGameDataEntityStruct>(id); // this will always fail
|
|
return true;
|
|
}
|
|
|
|
public uint HighestID()
|
|
{
|
|
EntityCollection<MyGameDataEntityStruct> games = entitiesDB.QueryEntities<MyGameDataEntityStruct>(MyGamesScreenExclusiveGroups.MyGames);
|
|
var gamesB = games.ToBuffer().buffer;
|
|
uint max = 0;
|
|
for (int i = 0; i < games.count; i++)
|
|
{
|
|
if (gamesB[i].ID.entityID > max)
|
|
{
|
|
max = gamesB[i].ID.entityID;
|
|
}
|
|
}
|
|
return max;
|
|
}
|
|
|
|
public bool EnterGame(EGID id)
|
|
{
|
|
if (!ExistsGameInfo(id)) return false;
|
|
ref MyGameDataEntityStruct mgdes = ref GetGameInfo(id);
|
|
return EnterGame(mgdes.GameName, mgdes.FileId);
|
|
}
|
|
|
|
public bool EnterGame(ECSString gameName, string fileId, bool autoEnterSim = false)
|
|
{
|
|
FullGameFields._multiplayerParams.MultiplayerMode = MultiplayerMode.SinglePlayer;
|
|
ref var selection = ref entitiesDB.QueryEntity<GameSelectionComponent>(GameSelectionConstants.GameSelectionEGID);
|
|
selection.userContentID.Set(fileId);
|
|
selection.triggerStart = true;
|
|
selection.saveType = SaveType.ExistingSave;
|
|
selection.saveName = gameName;
|
|
selection.gameMode = GameMode.PlayGame;
|
|
selection.gameID.Set("GAMEID_Road_Track"); //TODO: Expose to the API
|
|
return true;
|
|
}
|
|
|
|
public bool SetGameName(EGID id, string name)
|
|
{
|
|
if (!ExistsGameInfo(id)) return false;
|
|
GetGameInfo(id).GameName.Set(name);
|
|
GetGameViewInfo(id).MyGamesSlotComponent.GameName = StringUtil.SanitiseString(name);
|
|
return true;
|
|
}
|
|
|
|
public bool SetGameDescription(EGID id, string name)
|
|
{
|
|
if (!ExistsGameInfo(id)) return false;
|
|
GetGameInfo(id).GameDescription.Set(name);
|
|
GetGameViewInfo(id).MyGamesSlotComponent.GameDescription = StringUtil.SanitiseString(name);
|
|
return true;
|
|
}
|
|
|
|
public bool ExistsGameInfo(EGID id)
|
|
{
|
|
return entitiesDB.Exists<MyGameDataEntityStruct>(id);
|
|
}
|
|
|
|
public ref MyGameDataEntityStruct GetGameInfo(EGID id)
|
|
{
|
|
return ref GetComponent<MyGameDataEntityStruct>(id);
|
|
}
|
|
|
|
public dynamic GetGameViewInfo(EGID id)
|
|
{
|
|
dynamic structOptional = AccessTools.Method("TechbloxModdingAPI.Utility.NativeApiExtensions:QueryEntityOptional", new []{typeof(EntitiesDB), typeof(EGID)})
|
|
.MakeGenericMethod(AccessTools.TypeByName("RobocraftX.GUI.MyGamesScreen.MyGamesSlotEntityViewStruct"))
|
|
.Invoke(null, new object[] {entitiesDB, new EGID(id.entityID, MyGamesScreenExclusiveGroups.GameSlotGuiEntities)});
|
|
if (structOptional == null) throw new Exception("Could not get game slot entity");
|
|
return structOptional ? structOptional : null;
|
|
}
|
|
|
|
public ref T GetComponent<T>(EGID id) where T: unmanaged, IEntityComponent
|
|
{
|
|
return ref entitiesDB.QueryEntity<T>(id);
|
|
}
|
|
|
|
internal void CloseBetaPopup()
|
|
{
|
|
var (buffer, count) = entitiesDB.QueryEntities<TogglePanelButtonEntityViewStruct>(ExclusiveGroup.Search("BetaPopup"));
|
|
for (int index = 0; index < count; ++index)
|
|
{
|
|
entitiesDB.QueryEntity<GUIEntityViewStruct>(buffer[index].TogglePanelButtonComponent.targetPanel)
|
|
.guiRoot.enabled = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class MyGameDataEntityDescriptor_DamnItFJWhyDidYouMakeThisInternal : GenericEntityDescriptor<MyGameDataEntityStruct> { }
|
|
|
|
[HarmonyPatch]
|
|
static class MenuEnteredEnginePatch
|
|
{
|
|
internal static bool IsInMenu;
|
|
internal static Action EnteredExitedMenu;
|
|
public static void Postfix()
|
|
{
|
|
IsInMenu = true;
|
|
EnteredExitedMenu();
|
|
}
|
|
|
|
public static MethodBase TargetMethod()
|
|
{
|
|
return AccessTools.Method(typeof(FullGameCompositionRoot), "SwitchToMenu");
|
|
}
|
|
}
|
|
|
|
[HarmonyPatch]
|
|
static class MenuExitedEnginePatch
|
|
{
|
|
public static void Prefix()
|
|
{
|
|
MenuEnteredEnginePatch.IsInMenu = false;
|
|
MenuEnteredEnginePatch.EnteredExitedMenu();
|
|
}
|
|
|
|
public static MethodBase TargetMethod()
|
|
{
|
|
return AccessTools.Method(typeof(FullGameCompositionRoot), "SwitchToGame");
|
|
}
|
|
}
|
|
|
|
public struct MenuEventArgs
|
|
{
|
|
|
|
}
|
|
}
|