Merge branch 'preview'
# Conflicts: # Automation/gen_csproj.py # TechbloxModdingAPI/TechbloxModdingAPI.csproj
This commit is contained in:
commit
09d3c5e81c
43 changed files with 623 additions and 317 deletions
56
TechbloxModdingAPI/App/AntiAntiCheatPatch.cs
Normal file
56
TechbloxModdingAPI/App/AntiAntiCheatPatch.cs
Normal file
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using HarmonyLib;
|
||||
using Svelto.Tasks;
|
||||
|
||||
namespace TechbloxModdingAPI.App
|
||||
{
|
||||
public static class AntiAntiCheatPatch
|
||||
{
|
||||
private delegate bool AntiAnticheatDelegate(ref object __result);
|
||||
|
||||
private delegate bool AntiAnticheatDelegateBool(ref bool __result);
|
||||
|
||||
private delegate bool AntiAnticheatDelegateTask(ref IEnumerator<TaskContract> __result);
|
||||
|
||||
public static void Init(Harmony harmony)
|
||||
{
|
||||
var type = AccessTools.TypeByName("Techblox.Services.Eos.Anticheat.Client.Services.AnticheatClientService");
|
||||
harmony.Patch(type.GetConstructors()[0], new HarmonyMethod(((Func<bool>) AntiAntiCheat).Method));
|
||||
harmony.Patch(AccessTools.Method(type, "Shutdown"), new HarmonyMethod(((Func<bool>) AntiAntiCheat).Method));
|
||||
harmony.Patch(AccessTools.Method(type, "StartProtectedSession"), new HarmonyMethod(((AntiAnticheatDelegate) AntiAntiCheat).Method));
|
||||
harmony.Patch(AccessTools.Method(type, "StopProtectedSession"), new HarmonyMethod(((AntiAnticheatDelegateBool) AntiAntiCheat).Method));
|
||||
harmony.Patch(AccessTools.Method("Techblox.Services.Eos.Anticheat.Client.EosGetPendingMessagesToSendServiceRequest:Execute"), new HarmonyMethod(((AntiAnticheatDelegateTask)AntiAntiCheatTask).Method));
|
||||
harmony.Patch(AccessTools.Method("Techblox.Anticheat.Client.Engines.ShowFeedbackDialogEngine:PollAnticheatStatus"), new HarmonyMethod(((AntiAnticheatDelegateTask)AntiAntiCheatTask).Method));
|
||||
}
|
||||
|
||||
private static bool AntiAntiCheat() => false;
|
||||
|
||||
private static bool AntiAntiCheat(ref object __result)
|
||||
{
|
||||
var targetType =
|
||||
AccessTools.TypeByName("Techblox.Services.Eos.Anticheat.Client.Services.StartProtectedSessionResult");
|
||||
var target = Activator.CreateInstance(targetType);
|
||||
targetType.GetField("Success").SetValue(target, true);
|
||||
__result = target;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool AntiAntiCheat(ref bool __result)
|
||||
{
|
||||
__result = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool AntiAntiCheatTask(ref IEnumerator<TaskContract> __result)
|
||||
{
|
||||
IEnumerator<TaskContract> Func()
|
||||
{
|
||||
yield return Yield.It;
|
||||
}
|
||||
|
||||
__result = Func();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
using System;
|
||||
|
||||
using RobocraftX.GUI.MyGamesScreen;
|
||||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Engines;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.App
|
||||
{
|
||||
public class AppEngine : IFactoryEngine
|
||||
{
|
||||
public WrappedHandler<MenuEventArgs> EnterMenu;
|
||||
|
||||
public WrappedHandler<MenuEventArgs> ExitMenu;
|
||||
|
||||
public IEntityFactory Factory { set; private get; }
|
||||
|
||||
public string Name => "TechbloxModdingAPIAppEngine";
|
||||
|
||||
public bool isRemovable => false;
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
IsInMenu = false;
|
||||
ExitMenu.Invoke(this, new MenuEventArgs { });
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
IsInMenu = true;
|
||||
EnterMenu.Invoke(this, new MenuEventArgs { });
|
||||
}
|
||||
|
||||
// app functionality
|
||||
|
||||
public bool IsInMenu
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = false;
|
||||
}
|
||||
}
|
|
@ -14,12 +14,12 @@ namespace TechbloxModdingAPI.App
|
|||
/// </summary>
|
||||
public class Client
|
||||
{
|
||||
public static Client Instance { get; } = new Client();
|
||||
|
||||
protected static Func<object> ErrorHandlerInstanceGetter;
|
||||
|
||||
protected static Action<object, Error> EnqueueError;
|
||||
|
||||
protected static Action<object> HandleErrorClosed;
|
||||
|
||||
/// <summary>
|
||||
/// An event that fires whenever the main menu is loaded.
|
||||
/// </summary>
|
||||
|
@ -93,14 +93,31 @@ namespace TechbloxModdingAPI.App
|
|||
EnqueueError(errorHandlerInstance, popup);
|
||||
}
|
||||
|
||||
// TODO
|
||||
/*public void CloseCurrentPrompt()
|
||||
public void CloseCurrentPrompt()
|
||||
{
|
||||
// RobocraftX.Services.ErrorHandler.Instance.HandlePopupClosed();
|
||||
// FIXME: this is a call that is also called when closing, not the actual closing action itself (so it doesn't work)
|
||||
object errorHandlerInstance = ErrorHandlerInstanceGetter();
|
||||
HandleErrorClosed(errorHandlerInstance);
|
||||
}*/
|
||||
var popup = GetPopupCloseMethods(errorHandlerInstance);
|
||||
popup.Close();
|
||||
}
|
||||
|
||||
public void SelectFirstPromptButton()
|
||||
{
|
||||
object errorHandlerInstance = ErrorHandlerInstanceGetter();
|
||||
var popup = GetPopupCloseMethods(errorHandlerInstance);
|
||||
popup.FirstButton();
|
||||
}
|
||||
|
||||
public void SelectSecondPromptButton()
|
||||
{
|
||||
object errorHandlerInstance = ErrorHandlerInstanceGetter();
|
||||
var popup = GetPopupCloseMethods(errorHandlerInstance);
|
||||
popup.SecondButton();
|
||||
}
|
||||
|
||||
internal void CloseBetaPopup()
|
||||
{
|
||||
Game.menuEngine.CloseBetaPopup();
|
||||
}
|
||||
|
||||
internal static void Init()
|
||||
{
|
||||
|
@ -113,9 +130,6 @@ namespace TechbloxModdingAPI.App
|
|||
EnqueueError = (Action<object, Error>) AccessTools.Method("TechbloxModdingAPI.App.Client:GenEnqueueError")
|
||||
.MakeGenericMethod(errorHandler, errorHandle)
|
||||
.Invoke(null, new object[0]);
|
||||
/*HandleErrorClosed = (Action<object>) AccessTools.Method("TechbloxModdingAPI.App.Client:GenHandlePopupClosed")
|
||||
.MakeGenericMethod(errorHandler)
|
||||
.Invoke(null, new object[0]);*/
|
||||
}
|
||||
|
||||
// Creating delegates once is faster than reflection every time
|
||||
|
@ -140,14 +154,23 @@ namespace TechbloxModdingAPI.App
|
|||
return enqueueCasted;
|
||||
}
|
||||
|
||||
private static Action<object> GenHandlePopupClosed<T>()
|
||||
private static (Action Close, Action FirstButton, Action SecondButton) _errorPopup;
|
||||
|
||||
private static (Action Close, Action FirstButton, Action SecondButton) GetPopupCloseMethods(object handler)
|
||||
{
|
||||
Type errorHandler = AccessTools.TypeByName("RobocraftX.Services.ErrorHandler");
|
||||
MethodInfo handlePopupClosed = AccessTools.Method(errorHandler, "HandlePopupClosed");
|
||||
Action<T> handleSimple =
|
||||
(Action<T>) Delegate.CreateDelegate(typeof(Action<T>), handlePopupClosed);
|
||||
Action<object> handleCasted = (object instance) => handleSimple((T) instance);
|
||||
return handleCasted;
|
||||
if (_errorPopup.Close != null)
|
||||
return _errorPopup;
|
||||
Type errorHandler = handler.GetType();
|
||||
FieldInfo field = AccessTools.Field(errorHandler, "errorPopup");
|
||||
var errorPopup = (ErrorPopup)field.GetValue(handler);
|
||||
MethodInfo info = AccessTools.Method(errorPopup.GetType(), "ClosePopup");
|
||||
var close = (Action)Delegate.CreateDelegate(typeof(Action), errorPopup, info);
|
||||
info = AccessTools.Method(errorPopup.GetType(), "HandleFirstOption");
|
||||
var first = (Action)Delegate.CreateDelegate(typeof(Action), errorPopup, info);
|
||||
info = AccessTools.Method(errorPopup.GetType(), "HandleSecondOption");
|
||||
var second = (Action)Delegate.CreateDelegate(typeof(Action), errorPopup, info);
|
||||
_errorPopup = (close, first, second);
|
||||
return _errorPopup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,17 +42,25 @@ namespace TechbloxModdingAPI.App
|
|||
[APITestCase(TestType.Menu)]
|
||||
public static void TestPopUp2()
|
||||
{
|
||||
Client c = new Client();
|
||||
c.PromptUser(popup2);
|
||||
//c.CloseCurrentPrompt();
|
||||
Client.Instance.PromptUser(popup2);
|
||||
}
|
||||
|
||||
[APITestCase(TestType.Menu)]
|
||||
public static void TestPopUp1()
|
||||
{
|
||||
Client c = new Client();
|
||||
c.PromptUser(popup1);
|
||||
//c.CloseCurrentPrompt();
|
||||
Client.Instance.PromptUser(popup1);
|
||||
}
|
||||
|
||||
[APITestCase(TestType.Menu)]
|
||||
public static void TestPopUpClose1()
|
||||
{
|
||||
Client.Instance.CloseCurrentPrompt();
|
||||
}
|
||||
|
||||
[APITestCase(TestType.Menu)]
|
||||
public static void TestPopUpClose2()
|
||||
{
|
||||
Client.Instance.CloseCurrentPrompt();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,23 +1,27 @@
|
|||
namespace TechbloxModdingAPI.App
|
||||
using System;
|
||||
|
||||
namespace TechbloxModdingAPI.App
|
||||
{
|
||||
public enum CurrentGameMode
|
||||
{
|
||||
None,
|
||||
/// <summary>
|
||||
/// Building a game
|
||||
/// Building a world
|
||||
/// </summary>
|
||||
Build,
|
||||
/// <summary>
|
||||
/// Playing a game
|
||||
/// Playing on a map
|
||||
/// </summary>
|
||||
Play,
|
||||
/// <summary>
|
||||
/// Viewing a prefab
|
||||
/// Viewing a prefab (doesn't exist anymore)
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
View,
|
||||
/// <summary>
|
||||
/// Viewing a tutorial
|
||||
/// Viewing a tutorial (doesn't exist anymore)
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
Tutorial
|
||||
}
|
||||
}
|
|
@ -2,12 +2,10 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.GUI.MyGamesScreen;
|
||||
using RobocraftX.StateSync;
|
||||
using Svelto.ECS;
|
||||
using Techblox.GameSelection;
|
||||
|
||||
using TechbloxModdingAPI;
|
||||
using TechbloxModdingAPI.Blocks;
|
||||
using TechbloxModdingAPI.Tasks;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
@ -318,7 +316,7 @@ namespace TechbloxModdingAPI.App
|
|||
get
|
||||
{
|
||||
if (menuMode || !VerifyMode()) return CurrentGameMode.None;
|
||||
return (CurrentGameMode) GameMode.CurrentMode;
|
||||
return gameEngine.GetGameData().gameMode == GameMode.CreateWorld ? CurrentGameMode.Build : CurrentGameMode.Play;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,12 +27,14 @@ namespace TechbloxModdingAPI.App
|
|||
|
||||
public JobHandle OnInitializeTimeRunningMode(JobHandle inputDeps)
|
||||
{
|
||||
Console.WriteLine("Init time running mode");
|
||||
SimulationMode.Invoke(this, new GameEventArgs { GameName = "", GamePath = "" }); // TODO
|
||||
return inputDeps;
|
||||
}
|
||||
|
||||
public JobHandle OnInitializeTimeStoppedMode(JobHandle inputDeps)
|
||||
{
|
||||
Console.WriteLine("Init time stopped mode");
|
||||
BuildMode.Invoke(this, new GameEventArgs { GameName = "", GamePath = "" });
|
||||
return inputDeps;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
using HarmonyLib;
|
||||
using RobocraftX;
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.Schedulers;
|
||||
using RobocraftX.SimulationModeState;
|
||||
|
@ -8,11 +10,15 @@ using Svelto.Tasks;
|
|||
using Svelto.Tasks.Lean;
|
||||
using RobocraftX.Blocks;
|
||||
using RobocraftX.Common.Loading;
|
||||
using RobocraftX.Multiplayer;
|
||||
using RobocraftX.ScreenshotTaker;
|
||||
using Techblox.Environment.Transition;
|
||||
using Techblox.GameSelection;
|
||||
|
||||
using TechbloxModdingAPI.Blocks;
|
||||
using TechbloxModdingAPI.Engines;
|
||||
using TechbloxModdingAPI.Input;
|
||||
using TechbloxModdingAPI.Players;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.App
|
||||
|
@ -30,16 +36,34 @@ namespace TechbloxModdingAPI.App
|
|||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
private bool enteredGame;
|
||||
private bool loadingFinished;
|
||||
private bool playerJoined;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (GameReloadedPatch.IsReload)
|
||||
return; // Toggling time mode
|
||||
ExitGame.Invoke(this, new GameEventArgs { GameName = GetGameData().saveName, GamePath = GetGameData().gameID });
|
||||
IsInGame = false;
|
||||
loadingFinished = false;
|
||||
playerJoined = false;
|
||||
enteredGame = false;
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
if (GameReloadedPatch.IsReload)
|
||||
return; // Toggling time mode
|
||||
enteredGame = true;
|
||||
Player.Joined += OnPlayerJoined;
|
||||
}
|
||||
|
||||
private void OnPlayerJoined(object sender, PlayerEventArgs args)
|
||||
{
|
||||
if (args.Player.Type != PlayerType.Local) return;
|
||||
playerJoined = true;
|
||||
Player.Joined -= OnPlayerJoined;
|
||||
CheckJoinEvent();
|
||||
}
|
||||
|
||||
// game functionality
|
||||
|
@ -54,7 +78,7 @@ namespace TechbloxModdingAPI.App
|
|||
{
|
||||
if (async)
|
||||
{
|
||||
ExitCurrentGameAsync().RunOn(Lean.EveryFrameStepRunner_TimeRunningAndStopped);
|
||||
ExitCurrentGameAsync().RunOn(ClientLean.EveryFrameStepRunner_TimeRunningAndStopped);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -94,10 +118,23 @@ namespace TechbloxModdingAPI.App
|
|||
|
||||
public void ToggleTimeMode()
|
||||
{
|
||||
if (!entitiesDB.FoundInGroups<BlockTagEntityStruct>())
|
||||
throw new AppStateException("At least one block must exist in the world to enter simulation");
|
||||
SwitchAnimationUtil.Start(entitiesDB);
|
||||
}
|
||||
if (TimeRunningModeUtil.IsTimeStoppedMode(entitiesDB))
|
||||
FakeInput.ActionInput(toggleMode: true);
|
||||
else
|
||||
{
|
||||
IEnumerator<TaskContract> ReloadBuildModeTask()
|
||||
{
|
||||
SwitchAnimationUtil.Start(entitiesDB);
|
||||
while (SwitchAnimationUtil.IsFadeOutActive(entitiesDB))
|
||||
yield return (TaskContract)Yield.It;
|
||||
FullGameFields._multiplayerParams.MultiplayerMode = MultiplayerMode.SinglePlayer;
|
||||
AccessTools.Method(typeof(FullGameCompositionRoot), "ReloadGame")
|
||||
.Invoke(FullGameFields.Instance, new object[] { });
|
||||
}
|
||||
|
||||
ReloadBuildModeTask().RunOn(ClientLean.UIScheduler);
|
||||
}
|
||||
}
|
||||
|
||||
public EGID[] GetAllBlocksInGame(BlockIDs filter = BlockIDs.Invalid)
|
||||
{
|
||||
|
@ -142,9 +179,16 @@ namespace TechbloxModdingAPI.App
|
|||
public void Remove(ref LoadingActionEntityStruct entityComponent, EGID egid)
|
||||
{ // Finished loading
|
||||
if (!enteredGame) return;
|
||||
enteredGame = false;
|
||||
loadingFinished = true;
|
||||
CheckJoinEvent();
|
||||
}
|
||||
|
||||
private void CheckJoinEvent()
|
||||
{
|
||||
if (!loadingFinished || !playerJoined) return;
|
||||
EnterGame.Invoke(this, new GameEventArgs { GameName = GetGameData().saveName, GamePath = GetGameData().gameID });
|
||||
IsInGame = true;
|
||||
enteredGame = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,16 +3,15 @@ using System.Reflection;
|
|||
using HarmonyLib;
|
||||
|
||||
using RobocraftX;
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.FrontEnd;
|
||||
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;
|
||||
using GameMode = RobocraftX.Common.GameMode;
|
||||
|
||||
namespace TechbloxModdingAPI.App
|
||||
{
|
||||
|
@ -105,20 +104,16 @@ namespace TechbloxModdingAPI.App
|
|||
return EnterGame(mgdes.GameName, mgdes.FileId);
|
||||
}
|
||||
|
||||
public bool EnterGame(string gameName, string fileId, bool autoEnterSim = false)
|
||||
public bool EnterGame(ECSString 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});
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -161,6 +156,16 @@ namespace TechbloxModdingAPI.App
|
|||
{
|
||||
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> { }
|
||||
|
@ -178,7 +183,7 @@ namespace TechbloxModdingAPI.App
|
|||
|
||||
public static MethodBase TargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(FullGameCompositionRoot), "GoToMenu");
|
||||
return AccessTools.Method(typeof(FullGameCompositionRoot), "SwitchToMenu");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,9 +8,10 @@ using Svelto.ECS.EntityStructs;
|
|||
using RobocraftX.Common;
|
||||
using RobocraftX.Blocks;
|
||||
using Unity.Mathematics;
|
||||
using Gamecraft.Blocks.GUI;
|
||||
using HarmonyLib;
|
||||
using RobocraftX.PilotSeat;
|
||||
using RobocraftX.Rendering;
|
||||
using Techblox.BlockLabels;
|
||||
|
||||
using TechbloxModdingAPI.Blocks;
|
||||
using TechbloxModdingAPI.Blocks.Engines;
|
||||
|
@ -339,11 +340,9 @@ namespace TechbloxModdingAPI
|
|||
[TestValue(null)]
|
||||
public string Label
|
||||
{
|
||||
get => BlockEngine.GetBlockInfoViewComponent<TextLabelEntityViewStruct>(this).textLabelComponent?.text;
|
||||
get => BlockEngine.GetBlockInfo<LabelResourceIDComponent>(this).ToString(); //TODO: Block labels
|
||||
set
|
||||
{
|
||||
var comp = BlockEngine.GetBlockInfoViewComponent<TextLabelEntityViewStruct>(this).textLabelComponent;
|
||||
if (comp != null) comp.text = value;
|
||||
{ //TODO
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
|
|
@ -273,6 +273,12 @@ namespace TechbloxModdingAPI.Blocks
|
|||
/// <summary>
|
||||
/// The grid block used by the world editor, named Small Grid like the other one
|
||||
/// </summary>
|
||||
SmallGridInWorldEditor
|
||||
SmallGridInWorldEditor,
|
||||
SegoeUITextblock = 376,
|
||||
GravtracTextblock,
|
||||
HauserTextblock,
|
||||
TechnopollasTextblock,
|
||||
BitBlock = 385,
|
||||
Timer
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@ namespace TechbloxModdingAPI.Blocks
|
|||
base(new EGID(id, CommonExclusiveGroups.ENGINE_BLOCK_BUILD_GROUP))
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Gets or sets the Engine's On property. May not be saved.
|
||||
/// </summary>
|
||||
|
@ -34,6 +34,7 @@ namespace TechbloxModdingAPI.Blocks
|
|||
}
|
||||
set
|
||||
{
|
||||
Techblox.BlockColours.BlockColoursCompositionRoot
|
||||
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).engineOn = value;
|
||||
}
|
||||
}
|
||||
|
@ -377,6 +378,6 @@ namespace TechbloxModdingAPI.Blocks
|
|||
{
|
||||
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockReadonlyComponent>(this).manualToAutoGearCoolOffTime = value;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
|
||||
copyToBlock.Invoke(Patch.copyEngine, new object[] {pickedBlock.ID, pickedBlock});
|
||||
|
||||
ExclusiveGroupStruct group = WiresExclusiveGroups.WIRES_COPY_GROUP + playerID;
|
||||
ExclusiveGroupStruct group = BuildModeWiresGroups.WIRES_COPY_GROUP + playerID;
|
||||
copyWireToBlock.Invoke(Patch.createWireEngine, new object[] {group, pickedBlock.ID});
|
||||
|
||||
pickedBlock.placedBlockTweaksMustCopy = false;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Gamecraft.Blocks.BlockGroups;
|
||||
|
@ -173,7 +173,8 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
foreach (var block in blocks)
|
||||
{
|
||||
GhostChildUtility.BuildGhostChild(in playerID, block.Id, in pos, in rot, entitiesDB,
|
||||
BuildGhostBlueprintFactory, false, bssesopt.Get().buildingDroneReference);
|
||||
BuildGhostBlueprintFactory, false, bssesopt.Get().buildingDroneReference,
|
||||
FullGameFields._managers.blockLabelResourceManager);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -272,7 +273,8 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
uint ghostChildBlockId = CommonExclusiveGroups.GetNewGhostChildBlockID();
|
||||
var ghostEntityReference = GhostBlockUtils.GetGhostEntityReference(sourceId.entityID, entitiesDB);
|
||||
var entityInitializer = BuildGhostBlueprintFactory.Build(
|
||||
new EGID(ghostChildBlockId, BoxSelectExclusiveGroups.GhostChildEntitiesExclusiveGroup), /*dbStruct.DBID*/ (uint)BlockIDs.Cube);
|
||||
new EGID(ghostChildBlockId, BoxSelectExclusiveGroups.GhostChildEntitiesExclusiveGroup), /*dbStruct.DBID*/ (uint)BlockIDs.Cube,
|
||||
FullGameFields._managers.blockLabelResourceManager);
|
||||
entityInitializer.Init(dbStruct);
|
||||
entityInitializer.Init(new GFXPrefabEntityStructGPUI(
|
||||
PrefabsID.GetOrCreatePrefabID((ushort)entityInitializer.Get<PrefabAssetIDComponent>().prefabAssetID,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using RobocraftX.Common;
|
||||
using RobocraftX.UECS;
|
||||
using RobocraftX.DOTS;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.EntityStructs;
|
||||
using Unity.Mathematics;
|
||||
|
@ -40,7 +40,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntityOrDefault<PositionEntityStruct>(block);
|
||||
ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntityOrDefault<GridRotationStruct>(block);
|
||||
ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntityOrDefault<LocalTransformEntityStruct>(block);
|
||||
ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntityOrDefault<UECSPhysicsEntityStruct>(block);
|
||||
ref DOTSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntityOrDefault<DOTSPhysicsEntityStruct>(block);
|
||||
// main (persistent) position
|
||||
posStruct.position = vector;
|
||||
// placement grid position
|
||||
|
@ -50,7 +50,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
// collision position
|
||||
if (phyStruct.ID != default)
|
||||
{ //It exists
|
||||
FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.uecsEntity, new Translation
|
||||
FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.dotsEntity, new Translation
|
||||
{
|
||||
Value = posStruct.position
|
||||
});
|
||||
|
|
|
@ -54,7 +54,8 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
//RobocraftX.CR.MachineEditing.PlaceSingleBlockEngine
|
||||
DBEntityStruct dbEntity = new DBEntityStruct {DBID = block};
|
||||
|
||||
EntityInitializer structInitializer = _blockEntityFactory.Build(CommonExclusiveGroups.nextBlockEntityID, block); //The ghost block index is only used for triggers
|
||||
//TODO: Test
|
||||
EntityInitializer structInitializer = _blockEntityFactory.Build(CommonExclusiveGroups.blockIDGeneratorClient.Next(), block); //The ghost block index is only used for triggers
|
||||
uint prefabAssetID = structInitializer.Has<PrefabAssetIDComponent>()
|
||||
? structInitializer.Get<PrefabAssetIDComponent>().prefabAssetID
|
||||
: throw new BlockException("Prefab asset ID not found!"); //Set by the game
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using RobocraftX.Common;
|
||||
using RobocraftX.UECS;
|
||||
using RobocraftX.DOTS;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.EntityStructs;
|
||||
using Unity.Mathematics;
|
||||
|
@ -40,7 +40,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
ref RotationEntityStruct rotStruct = ref this.entitiesDB.QueryEntityOrDefault<RotationEntityStruct>(block);
|
||||
ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntityOrDefault<GridRotationStruct>(block);
|
||||
ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntityOrDefault<LocalTransformEntityStruct>(block);
|
||||
ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntityOrDefault<UECSPhysicsEntityStruct>(block);
|
||||
ref DOTSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntityOrDefault<DOTSPhysicsEntityStruct>(block);
|
||||
// main (persistent) rotation
|
||||
Quaternion newRotation = rotStruct.rotation;
|
||||
newRotation.eulerAngles = vector;
|
||||
|
@ -52,7 +52,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
// collision rotation
|
||||
if (phyStruct.ID != default)
|
||||
{ //It exists
|
||||
FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.uecsEntity,
|
||||
FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.dotsEntity,
|
||||
new Unity.Transforms.Rotation
|
||||
{
|
||||
Value = rotStruct.rotation
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
using HarmonyLib;
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.UECS;
|
||||
using RobocraftX.DOTS;
|
||||
using Svelto.ECS;
|
||||
using Unity.Entities;
|
||||
|
||||
|
@ -13,7 +13,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
{
|
||||
public class ScalingEngine : IApiEngine
|
||||
{
|
||||
private static IReactOnAddAndRemove<UECSPhysicsEntityCreationStruct> physicsEngine;
|
||||
private static IReactOnAddAndRemove<DOTSPhysicsEntityCreationStruct> physicsEngine;
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
|
@ -34,16 +34,16 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
if (_entityManager == default)
|
||||
_entityManager = FullGameFields._physicsWorld.EntityManager;
|
||||
//Assuming the block exists
|
||||
var entity = entitiesDB.QueryEntity<UECSPhysicsEntityStruct>(egid).uecsEntity;
|
||||
var pes = new UECSPhysicsEntityCreationStruct();
|
||||
physicsEngine.Add(ref pes, egid); //Create new UECS entity
|
||||
var entity = entitiesDB.QueryEntity<DOTSPhysicsEntityStruct>(egid).dotsEntity;
|
||||
var pes = new DOTSPhysicsEntityCreationStruct();
|
||||
physicsEngine.Add(ref pes, egid); //Create new DOTS entity
|
||||
_entityManager.DestroyEntity(entity);
|
||||
}
|
||||
|
||||
[HarmonyPatch]
|
||||
class PhysicsEnginePatch
|
||||
{
|
||||
static void Postfix(IReactOnAddAndRemove<UECSPhysicsEntityCreationStruct> __instance)
|
||||
static void Postfix(IReactOnAddAndRemove<DOTSPhysicsEntityCreationStruct> __instance)
|
||||
{
|
||||
physicsEngine = __instance;
|
||||
Logging.MetaDebugLog("Physics engine injected.");
|
||||
|
@ -51,7 +51,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
|
||||
static MethodBase TargetMethod(Harmony instance)
|
||||
{
|
||||
return AccessTools.Method("RobocraftX.StateSync.HandleUECSPhysicEntitiesWithPrefabCreationEngine" +
|
||||
return AccessTools.Method("RobocraftX.StateSync.HandleDOTSPhysicEntitiesWithPrefabCreationEngine" +
|
||||
":Ready");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
|
||||
public WireEntityStruct CreateNewWire(EGID startBlock, byte startPort, EGID endBlock, byte endPort)
|
||||
{
|
||||
EGID wireEGID = new EGID(WiresExclusiveGroups.NewWireEntityId, NamedExclusiveGroup<WiresGroup>.Group);
|
||||
EGID wireEGID = new EGID(BuildModeWiresGroups.NewWireEntityId, BuildModeWiresGroups.WiresGroup.Group);
|
||||
EntityInitializer wireInitializer = Factory.BuildEntity<WireEntityDescriptor>(wireEGID);
|
||||
wireInitializer.Init(new WireEntityStruct
|
||||
{
|
||||
|
@ -77,8 +77,8 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
public ref PortEntityStruct GetPortByOffset(BlockPortsStruct bps, byte portNumber, bool input)
|
||||
{
|
||||
ExclusiveGroup group = input
|
||||
? NamedExclusiveGroup<InputPortsGroup>.Group
|
||||
: NamedExclusiveGroup<OutputPortsGroup>.Group;
|
||||
? NamedExclusiveGroup<BuildModeWiresGroups.InputPortsGroup>.Group
|
||||
: NamedExclusiveGroup<BuildModeWiresGroups.OutputPortsGroup>.Group;
|
||||
uint id = (input ? bps.firstInputID : bps.firstOutputID) + portNumber;
|
||||
EGID egid = new EGID(id, group);
|
||||
if (!entitiesDB.Exists<PortEntityStruct>(egid))
|
||||
|
@ -193,7 +193,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
EGID[] inputs = new EGID[ports.inputCount];
|
||||
for (uint i = 0; i < ports.inputCount; i++)
|
||||
{
|
||||
inputs[i] = new EGID(i + ports.firstInputID, NamedExclusiveGroup<InputPortsGroup>.Group);
|
||||
inputs[i] = new EGID(i + ports.firstInputID, NamedExclusiveGroup<BuildModeWiresGroups.InputPortsGroup>.Group);
|
||||
}
|
||||
return inputs;
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
EGID[] outputs = new EGID[ports.outputCount];
|
||||
for (uint i = 0; i < ports.outputCount; i++)
|
||||
{
|
||||
outputs[i] = new EGID(i + ports.firstOutputID, NamedExclusiveGroup<OutputPortsGroup>.Group);
|
||||
outputs[i] = new EGID(i + ports.firstOutputID, NamedExclusiveGroup<BuildModeWiresGroups.OutputPortsGroup>.Group);
|
||||
}
|
||||
return outputs;
|
||||
}
|
||||
|
@ -219,8 +219,8 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
if (!entitiesDB.Exists<BlockPortsStruct>(block))
|
||||
return default;
|
||||
var group = output
|
||||
? NamedExclusiveGroup<OutputPortsGroup>.Group
|
||||
: NamedExclusiveGroup<InputPortsGroup>.Group;
|
||||
? NamedExclusiveGroup<BuildModeWiresGroups.OutputPortsGroup>.Group
|
||||
: NamedExclusiveGroup<BuildModeWiresGroups.InputPortsGroup>.Group;
|
||||
BlockPortsStruct ports = entitiesDB.QueryEntity<BlockPortsStruct>(block);
|
||||
if (!entitiesDB.TryQueryMappedEntities<PortEntityStruct>(group, out var mapper))
|
||||
return default;
|
||||
|
@ -237,7 +237,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
|
||||
public ref WireEntityStruct MatchPortToWire(PortEntityStruct port, EGID blockID, out bool exists)
|
||||
{
|
||||
var wires = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<WiresGroup>.Group);
|
||||
var wires = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group);
|
||||
var wiresB = wires.ToBuffer().buffer;
|
||||
for (uint i = 0; i < wires.count; i++)
|
||||
{
|
||||
|
@ -264,7 +264,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
else
|
||||
{
|
||||
BlockPortsStruct ports = entitiesDB.QueryEntity<BlockPortsStruct>(startBlock);
|
||||
startPorts = new EGID[] {new EGID(ports.firstOutputID + startPort, NamedExclusiveGroup<OutputPortsGroup>.Group) };
|
||||
startPorts = new EGID[] {new EGID(ports.firstOutputID + startPort, NamedExclusiveGroup<BuildModeWiresGroups.OutputPortsGroup>.Group) };
|
||||
}
|
||||
|
||||
EGID[] endPorts;
|
||||
|
@ -276,10 +276,10 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
else
|
||||
{
|
||||
BlockPortsStruct ports = entitiesDB.QueryEntity<BlockPortsStruct>(endBlock);
|
||||
endPorts = new EGID[] {new EGID(ports.firstInputID + endPort, NamedExclusiveGroup<InputPortsGroup>.Group) };
|
||||
endPorts = new EGID[] {new EGID(ports.firstInputID + endPort, NamedExclusiveGroup<BuildModeWiresGroups.InputPortsGroup>.Group) };
|
||||
}
|
||||
|
||||
EntityCollection<WireEntityStruct> wires = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<WiresGroup>.Group);
|
||||
EntityCollection<WireEntityStruct> wires = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group);
|
||||
var wiresB = wires.ToBuffer().buffer;
|
||||
for (int endIndex = 0; endIndex < endPorts.Length; endIndex++)
|
||||
{
|
||||
|
@ -304,7 +304,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
public OptionalRef<ChannelDataStruct> GetChannelDataStruct(EGID portID)
|
||||
{
|
||||
var port = GetPort(portID);
|
||||
var channels = entitiesDB.QueryEntities<ChannelDataStruct>(NamedExclusiveGroup<ChannelDataGroup>.Group);
|
||||
var channels = entitiesDB.QueryEntities<ChannelDataStruct>(NamedExclusiveGroup<BuildModeWiresGroups.ChannelDataGroup>.Group);
|
||||
var channelsB = channels.ToBuffer();
|
||||
return port.firstChannelIndexCachedInSim < channels.count
|
||||
? new OptionalRef<ChannelDataStruct>(channelsB.buffer, port.firstChannelIndexCachedInSim)
|
||||
|
@ -329,7 +329,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
|
||||
public EGID[] WiredToInput(EGID block, byte port)
|
||||
{
|
||||
WireEntityStruct[] wireEntityStructs = Search(NamedExclusiveGroup<WiresGroup>.Group,
|
||||
WireEntityStruct[] wireEntityStructs = Search(NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group,
|
||||
(WireEntityStruct wes) => wes.destinationPortUsage == port && wes.destinationBlockEGID == block);
|
||||
EGID[] result = new EGID[wireEntityStructs.Length];
|
||||
for (uint i = 0; i < wireEntityStructs.Length; i++)
|
||||
|
@ -342,7 +342,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
|
||||
public EGID[] WiredToOutput(EGID block, byte port)
|
||||
{
|
||||
WireEntityStruct[] wireEntityStructs = Search(NamedExclusiveGroup<WiresGroup>.Group,
|
||||
WireEntityStruct[] wireEntityStructs = Search(NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group,
|
||||
(WireEntityStruct wes) => wes.sourcePortUsage == port && wes.sourceBlockEGID == block);
|
||||
EGID[] result = new EGID[wireEntityStructs.Length];
|
||||
for (uint i = 0; i < wireEntityStructs.Length; i++)
|
||||
|
@ -371,13 +371,13 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
private EntityCollection<ChannelDataStruct> GetSignalStruct(uint signalID, out uint index, bool input = true)
|
||||
{
|
||||
ExclusiveGroup group = input
|
||||
? NamedExclusiveGroup<InputPortsGroup>.Group
|
||||
: NamedExclusiveGroup<OutputPortsGroup>.Group;
|
||||
? NamedExclusiveGroup<BuildModeWiresGroups.InputPortsGroup>.Group
|
||||
: NamedExclusiveGroup<BuildModeWiresGroups.OutputPortsGroup>.Group;
|
||||
if (entitiesDB.Exists<PortEntityStruct>(signalID, group))
|
||||
{
|
||||
index = entitiesDB.QueryEntity<PortEntityStruct>(signalID, group).anyChannelIndex;
|
||||
var channelData =
|
||||
entitiesDB.QueryEntities<ChannelDataStruct>(NamedExclusiveGroup<ChannelDataGroup>.Group);
|
||||
entitiesDB.QueryEntities<ChannelDataStruct>(NamedExclusiveGroup<BuildModeWiresGroups.ChannelDataGroup>.Group);
|
||||
return channelData;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using HarmonyLib;
|
||||
using Svelto.ECS;
|
||||
using RobocraftX.CR.MainGame;
|
||||
using RobocraftX.Multiplayer;
|
||||
using RobocraftX.StateSync;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// Patch of RobocraftX.CR.MainGame.MainGameCompositionRoot.DeterministicCompose<T>()
|
||||
/// Initializes custom commands
|
||||
/// </summary>
|
||||
[HarmonyPatch]
|
||||
static class CommandPatch
|
||||
{
|
||||
public static void Postfix(StateSyncRegistrationHelper stateSyncReg)
|
||||
{
|
||||
/*CommandLineCompositionRoot.Compose(contextHolder, stateSyncReg.enginesRoot, reloadGame, multiplayerParameters,
|
||||
stateSyncReg); - uREPL C# compilation not supported anymore */
|
||||
var enginesRoot = stateSyncReg.enginesRoot;
|
||||
CommandManager.RegisterEngines(enginesRoot);
|
||||
}
|
||||
|
||||
public static MethodInfo TargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(MainGameCompositionRoot), "DeterministicCompose")
|
||||
.MakeGenericMethod(typeof(object));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -62,6 +62,7 @@ namespace TechbloxModdingAPI
|
|||
var id = initializer(this);
|
||||
if (!dict.ContainsKey(id)) // Multiple instances may be created
|
||||
dict.Add(id, this);
|
||||
Id = id;
|
||||
}
|
||||
|
||||
#region ECS initializer stuff
|
||||
|
|
|
@ -6,27 +6,67 @@ using RobocraftX.FrontEnd;
|
|||
using RobocraftX.StateSync;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.Schedulers;
|
||||
using TechbloxModdingAPI.Commands;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Engines
|
||||
{
|
||||
[HarmonyPatch]
|
||||
class GameLoadedEnginePatch
|
||||
static class GameLoadedTimeStoppedEnginePatch
|
||||
{
|
||||
public static EntitiesSubmissionScheduler Scheduler { get; private set; }
|
||||
public static void Postfix(StateSyncRegistrationHelper stateSyncReg)
|
||||
{
|
||||
// register all game engines, including deterministic
|
||||
GameEngineManager.RegisterEngines(stateSyncReg);
|
||||
Scheduler = stateSyncReg.enginesRoot.scheduler;
|
||||
// register command engines
|
||||
/*CommandLineCompositionRoot.Compose(contextHolder, stateSyncReg.enginesRoot, reloadGame, multiplayerParameters,
|
||||
stateSyncReg); - uREPL C# compilation not supported anymore */
|
||||
CommandManager.RegisterEngines(stateSyncReg.enginesRoot);
|
||||
}
|
||||
|
||||
public static MethodBase TargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(MainGameCompositionRoot), "DeterministicCompose").MakeGenericMethod(typeof(object));
|
||||
return AccessTools.Method(typeof(MainGameCompositionRoot), "DeterministicTimeStoppedCompose").MakeGenericMethod(typeof(object));
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch]
|
||||
static class GameLoadedTimeRunningEnginePatch
|
||||
{
|
||||
public static void Postfix(StateSyncRegistrationHelper stateSyncReg)
|
||||
{
|
||||
GameEngineManager.RegisterEngines(stateSyncReg);
|
||||
CommandManager.RegisterEngines(stateSyncReg.enginesRoot);
|
||||
}
|
||||
|
||||
public static MethodBase TargetMethod()
|
||||
{
|
||||
return AccessTools.Method(typeof(MainGameCompositionRoot), "DeterministicTimeRunningCompose").MakeGenericMethod(typeof(object));
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch]
|
||||
static class GameReloadedPatch
|
||||
{
|
||||
internal static bool IsReload;
|
||||
public static void Prefix() => IsReload = true;
|
||||
public static MethodBase TargetMethod() => AccessTools.Method(typeof(FullGameCompositionRoot), "ReloadGame");
|
||||
}
|
||||
|
||||
[HarmonyPatch]
|
||||
static class GameSwitchedToPatch
|
||||
{
|
||||
public static void Prefix() => GameReloadedPatch.IsReload = false;
|
||||
public static MethodBase TargetMethod() => AccessTools.Method(typeof(FullGameCompositionRoot), "SwitchToGame");
|
||||
}
|
||||
|
||||
[HarmonyPatch]
|
||||
static class MenuSwitchedToPatch
|
||||
{
|
||||
public static void Prefix() => GameReloadedPatch.IsReload = false;
|
||||
public static MethodBase TargetMethod() => AccessTools.Method(typeof(FullGameCompositionRoot), "SwitchToMenu");
|
||||
}
|
||||
|
||||
[HarmonyPatch]
|
||||
class MenuLoadedEnginePatch
|
||||
{
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
using System;
|
||||
using RobocraftX.Common.Input;
|
||||
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.Common.Input;
|
||||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.App;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Input
|
||||
{
|
||||
public static class FakeInput
|
||||
{
|
||||
private static readonly FakeInputEngine inputEngine = new FakeInputEngine();
|
||||
internal static readonly FakeInputEngine inputEngine = new FakeInputEngine();
|
||||
|
||||
/// <summary>
|
||||
/// Customize the local input.
|
||||
|
@ -103,39 +101,39 @@ namespace TechbloxModdingAPI.Input
|
|||
}
|
||||
|
||||
public static void ActionInput(uint playerID = uint.MaxValue, bool toggleMode = false, bool forward = false, bool backward = false, bool up = false, bool down = false, bool left = false, bool right = false, bool sprint = false, bool toggleFly = false, bool alt = false, bool primary = false, bool secondary = false, bool tertiary = false, bool primaryHeld = false, bool secondaryHeld = false, bool toggleUnitGrid = false, bool ctrl = false, bool toggleColourMode = false, bool scaleBlockUp = false, bool scaleBlockDown = false, bool rotateBlockClockwise = false, bool rotateBlockCounterclockwise = false, bool cutSelection = false, bool copySelection = false, bool deleteSelection = false)
|
||||
{
|
||||
if (playerID == uint.MaxValue)
|
||||
{
|
||||
playerID = inputEngine.GetLocalPlayerID();
|
||||
}
|
||||
ref LocalPlayerInputEntityStruct currentInput = ref inputEngine.GetPlayerInputRef(playerID);
|
||||
{ // TODO: We can only alter our own inputs clientside
|
||||
ref var currentInput = ref inputEngine._localInputCache;
|
||||
|
||||
//Utility.Logging.CommandLog($"Current sim frame {currentInput.frame}");
|
||||
// set inputs
|
||||
if (toggleMode) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.ToggleTimeRunningMode;
|
||||
if (forward) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.Forward;
|
||||
if (backward) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.Backward;
|
||||
if (up) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.Up;
|
||||
if (down) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.Down;
|
||||
if (left) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.Left;
|
||||
if (right) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.Right;
|
||||
if (sprint) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.Sprint;
|
||||
//if (toggleFly) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.SwitchFlyMode;
|
||||
//if (alt) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.AltAction;
|
||||
if (primary) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.PrimaryAction;
|
||||
if (secondary) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.SecondaryAction;
|
||||
if (tertiary) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.TertiaryAction;
|
||||
if (primaryHeld) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.PrimaryActionHeld;
|
||||
if (secondaryHeld) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.SecondaryActionHeld;
|
||||
//if (toggleUnitGrid) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.ToggleUnitGrid;
|
||||
if (ctrl) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.CtrlAction;
|
||||
if (toggleColourMode) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.ToggleColourMode;
|
||||
if (scaleBlockUp) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.ScaleBlockUp;
|
||||
if (scaleBlockDown) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.ScaleBlockDown;
|
||||
if (rotateBlockClockwise) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.RotateBlockClockwise;
|
||||
if (rotateBlockCounterclockwise) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.RotateBlockAnticlockwise;
|
||||
if (cutSelection) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.CutSelection;
|
||||
if (copySelection) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.CopySelection;
|
||||
if (deleteSelection) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.DeleteSelection;
|
||||
if (toggleMode) currentInput |= RobocraftX.Common.Input.ActionInput.ToggleTimeRunningModePlay; //TODO: Test, play
|
||||
if (forward) currentInput |= RobocraftX.Common.Input.ActionInput.Forward;
|
||||
if (backward) currentInput |= RobocraftX.Common.Input.ActionInput.Backward;
|
||||
if (up) currentInput |= RobocraftX.Common.Input.ActionInput.Up;
|
||||
if (down) currentInput |= RobocraftX.Common.Input.ActionInput.Down;
|
||||
if (left) currentInput |= RobocraftX.Common.Input.ActionInput.Left;
|
||||
if (right) currentInput |= RobocraftX.Common.Input.ActionInput.Right;
|
||||
if (sprint) currentInput |= RobocraftX.Common.Input.ActionInput.Sprint;
|
||||
//if (toggleFly) currentInput |= RobocraftX.Common.Input.ActionInput.SwitchFlyMode;
|
||||
//if (alt) currentInput |= RobocraftX.Common.Input.ActionInput.AltAction;
|
||||
if (primary) currentInput |= RobocraftX.Common.Input.ActionInput.PrimaryActionClick;
|
||||
if (secondary) currentInput |= RobocraftX.Common.Input.ActionInput.SecondaryActionClick;
|
||||
if (tertiary) currentInput |= RobocraftX.Common.Input.ActionInput.TertiaryAction;
|
||||
if (primaryHeld) currentInput |= RobocraftX.Common.Input.ActionInput.PrimaryActionHeld;
|
||||
if (secondaryHeld) currentInput |= RobocraftX.Common.Input.ActionInput.SecondaryActionHeld;
|
||||
//if (toggleUnitGrid) currentInput |= RobocraftX.Common.Input.ActionInput.ToggleUnitGrid;
|
||||
if (ctrl) currentInput |= RobocraftX.Common.Input.ActionInput.CtrlAction;
|
||||
if (toggleColourMode) currentInput |= RobocraftX.Common.Input.ActionInput.ToggleColourMode;
|
||||
if (scaleBlockUp) currentInput |= RobocraftX.Common.Input.ActionInput.ScaleBlockUp;
|
||||
if (scaleBlockDown) currentInput |= RobocraftX.Common.Input.ActionInput.ScaleBlockDown;
|
||||
if (rotateBlockClockwise) currentInput |= RobocraftX.Common.Input.ActionInput.RotateBlockClockwise;
|
||||
if (rotateBlockCounterclockwise) currentInput |= RobocraftX.Common.Input.ActionInput.RotateBlockAnticlockwise;
|
||||
if (cutSelection) currentInput |= RobocraftX.Common.Input.ActionInput.CutSelection;
|
||||
if (copySelection) currentInput |= RobocraftX.Common.Input.ActionInput.CopySelection;
|
||||
if (deleteSelection) currentInput |= RobocraftX.Common.Input.ActionInput.DeleteSelection;
|
||||
|
||||
if(Game.CurrentGame().IsTimeStopped)
|
||||
inputEngine.HandleCustomInput(); // Only gets called when online, so calling it here as well
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace TechbloxModdingAPI.Input
|
|||
|
||||
public bool IsReady = false;
|
||||
|
||||
internal ActionInput _localInputCache;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
IsReady = false;
|
||||
|
@ -86,6 +88,14 @@ namespace TechbloxModdingAPI.Input
|
|||
return ref entitiesDB.QueryEntity<LocalPlayerInputEntityStruct>(egid);
|
||||
}
|
||||
|
||||
internal void HandleCustomInput()
|
||||
{
|
||||
if (!LocalPlayerIDUtility.DoesLocalPlayerExist(entitiesDB))
|
||||
return;
|
||||
GetPlayerInputRef(GetLocalPlayerID()).actionMask |= _localInputCache;
|
||||
_localInputCache = default;
|
||||
}
|
||||
|
||||
public uint GetLocalPlayerID()
|
||||
{
|
||||
return LocalPlayerIDUtility.GetLocalPlayerID(entitiesDB);
|
||||
|
|
19
TechbloxModdingAPI/Input/FakeInputPatch.cs
Normal file
19
TechbloxModdingAPI/Input/FakeInputPatch.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
using System.Reflection;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace TechbloxModdingAPI.Input
|
||||
{
|
||||
[HarmonyPatch]
|
||||
public static class FakeInputPatch
|
||||
{
|
||||
public static void Prefix()
|
||||
{
|
||||
FakeInput.inputEngine.HandleCustomInput(); // This gets called right before the input is sent to the server
|
||||
}
|
||||
|
||||
public static MethodBase TargetMethod()
|
||||
{
|
||||
return AccessTools.Method("RobocraftX.Multiplayer.Input.NetworkInputRecorderEngine:RecordDeterministicInput");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +1,7 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TechbloxModdingAPI.App;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using Rewired.Internal;
|
||||
using Svelto.DataStructures;
|
||||
using Svelto.Tasks;
|
||||
using Svelto.Tasks.ExtraLean;
|
||||
using Svelto.Tasks.ExtraLean.Unity;
|
||||
using TechbloxModdingAPI.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TechbloxModdingAPI.Interface.IMGUI
|
||||
|
|
|
@ -3,13 +3,11 @@ using System.Reflection;
|
|||
using HarmonyLib;
|
||||
|
||||
using RobocraftX;
|
||||
using RobocraftX.Schedulers;
|
||||
using RobocraftX.Services;
|
||||
using Svelto.Context;
|
||||
using Svelto.Tasks.ExtraLean;
|
||||
|
||||
using TechbloxModdingAPI.App;
|
||||
using TechbloxModdingAPI.Blocks;
|
||||
using TechbloxModdingAPI.Events;
|
||||
using TechbloxModdingAPI.Tasks;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
|
@ -51,34 +49,42 @@ namespace TechbloxModdingAPI
|
|||
harmony.PatchAll(currentAssembly);
|
||||
}
|
||||
catch (Exception e)
|
||||
{ //Can't use ErrorBuilder or Logging.LogException (which eventually uses ErrorBuilder) yet
|
||||
Logging.Log(e.ToString());
|
||||
Logging.LogWarning("Failed to patch Techblox. Attempting to patch to display error...");
|
||||
harmony.Patch(AccessTools.Method(typeof(FullGameCompositionRoot), "OnContextInitialized")
|
||||
.MakeGenericMethod(typeof(UnityContext<FullGameCompositionRoot>)),
|
||||
new HarmonyMethod(((Action) OnPatchError).Method)); //Can't use lambdas here :(
|
||||
{
|
||||
HandleError(e, "Failed to patch Techblox. Attempting to patch to display error...", OnPatchError);
|
||||
return;
|
||||
}
|
||||
|
||||
// init utility
|
||||
Logging.MetaDebugLog($"Initializing Utility");
|
||||
Utility.GameState.Init();
|
||||
// init block implementors
|
||||
Logging.MetaDebugLog($"Initializing Blocks");
|
||||
// init input
|
||||
Input.FakeInput.Init();
|
||||
// init object-oriented classes
|
||||
Player.Init();
|
||||
Block.Init();
|
||||
BlockGroup.Init();
|
||||
Wire.Init();
|
||||
Logging.MetaDebugLog($"Initializing Client");
|
||||
Client.Init();
|
||||
Game.Init();
|
||||
// init UI
|
||||
Interface.IMGUI.Constants.Init();
|
||||
Interface.IMGUI.IMGUIManager.Init();
|
||||
Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} initialized");
|
||||
try
|
||||
{
|
||||
// init utility
|
||||
Logging.MetaDebugLog($"Initializing Utility");
|
||||
Utility.GameState.Init();
|
||||
// init block implementors
|
||||
Logging.MetaDebugLog($"Initializing Blocks");
|
||||
// init input
|
||||
Input.FakeInput.Init();
|
||||
// init object-oriented classes
|
||||
Player.Init();
|
||||
Block.Init();
|
||||
BlockGroup.Init();
|
||||
Wire.Init();
|
||||
// init client
|
||||
Logging.MetaDebugLog($"Initializing Client");
|
||||
Client.Init();
|
||||
Game.Init();
|
||||
// init UI
|
||||
Logging.MetaDebugLog($"Initializing UI");
|
||||
Interface.IMGUI.Constants.Init();
|
||||
Interface.IMGUI.IMGUIManager.Init();
|
||||
// init anti-anticheat
|
||||
Logging.MetaDebugLog("Initializing anti-anticheat");
|
||||
AntiAntiCheatPatch.Init(harmony);
|
||||
Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} initialized");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
HandleError(e, "Failed to initialize the API! Attempting to patch to display error...", OnInitError);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -109,5 +115,26 @@ namespace TechbloxModdingAPI
|
|||
ErrorBuilder.DisplayMustQuitError("Failed to patch Techblox!\n" +
|
||||
"Make sure you're using the latest version of TechbloxModdingAPI or disable mods if the API isn't released yet.");
|
||||
}
|
||||
|
||||
private static void OnInitError()
|
||||
{
|
||||
ErrorBuilder.DisplayMustQuitError("Failed to initialize the modding API!\n" +
|
||||
"Make sure you're using the latest version. If you are, please report the error.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles an init error. Logs the exception, a log message, and allows displaying an error in-game.
|
||||
/// </summary>
|
||||
/// <param name="e">The exception</param>
|
||||
/// <param name="logMsg">The log message</param>
|
||||
/// <param name="onInit">The action to run when the game is ready to display error messages</param>
|
||||
private static void HandleError(Exception e, string logMsg, Action onInit)
|
||||
{ //Can't use ErrorBuilder or Logging.LogException (which eventually uses ErrorBuilder) yet
|
||||
Logging.Log(e.ToString());
|
||||
Logging.LogWarning(logMsg);
|
||||
harmony.Patch(AccessTools.Method(typeof(FullGameCompositionRoot), "OnContextInitialized")
|
||||
.MakeGenericMethod(typeof(UnityContext<FullGameCompositionRoot>)),
|
||||
new HarmonyMethod(onInit.Method)); //Can't use lambdas here :(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace TechbloxModdingAPI.Persistence
|
|||
Logging.MetaDebugLog("Skipping component serialization: no serializers registered!");
|
||||
return;
|
||||
}
|
||||
serializationData.data.ExpandBy((uint)frameStart.Length);
|
||||
serializationData.data.IncreaseCapacityBy((uint)frameStart.Length);
|
||||
BinaryBufferWriter bbw = new BinaryBufferWriter(serializationData.data.ToArrayFast(out int buffLen), serializationData.dataPos);
|
||||
uint originalPos = serializationData.dataPos;
|
||||
Logging.MetaDebugLog($"dataPos: {originalPos}");
|
||||
|
@ -35,14 +35,14 @@ namespace TechbloxModdingAPI.Persistence
|
|||
bbw.Write(frameStart[i]);
|
||||
}
|
||||
Logging.MetaDebugLog($"dataPos (after frame start): {bbw.Position}");
|
||||
serializationData.data.ExpandBy(4u);
|
||||
serializationData.data.IncreaseCapacityBy(4u);
|
||||
bbw.Write((uint)SerializerManager.GetSerializersCount());
|
||||
string[] serializerKeys = SerializerManager.GetSerializerNames();
|
||||
for (uint c = 0; c < serializerKeys.Length; c++)
|
||||
{
|
||||
Logging.MetaDebugLog($"dataPos (loop start): {bbw.Position}");
|
||||
// write component info
|
||||
serializationData.data.ExpandBy(4u + (uint)serializerKeys[c].Length);
|
||||
serializationData.data.IncreaseCapacityBy(4u + (uint)serializerKeys[c].Length);
|
||||
bbw.Write((uint)serializerKeys[c].Length);
|
||||
Logging.MetaDebugLog($"dataPos (now): {bbw.Position}");
|
||||
byte[] nameBytes = Encoding.UTF8.GetBytes(serializerKeys[c]);
|
||||
|
@ -51,7 +51,7 @@ namespace TechbloxModdingAPI.Persistence
|
|||
bbw.Write(nameBytes[i]);
|
||||
}
|
||||
Logging.MetaDebugLog($"dataPos (now): {bbw.Position}");
|
||||
serializationData.data.ExpandBy(4u);
|
||||
serializationData.data.IncreaseCapacityBy(4u);
|
||||
serializationData.dataPos = bbw.Position + 4u;
|
||||
Logging.MetaDebugLog($"dataPos (now): {bbw.Position}");
|
||||
Logging.MetaDebugLog($"dataPos (appears to be): {serializationData.dataPos}");
|
||||
|
@ -73,8 +73,8 @@ namespace TechbloxModdingAPI.Persistence
|
|||
}
|
||||
|
||||
public static MethodBase TargetMethod()
|
||||
{
|
||||
return typeof(SaveGameEngine).GetMethod("SerializeGameToBuffer");
|
||||
{
|
||||
return AccessTools.TypeByName("RobocraftX.SaveAndLoad.SaveGameEngine").GetMethod("SerializeGameToBuffer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace TechbloxModdingAPI.Persistence
|
|||
|
||||
public bool Serialize(ref ISerializationData serializationData, EntitiesDB entitiesDB, IEntitySerialization entitySerializer)
|
||||
{
|
||||
serializationData.data.ExpandBy(4u);
|
||||
serializationData.data.IncreaseCapacityBy(4u);
|
||||
BinaryBufferWriter bbw = new BinaryBufferWriter(serializationData.data.ToArrayFast(out int count), serializationData.dataPos);
|
||||
EGID[] toSerialize = getEntitiesToSerialize(entitiesDB);
|
||||
bbw.Write((uint)toSerialize.Length);
|
||||
|
|
|
@ -20,6 +20,22 @@ namespace TechbloxModdingAPI
|
|||
add => seatExited += value;
|
||||
remove => seatExited -= value;
|
||||
}
|
||||
|
||||
internal static WrappedHandler<PlayerEventArgs> joined;
|
||||
|
||||
public static event EventHandler<PlayerEventArgs> Joined
|
||||
{
|
||||
add => joined += value;
|
||||
remove => joined -= value;
|
||||
}
|
||||
|
||||
internal static WrappedHandler<PlayerEventArgs> left;
|
||||
|
||||
public static event EventHandler<PlayerEventArgs> Left
|
||||
{
|
||||
add => left += value;
|
||||
remove => left -= value;
|
||||
}
|
||||
}
|
||||
|
||||
public struct PlayerSeatEventArgs
|
||||
|
@ -27,4 +43,10 @@ namespace TechbloxModdingAPI
|
|||
public EGID SeatId;
|
||||
public Seat Seat => (Seat)Block.New(SeatId);
|
||||
}
|
||||
|
||||
public struct PlayerEventArgs
|
||||
{
|
||||
public EGID PlayerId;
|
||||
public Player Player => Player.GetInstance(PlayerId.entityID);
|
||||
}
|
||||
}
|
|
@ -23,8 +23,8 @@ namespace TechbloxModdingAPI
|
|||
public partial class Player : EcsObjectBase, IEquatable<Player>, IEquatable<EGID>
|
||||
{
|
||||
// static functionality
|
||||
private static PlayerEngine playerEngine = new PlayerEngine();
|
||||
private static PlayerEventsEngine playerEventsEngine = new PlayerEventsEngine();
|
||||
private static readonly PlayerEngine playerEngine = new PlayerEngine();
|
||||
private static readonly PlayerEventsEngine playerEventsEngine = new PlayerEventsEngine();
|
||||
private static Player localPlayer;
|
||||
|
||||
/// <summary>
|
||||
|
@ -76,6 +76,12 @@ namespace TechbloxModdingAPI
|
|||
}
|
||||
}
|
||||
|
||||
internal static Player GetInstance(uint id)
|
||||
{
|
||||
return EcsObjectBase.GetInstance(new EGID(id, CharacterExclusiveGroups.OnFootGroup),
|
||||
e => new Player(e.entityID));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:TechbloxModdingAPI.Player"/> class.
|
||||
/// </summary>
|
||||
|
@ -119,6 +125,7 @@ namespace TechbloxModdingAPI
|
|||
})
|
||||
{
|
||||
this.Type = player;
|
||||
Id = base.Id.entityID;
|
||||
}
|
||||
|
||||
// object fields & properties
|
||||
|
@ -187,8 +194,6 @@ namespace TechbloxModdingAPI
|
|||
public float Mass =>
|
||||
1f / playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().physicsMass.InverseMass;
|
||||
|
||||
private float _ping = -1f;
|
||||
|
||||
/// <summary>
|
||||
/// The player's latest network ping time.
|
||||
/// </summary>
|
||||
|
@ -197,12 +202,7 @@ namespace TechbloxModdingAPI
|
|||
{
|
||||
get
|
||||
{
|
||||
var opt = playerEngine.GetPlayerStruct<PlayerNetworkStatsEntityStruct>(Id, Type);
|
||||
if (opt)
|
||||
{
|
||||
_ping = opt.Get().lastPingTimeSinceLevelLoad ?? _ping;
|
||||
}
|
||||
return _ping;
|
||||
return playerEngine.GetPing() / 1000f;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -435,15 +435,38 @@ namespace TechbloxModdingAPI
|
|||
playerEngine.SetLocation(Id, location, exitSeat: exitSeat);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enter the given seat.
|
||||
/// </summary>
|
||||
/// <param name="seat">The seat to enter.</param>
|
||||
public void EnterSeat(Seat seat)
|
||||
{
|
||||
playerEngine.EnterSeat(Id, seat.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exit the seat the player is currently in.
|
||||
/// </summary>
|
||||
public void ExitSeat()
|
||||
{
|
||||
playerEngine.ExitSeat(Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spawn the machine the player is holding in time running mode.
|
||||
/// </summary>
|
||||
public bool SpawnMachine()
|
||||
{
|
||||
return playerEngine.SpawnMachine(Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Despawn the player's machine in time running mode and place it in their hand.
|
||||
/// </summary>
|
||||
public bool DespawnMachine()
|
||||
{
|
||||
return playerEngine.DespawnMachine(Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the block the player is currently looking at in build mode.
|
||||
|
@ -481,7 +504,7 @@ namespace TechbloxModdingAPI
|
|||
{
|
||||
var egid = playerEngine.GetThingLookedAt(Id, maxDistance);
|
||||
return egid != default && egid.groupID == WiresGUIExclusiveGroups.WireGroup
|
||||
? EcsObjectBase.GetInstance(new EGID(egid.entityID, NamedExclusiveGroup<WiresGroup>.Group),
|
||||
? EcsObjectBase.GetInstance(new EGID(egid.entityID, BuildModeWiresGroups.WiresGroup.Group),
|
||||
e => new Wire(e))
|
||||
: null;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,9 @@ using RobocraftX.Physics;
|
|||
using RobocraftX.Blocks.Ghost;
|
||||
using Gamecraft.GUI.HUDFeedbackBlocks;
|
||||
using RobocraftX.Blocks;
|
||||
using RobocraftX.Multiplayer;
|
||||
using RobocraftX.PilotSeat;
|
||||
using RobocraftX.SimulationModeState;
|
||||
using Svelto.ECS;
|
||||
using Techblox.Camera;
|
||||
using Unity.Mathematics;
|
||||
|
@ -19,6 +21,7 @@ using Svelto.ECS.EntityStructs;
|
|||
using Techblox.BuildingDrone;
|
||||
|
||||
using TechbloxModdingAPI.Engines;
|
||||
using TechbloxModdingAPI.Input;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Players
|
||||
|
@ -204,6 +207,8 @@ namespace TechbloxModdingAPI.Players
|
|||
|
||||
public void EnterSeat(uint playerId, EGID seatId)
|
||||
{
|
||||
if (!TimeRunningModeUtil.IsTimeRunningMode(entitiesDB))
|
||||
return;
|
||||
PilotSeatGroupUtils.SwapTagTo<OCCUPIED_TAG>(Functions, seatId);
|
||||
var opt = GetCharacterStruct<CharacterPilotSeatEntityStruct>(playerId, out var group);
|
||||
if (!opt) return;
|
||||
|
@ -221,11 +226,46 @@ namespace TechbloxModdingAPI.Players
|
|||
|
||||
public void ExitSeat(uint playerId)
|
||||
{
|
||||
if (!TimeRunningModeUtil.IsTimeRunningMode(entitiesDB))
|
||||
return;
|
||||
EGID egid = new EGID(playerId, CharacterExclusiveGroups.InPilotSeatGroup);
|
||||
var opt = entitiesDB.QueryEntityOptional<CharacterPilotSeatEntityStruct>(egid);
|
||||
if (!opt) return;
|
||||
opt.Get().instantExit = true;
|
||||
entitiesDB.PublishEntityChange<CharacterPilotSeatEntityStruct>(egid);
|
||||
}
|
||||
|
||||
public bool SpawnMachine(uint playerId)
|
||||
{
|
||||
if (!TimeRunningModeUtil.IsTimeRunningMode(entitiesDB))
|
||||
return false;
|
||||
EGID egid = new EGID(playerId, CharacterExclusiveGroups.MachineSpawningGroup);
|
||||
if (!entitiesDB.Exists<CharacterTagEntityStruct>(egid))
|
||||
return false;
|
||||
//Functions.SwapEntityGroup<CharacterEntityDescriptor>(egid, CharacterExclusiveGroups.OnFootGroup);
|
||||
FakeInput.ActionInput(playerId, primary: true);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool DespawnMachine(uint playerId)
|
||||
{
|
||||
if (!TimeRunningModeUtil.IsTimeRunningMode(entitiesDB))
|
||||
return false;
|
||||
GetCharacterStruct<CharacterTagEntityStruct>(playerId, out var group);
|
||||
if (group.isInvalid)
|
||||
return false;
|
||||
EGID egid = new EGID(playerId, group);
|
||||
if (!entitiesDB.Exists<CharacterTagEntityStruct>(egid))
|
||||
return false;
|
||||
Functions.SwapEntityGroup<CharacterEntityDescriptor>(egid, CharacterExclusiveGroups.MachineSpawningGroup);
|
||||
return true;
|
||||
}
|
||||
|
||||
public uint GetPing()
|
||||
{
|
||||
return entitiesDB
|
||||
.QueryUniqueEntity<NetworkStatsEntityStruct>(MultiplayerExclusiveGroups.MultiplayerStateGroup)
|
||||
.networkStats.PingMs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
using RobocraftX.Character;
|
||||
using RobocraftX.Character.Movement;
|
||||
using RobocraftX.Common.Input;
|
||||
using Svelto.ECS;
|
||||
|
||||
using TechbloxModdingAPI.Engines;
|
||||
|
||||
namespace TechbloxModdingAPI.Players
|
||||
{
|
||||
public class PlayerEventsEngine : IApiEngine, IReactOnSwap<CharacterPilotSeatEntityStruct>
|
||||
public class PlayerEventsEngine : IApiEngine, IReactOnSwap<CharacterPilotSeatEntityStruct>, IReactOnAddAndRemove<PlayerIDStruct>
|
||||
{
|
||||
public void Ready()
|
||||
{
|
||||
|
@ -21,13 +23,22 @@ namespace TechbloxModdingAPI.Players
|
|||
|
||||
public void MovedTo(ref CharacterPilotSeatEntityStruct entityComponent, ExclusiveGroupStruct previousGroup, EGID egid)
|
||||
{
|
||||
var seatId = entityComponent.pilotSeatEntity.ToEGID(entitiesDB);
|
||||
var player = EcsObjectBase.GetInstance(new EGID(egid.entityID, CharacterExclusiveGroups.OnFootGroup),
|
||||
e => new Player(e.entityID));
|
||||
entitiesDB.TryGetEGID(entityComponent.pilotSeatEntity, out var seatId); //TODO: Can't get EGID
|
||||
var player = Player.GetInstance(egid.entityID);
|
||||
if (previousGroup == CharacterExclusiveGroups.InPilotSeatGroup)
|
||||
player.seatExited.Invoke(this, new PlayerSeatEventArgs { SeatId = seatId});
|
||||
else if (egid.groupID == CharacterExclusiveGroups.InPilotSeatGroup)
|
||||
player.seatEntered.Invoke(this, new PlayerSeatEventArgs { SeatId = seatId });
|
||||
}
|
||||
|
||||
public void Add(ref PlayerIDStruct entityComponent, EGID egid)
|
||||
{
|
||||
Player.joined.Invoke(this, new PlayerEventArgs { PlayerId = egid });
|
||||
}
|
||||
|
||||
public void Remove(ref PlayerIDStruct entityComponent, EGID egid)
|
||||
{
|
||||
Player.left.Invoke(this, new PlayerEventArgs { PlayerId = egid });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Svelto.Tasks;
|
||||
using Svelto.Tasks.Enumerators;
|
||||
|
@ -7,6 +8,7 @@ using Unity.Mathematics;
|
|||
using TechbloxModdingAPI.App;
|
||||
using TechbloxModdingAPI.Blocks;
|
||||
using TechbloxModdingAPI.Tests;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Players
|
||||
{
|
||||
|
@ -45,7 +47,20 @@ namespace TechbloxModdingAPI.Players
|
|||
[APITestCase(TestType.SimulationMode)]
|
||||
public static IEnumerator<TaskContract> SeatEventTestSim()
|
||||
{
|
||||
yield return new WaitForSecondsEnumerator(1).Continue();
|
||||
Assert.Equal(Player.LocalPlayer.SpawnMachine(), true, "Failed to spawn the player's machine.", "Successfully spawned the player's machine.");
|
||||
yield return new WaitForSecondsEnumerator(1).Continue();
|
||||
var seats = Game.CurrentGame().GetBlocksInGame(BlockIDs.DriverSeat);
|
||||
int c = 0;
|
||||
while (seats.Length == 0 && c < 10)
|
||||
{
|
||||
Logging.MetaLog("Waiting for a seat to be spawned...");
|
||||
yield return new WaitForSecondsEnumerator(1).Continue();
|
||||
Console.WriteLine("Spawn machine: " + Player.LocalPlayer.SpawnMachine());
|
||||
seats = Game.CurrentGame().GetBlocksInGame(BlockIDs.DriverSeat);
|
||||
c++;
|
||||
}
|
||||
|
||||
if (seats.Length == 0)
|
||||
{
|
||||
Assert.Fail("No driver seat found!");
|
||||
|
|
16
TechbloxModdingAPI/Tasks/OnGuiRunner.cs
Normal file
16
TechbloxModdingAPI/Tasks/OnGuiRunner.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using System.Collections;
|
||||
using Svelto.Tasks;
|
||||
using Svelto.Tasks.ExtraLean;
|
||||
using Svelto.Tasks.Unity.Internal;
|
||||
|
||||
namespace TechbloxModdingAPI.Tasks
|
||||
{
|
||||
public class OnGuiRunner : BaseRunner<ExtraLeanSveltoTask<IEnumerator>>
|
||||
{
|
||||
public OnGuiRunner(string name, uint runningOrder = 0)
|
||||
: base(name)
|
||||
{
|
||||
UnityCoroutineRunner.StartOnGuiCoroutine(this._processEnumerator, runningOrder);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ namespace TechbloxModdingAPI.Tasks
|
|||
{
|
||||
get
|
||||
{
|
||||
return RobocraftX.Schedulers.Lean.UIScheduler;
|
||||
return RobocraftX.Schedulers.ClientLean.UIScheduler;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ namespace TechbloxModdingAPI.Tasks
|
|||
{
|
||||
get
|
||||
{
|
||||
return RobocraftX.Schedulers.ExtraLean.UIScheduler;
|
||||
return RobocraftX.Schedulers.ClientExtraLean.UIScheduler;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,12 +10,10 @@ using IllusionInjector;
|
|||
using RobocraftX.FrontEnd;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
using RobocraftX.Common.Input;
|
||||
using Svelto.Tasks;
|
||||
using Svelto.Tasks.Lean;
|
||||
using TechbloxModdingAPI.Blocks;
|
||||
using TechbloxModdingAPI.Commands;
|
||||
using TechbloxModdingAPI.Input;
|
||||
using TechbloxModdingAPI.Players;
|
||||
using TechbloxModdingAPI.Tasks;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
@ -345,6 +343,11 @@ namespace TechbloxModdingAPI.Tests
|
|||
Logging.CommandLog(asset);
|
||||
}
|
||||
}).Build();
|
||||
Client.EnterMenu += (sender, args) => Scheduler.Schedule(new Once(() => Client.Instance.CloseBetaPopup()));
|
||||
|
||||
Game.Enter += (sender, args) =>
|
||||
Console.WriteLine(
|
||||
$"Current game selection data: {FullGameFields._gameSelectionData.gameMode} - {FullGameFields._gameSelectionData.saveType}");
|
||||
#if TEST
|
||||
TestRoot.RunTests();
|
||||
#endif
|
||||
|
@ -360,15 +363,6 @@ namespace TechbloxModdingAPI.Tests
|
|||
return modsString = sb.ToString();
|
||||
}
|
||||
|
||||
public override void OnUpdate()
|
||||
{
|
||||
if (UnityEngine.Input.GetKeyDown(KeyCode.End))
|
||||
{
|
||||
Console.WriteLine("Pressed button to toggle console");
|
||||
FakeInput.CustomInput(new LocalCosmeticInputEntityComponent {commandLineToggleInput = true});
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch]
|
||||
public class MinimumSpecsPatch
|
||||
{
|
||||
|
|
|
@ -7,7 +7,9 @@ using System.Linq; // welcome to the dark side
|
|||
using Svelto.Tasks;
|
||||
using Svelto.Tasks.Lean;
|
||||
using Svelto.Tasks.Enumerators;
|
||||
using Svelto.Tasks.Lean.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
using TechbloxModdingAPI.App;
|
||||
using TechbloxModdingAPI.Tasks;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
@ -64,7 +66,7 @@ namespace TechbloxModdingAPI.Tests
|
|||
_testsCountPassed = 0;
|
||||
_testsCountFailed = 0;
|
||||
// flow control
|
||||
Game.Enter += (sender, args) => { GameTests().RunOn(RobocraftX.Schedulers.Lean.EveryFrameStepRunner_TimeRunningAndStopped); };
|
||||
Game.Enter += (sender, args) => { GameTests().RunOn(new UpdateMonoRunner("TechbloxModdingAPITestRunner")); };
|
||||
Game.Exit += (s, a) => state = "ReturningFromGame";
|
||||
Client.EnterMenu += (sender, args) =>
|
||||
{
|
||||
|
@ -129,7 +131,7 @@ namespace TechbloxModdingAPI.Tests
|
|||
|
||||
private static IEnumerator<TaskContract> GoToGameTests()
|
||||
{
|
||||
Client app = new Client();
|
||||
Client app = Client.Instance;
|
||||
int oldLength = 0;
|
||||
while (app.MyGames.Length == 0 || oldLength != app.MyGames.Length)
|
||||
{
|
||||
|
@ -137,7 +139,15 @@ namespace TechbloxModdingAPI.Tests
|
|||
yield return new WaitForSecondsEnumerator(1).Continue();
|
||||
}
|
||||
yield return Yield.It;
|
||||
app.MyGames[0].EnterGame();
|
||||
try
|
||||
{
|
||||
app.MyGames[0].EnterGame();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Failed to go to game tests");
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
/*Game newGame = Game.NewGame();
|
||||
yield return new WaitForSecondsEnumerator(5).Continue(); // wait for sync
|
||||
newGame.EnterGame();*/
|
||||
|
@ -157,6 +167,7 @@ namespace TechbloxModdingAPI.Tests
|
|||
};
|
||||
for (var index = 0; index < testTypesToRun.Length; index++)
|
||||
{
|
||||
Logging.MetaLog($"Running test type {testTypesToRun[index]}");
|
||||
foreach (Type t in testTypes)
|
||||
{
|
||||
foreach (MethodBase m in t.GetMethods())
|
||||
|
@ -198,7 +209,16 @@ namespace TechbloxModdingAPI.Tests
|
|||
}
|
||||
|
||||
if (index + 1 < testTypesToRun.Length) //Don't toggle on the last test
|
||||
{
|
||||
bool running = currentGame.IsTimeRunning;
|
||||
currentGame.ToggleTimeMode();
|
||||
while (running ? !currentGame.IsTimeStopped : !currentGame.IsTimeRunning)
|
||||
{
|
||||
Logging.MetaLog($"Waiting for time to {(running?"stop":"start")}...");
|
||||
yield return new WaitForSecondsEnumerator(1).Continue();
|
||||
}
|
||||
}
|
||||
|
||||
yield return new WaitForSecondsEnumerator(5).Continue();
|
||||
}
|
||||
// exit game
|
||||
|
|
|
@ -1,20 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using DataLoader;
|
||||
using DataLoader;
|
||||
using HarmonyLib;
|
||||
using RobocraftX;
|
||||
using RobocraftX.Common.Utilities;
|
||||
using RobocraftX.CR.MainGame;
|
||||
using RobocraftX.GUI;
|
||||
using RobocraftX.Multiplayer;
|
||||
using RobocraftX.Rendering;
|
||||
using Svelto.Context;
|
||||
using Svelto.DataStructures;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.Schedulers;
|
||||
using Svelto.ECS.GUI;
|
||||
using Techblox.GameSelection;
|
||||
using UnityEngine;
|
||||
using Unity.Entities;
|
||||
using Unity.Physics.Systems;
|
||||
|
@ -104,14 +98,6 @@ namespace TechbloxModdingAPI.Utility
|
|||
}
|
||||
}
|
||||
|
||||
public static PhysicsUtility _physicsUtility
|
||||
{
|
||||
get
|
||||
{
|
||||
return (PhysicsUtility)fgcr?.Field("_physicsUtility").GetValue();
|
||||
}
|
||||
}
|
||||
|
||||
/*public static UnityEntitySubmissionScheduler _frontEndSubmissionScheduler
|
||||
{
|
||||
get
|
||||
|
@ -136,11 +122,11 @@ namespace TechbloxModdingAPI.Utility
|
|||
}
|
||||
}
|
||||
|
||||
public static ECSGameObjectResourceManager _eCsGameObjectResourceManager
|
||||
public static ECSResourceManagers _managers
|
||||
{
|
||||
get
|
||||
{
|
||||
return (ECSGameObjectResourceManager)fgcr?.Field("_eCsGameObjectResourceManager").GetValue();
|
||||
return (ECSResourceManagers)fgcr?.Field("_managers").GetValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,6 +146,22 @@ namespace TechbloxModdingAPI.Utility
|
|||
}
|
||||
}
|
||||
|
||||
public static SveltoGUI _frontEndGUI
|
||||
{
|
||||
get
|
||||
{
|
||||
return (SveltoGUI)fgcr?.Field("_frontEndGUI").GetValue();
|
||||
}
|
||||
}
|
||||
|
||||
public static GameSelectionData _gameSelectionData
|
||||
{
|
||||
get
|
||||
{
|
||||
return (GameSelectionData)fgcr?.Field("_gameSelectionData").GetValue();
|
||||
}
|
||||
}
|
||||
|
||||
private static Traverse fgcr;
|
||||
|
||||
public static void Init(FullGameCompositionRoot instance)
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using RobocraftX.StateSync;
|
||||
using Svelto.ECS;
|
||||
|
|
|
@ -34,6 +34,12 @@ namespace TechbloxModdingAPI.Utility
|
|||
Logging.LogWarning(wrappedException.ToString());
|
||||
}
|
||||
};
|
||||
if (wrappers.ContainsKey(added))
|
||||
{
|
||||
original.eventHandler -= wrapped;
|
||||
wrappers.Remove(added);
|
||||
}
|
||||
|
||||
wrappers.Add(added, wrapped);
|
||||
return new WrappedHandler<T> { eventHandler = original.eventHandler + wrapped };
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue