|
- using System;
- using System.Reflection;
- using HarmonyLib;
-
- using RobocraftX;
- using RobocraftX.Common;
- using RobocraftX.FrontEnd;
- using RobocraftX.GUI;
- using RobocraftX.GUI.MyGamesScreen;
- using Svelto.ECS;
- using Svelto.ECS.Experimental;
- using Techblox.GameSelection;
- using TechbloxModdingAPI.Engines;
- using TechbloxModdingAPI.Utility;
- using GameMode = RobocraftX.Common.GameMode;
-
- 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(string gameName, string fileId, bool autoEnterSim = false)
- {
- GameMode.CurrentMode = autoEnterSim ? RCXMode.Play : RCXMode.Build;
- var data = new GameSelectionData
- {
- gameMode = Techblox.GameSelection.GameMode.PlayGame,
- gameType = GameType.MachineEditor,
- saveName = gameName,
- saveType = SaveType.ExistingSave,
- gameID = "GAMEID_Road_Track", //TODO: Expose to the API
- userContentID = fileId
- };
- // the private FullGameCompositionRoot.SwitchToGame() method gets passed to menu items for this reason
- AccessTools.Method(typeof(FullGameCompositionRoot), "SwitchToGame").Invoke(FullGameFields.Instance, new object[]{data});
- 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 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), "GoToMenu");
- }
- }
-
- [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
- {
-
- }
- }
|