TechbloxModdingAPI/TechbloxModdingAPI/App/GameMenuEngine.cs
NorbiPeti 5602ef9268 All kinds of fixes of issues during automatic tests
- 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
2021-12-28 15:09:01 +01:00

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
{
}
}