Compare commits
No commits in common. "preview" and "v1.4.0-preview" have entirely different histories.
preview
...
v1.4.0-pre
189 changed files with 7484 additions and 11987 deletions
|
@ -1,67 +0,0 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import argparse
|
||||
import re
|
||||
# this assumes a mostly semver-complient version number
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Increment GamecraftModdingAPI version")
|
||||
parser.add_argument('version', metavar="VN", type=str, help="The version number to increment, or the index of the number (zero-indexed).")
|
||||
args = parser.parse_args()
|
||||
|
||||
version_index = -1
|
||||
try:
|
||||
version_index = int(args.version)
|
||||
except Exception:
|
||||
if args.version.lower() == "major":
|
||||
version_index = 0
|
||||
elif args.version.lower() == "minor":
|
||||
version_index = 1
|
||||
elif args.version.lower() == "patch":
|
||||
version_index = 2
|
||||
|
||||
if version_index < 0:
|
||||
print("Could not parse version argument.")
|
||||
exit(version_index)
|
||||
|
||||
print(version_index)
|
||||
old_version = ""
|
||||
new_version = ""
|
||||
|
||||
with open("../GamecraftModdingAPI/GamecraftModdingAPI.csproj", "r") as xmlFile:
|
||||
print("Parsing GamecraftModdingAPI.csproj")
|
||||
fileStr = xmlFile.read()
|
||||
versionMatch = re.search(r"<Version>(.+)</Version>", fileStr)
|
||||
if versionMatch is None:
|
||||
print("Unable to find version number in GamecraftModdingAPI.csproj")
|
||||
exit(1)
|
||||
old_version = versionMatch.group(1)
|
||||
versionList = old_version.split(".")
|
||||
if len(versionList) <= version_index:
|
||||
print("Invalid version string")
|
||||
exit(1)
|
||||
versionList[version_index] = str(int(versionList[version_index]) + 1)
|
||||
for i in range(version_index + 1, len(versionList)):
|
||||
try:
|
||||
int(versionList[i])
|
||||
versionList[i] = "0"
|
||||
except Exception:
|
||||
tmp = versionList[i].split("-")
|
||||
tmp[0] = "0"
|
||||
versionList[i] = "-".join(tmp)
|
||||
new_version = ".".join(versionList)
|
||||
print(new_version)
|
||||
newFileContents = fileStr.replace("<Version>"+old_version+"</Version>", "<Version>"+new_version+"</Version>")
|
||||
|
||||
with open("../GamecraftModdingAPI/GamecraftModdingAPI.csproj", "w") as xmlFile:
|
||||
print("Writing new version to project file")
|
||||
xmlFile.write(newFileContents)
|
||||
|
||||
with open("../doxygen.conf", "r") as doxFile:
|
||||
print("Parsing doxygen.conf")
|
||||
doxStr = doxFile.read()
|
||||
newFileContents = doxStr.replace("= \"v" + old_version + "\"", "= \"v" + new_version + "\"")
|
||||
|
||||
with open("../doxygen.conf", "w") as doxFile:
|
||||
print("Writing new version to doxygen config")
|
||||
doxFile.write(newFileContents)
|
19
Automation/gen_csproj.py
Executable file → Normal file
19
Automation/gen_csproj.py
Executable file → Normal file
|
@ -3,22 +3,15 @@
|
|||
import argparse
|
||||
from pathlib import Path, PurePath
|
||||
import re
|
||||
import os
|
||||
|
||||
DLL_EXCLUSIONS_REGEX = r"(System|Microsoft|Mono|IronPython|DiscordRPC)\."
|
||||
|
||||
def getAssemblyReferences(path):
|
||||
asmDir = Path(path)
|
||||
result = list()
|
||||
addedPath = ""
|
||||
if not asmDir.exists():
|
||||
addedPath = "../"
|
||||
asmDir = Path(addedPath + path)
|
||||
for child in asmDir.iterdir():
|
||||
if child.is_file() and re.search(DLL_EXCLUSIONS_REGEX, str(child), re.I) is None and str(child).lower().endswith(".dll"):
|
||||
childstr = str(child)
|
||||
childstr = os.path.relpath(childstr, addedPath).replace("\\", "/")
|
||||
result.append(childstr)
|
||||
result.append(str(child).replace("\\", "/"))
|
||||
return result
|
||||
|
||||
def buildReferencesXml(path):
|
||||
|
@ -34,16 +27,16 @@ def buildReferencesXml(path):
|
|||
return "<!--Start Dependencies-->\n <ItemGroup>\n" + "".join(result) + " </ItemGroup>\n<!--End Dependencies-->"
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generate TechbloxModdingAPI.csproj")
|
||||
parser = argparse.ArgumentParser(description="Generate GamecraftModdingAPI.csproj")
|
||||
# TODO (maybe?): add params for custom csproj read and write locations
|
||||
args = parser.parse_args()
|
||||
|
||||
print("Building Assembly references")
|
||||
asmXml = buildReferencesXml("../ref_preview/TechbloxPreview_Data/Managed")
|
||||
asmXml = buildReferencesXml("../ref/GamecraftPreview_Data/Managed")
|
||||
# print(asmXml)
|
||||
|
||||
with open("../TechbloxModdingAPI/TechbloxModdingAPI.csproj", "r") as xmlFile:
|
||||
print("Parsing TechbloxModdingAPI.csproj")
|
||||
with open("../GamecraftModdingAPI/GamecraftModdingAPI.csproj", "r") as xmlFile:
|
||||
print("Parsing GamecraftModdingAPI.csproj")
|
||||
fileStr = xmlFile.read()
|
||||
# print(fileStr)
|
||||
depsStart = re.search(r"\<!--\s*Start\s+Dependencies\s*--\>", fileStr)
|
||||
|
@ -52,7 +45,7 @@ if __name__ == "__main__":
|
|||
print("Unable to find dependency XML comments, aborting!")
|
||||
exit(1)
|
||||
newFileStr = fileStr[:depsStart.start()] + "\n" + asmXml + "\n" + fileStr[depsEnd.end() + 1:]
|
||||
with open("../TechbloxModdingAPI/TechbloxModdingAPI.csproj", "w") as xmlFile:
|
||||
with open("../GamecraftModdingAPI/GamecraftModdingAPI.csproj", "w") as xmlFile:
|
||||
print("Writing Assembly references")
|
||||
xmlFile.write(newFileStr)
|
||||
# print(newFileStr)
|
||||
|
|
|
@ -1,142 +0,0 @@
|
|||
using System;
|
||||
using System.CodeDom;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Gamecraft.Tweaks;
|
||||
using RobocraftX.Common;
|
||||
using Svelto.ECS;
|
||||
using Techblox.EngineBlock;
|
||||
|
||||
namespace CodeGenerator
|
||||
{
|
||||
public class BlockClassGenerator
|
||||
{
|
||||
public void Generate(string name, string group = null, Dictionary<string, string> renames = null, params Type[] types)
|
||||
{
|
||||
if (group is null)
|
||||
{
|
||||
group = GetGroup(name) + "_BLOCK_GROUP";
|
||||
if (typeof(CommonExclusiveGroups).GetFields().All(field => field.Name != group))
|
||||
group = GetGroup(name) + "_BLOCK_BUILD_GROUP";
|
||||
}
|
||||
|
||||
if (!group.Contains("."))
|
||||
group = "CommonExclusiveGroups." + group;
|
||||
|
||||
var codeUnit = new CodeCompileUnit();
|
||||
var ns = new CodeNamespace("TechbloxModdingAPI.Blocks");
|
||||
ns.Imports.Add(new CodeNamespaceImport("RobocraftX.Common"));
|
||||
ns.Imports.Add(new CodeNamespaceImport("Svelto.ECS"));
|
||||
var cl = new CodeTypeDeclaration(name);
|
||||
//cl.BaseTypes.Add(baseClass != null ? new CodeTypeReference(baseClass) : new CodeTypeReference("Block"));
|
||||
cl.BaseTypes.Add(new CodeTypeReference("SignalingBlock"));
|
||||
cl.Members.Add(new CodeConstructor
|
||||
{
|
||||
Parameters = {new CodeParameterDeclarationExpression("EGID", "egid")},
|
||||
Comments =
|
||||
{
|
||||
_start, new CodeCommentStatement($"Constructs a(n) {name} object representing an existing block.", true), _end
|
||||
},
|
||||
BaseConstructorArgs = {new CodeVariableReferenceExpression("egid")},
|
||||
Attributes = MemberAttributes.Public | MemberAttributes.Final
|
||||
});
|
||||
cl.Members.Add(new CodeConstructor
|
||||
{
|
||||
Parameters =
|
||||
{
|
||||
new CodeParameterDeclarationExpression(typeof(uint), "id")
|
||||
},
|
||||
Comments =
|
||||
{
|
||||
_start, new CodeCommentStatement($"Constructs a(n) {name} object representing an existing block.", true), _end
|
||||
},
|
||||
BaseConstructorArgs =
|
||||
{
|
||||
new CodeObjectCreateExpression("EGID", new CodeVariableReferenceExpression("id"),
|
||||
new CodeVariableReferenceExpression(group))
|
||||
},
|
||||
Attributes = MemberAttributes.Public | MemberAttributes.Final
|
||||
});
|
||||
foreach (var type in types)
|
||||
{
|
||||
GenerateProperties(cl, type, name, renames);
|
||||
}
|
||||
ns.Types.Add(cl);
|
||||
codeUnit.Namespaces.Add(ns);
|
||||
|
||||
var provider = CodeDomProvider.CreateProvider("CSharp");
|
||||
var path = $@"..\..\..\TechbloxModdingAPI\Blocks\{name}.cs";
|
||||
using (var sw = new StreamWriter(path))
|
||||
{
|
||||
provider.GenerateCodeFromCompileUnit(codeUnit, sw, new CodeGeneratorOptions {BracingStyle = "C"});
|
||||
}
|
||||
|
||||
File.WriteAllLines(path,
|
||||
File.ReadAllLines(path).SkipWhile(line => line.StartsWith("//") || line.Length == 0));
|
||||
}
|
||||
|
||||
private static string GetGroup(string name)
|
||||
{
|
||||
var ret = "";
|
||||
foreach (var ch in name)
|
||||
{
|
||||
if (char.IsUpper(ch) && ret.Length > 0)
|
||||
ret += "_" + ch;
|
||||
else
|
||||
ret += char.ToUpper(ch);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void GenerateProperties(CodeTypeDeclaration cl, Type type, string baseClass,
|
||||
Dictionary<string, string> renames)
|
||||
{
|
||||
if (!typeof(IEntityComponent).IsAssignableFrom(type))
|
||||
throw new ArgumentException("Type must be an entity component");
|
||||
foreach (var field in type.GetFields())
|
||||
{
|
||||
var attr = field.GetCustomAttribute<TweakableStatAttribute>();
|
||||
if (renames == null || !renames.TryGetValue(field.Name, out var propName))
|
||||
{
|
||||
propName = field.Name;
|
||||
if (attr != null)
|
||||
propName = attr.propertyName;
|
||||
}
|
||||
|
||||
propName = char.ToUpper(propName[0]) + propName.Substring(1);
|
||||
var structFieldReference = new CodeFieldReferenceExpression(new CodeMethodInvokeExpression(
|
||||
new CodeMethodReferenceExpression(new CodeSnippetExpression("BlockEngine"),
|
||||
"GetBlockInfo", new CodeTypeReference(type)),
|
||||
new CodeThisReferenceExpression()), field.Name);
|
||||
cl.Members.Add(new CodeMemberProperty
|
||||
{
|
||||
Name = propName,
|
||||
HasGet = true,
|
||||
HasSet = true,
|
||||
GetStatements =
|
||||
{
|
||||
new CodeMethodReturnStatement(structFieldReference)
|
||||
},
|
||||
SetStatements =
|
||||
{
|
||||
new CodeAssignStatement(structFieldReference, new CodePropertySetValueReferenceExpression())
|
||||
},
|
||||
Type = new CodeTypeReference(field.FieldType),
|
||||
Attributes = MemberAttributes.Public | MemberAttributes.Final,
|
||||
Comments =
|
||||
{
|
||||
_start, new CodeCommentStatement($"Gets or sets the {baseClass}'s {propName} property." +
|
||||
$" {(attr != null ? "Tweakable stat." : "May not be saved.")}", true), _end
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly CodeCommentStatement _start = new CodeCommentStatement("<summary>", true);
|
||||
private static readonly CodeCommentStatement _end = new CodeCommentStatement("</summary>", true);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,42 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using RobocraftX.Blocks;
|
||||
using RobocraftX.PilotSeat;
|
||||
using Techblox.EngineBlock;
|
||||
using Techblox.WheelRigBlock;
|
||||
|
||||
namespace CodeGenerator
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var bcg = new BlockClassGenerator();
|
||||
bcg.Generate("Engine", null, new Dictionary<string, string>
|
||||
{
|
||||
{ "engineOn", "On" }
|
||||
}, typeof(EngineBlockComponent), // Simulation time properties
|
||||
typeof(EngineBlockTweakableComponent), typeof(EngineBlockReadonlyComponent));
|
||||
bcg.Generate("DampedSpring", "DAMPEDSPRING_BLOCK_GROUP", new Dictionary<string, string>
|
||||
{
|
||||
{"maxExtent", "MaxExtension"}
|
||||
},
|
||||
typeof(TweakableJointDampingComponent), typeof(DampedSpringReadOnlyStruct));
|
||||
bcg.Generate("LogicGate", "LOGIC_BLOCK_GROUP");
|
||||
bcg.Generate("Servo", types: typeof(ServoReadOnlyStruct), renames: new Dictionary<string, string>
|
||||
{
|
||||
{"minDeviation", "MinimumAngle"},
|
||||
{"maxDeviation", "MaximumAngle"},
|
||||
{"servoVelocity", "MaximumForce"}
|
||||
});
|
||||
bcg.Generate("WheelRig", "WHEELRIG_BLOCK_BUILD_GROUP", null,
|
||||
typeof(WheelRigTweakableStruct), typeof(WheelRigReadOnlyStruct),
|
||||
typeof(WheelRigSteerableTweakableStruct), typeof(WheelRigSteerableReadOnlyStruct));
|
||||
bcg.Generate("Seat", "RobocraftX.PilotSeat.SeatGroups.PILOTSEAT_BLOCK_BUILD_GROUP", null, typeof(SeatFollowCamComponent), typeof(SeatReadOnlySettingsComponent));
|
||||
bcg.Generate("Piston", null, new Dictionary<string, string>
|
||||
{
|
||||
{"pistonVelocity", "MaximumForce"}
|
||||
}, typeof(PistonReadOnlyStruct));
|
||||
bcg.Generate("Motor", null, null, typeof(MotorReadOnlyStruct));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("CodeGenerator")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("CodeGenerator")]
|
||||
[assembly: AssemblyCopyright("Copyright © ExMods 2021")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("0EBB6400-95A7-4A3D-B2ED-BF31E364CC10")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -3,9 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29411.108
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TechbloxModdingAPI", "TechbloxModdingAPI\TechbloxModdingAPI.csproj", "{7FD5A7D8-4F3E-426A-B07D-7DC70442A4DF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeGenerator", "CodeGenerator\CodeGenerator.csproj", "{0EBB6400-95A7-4A3D-B2ED-BF31E364CC10}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GamecraftModdingAPI", "GamecraftModdingAPI\GamecraftModdingAPI.csproj", "{7FD5A7D8-4F3E-426A-B07D-7DC70442A4DF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -20,12 +18,6 @@ Global
|
|||
{7FD5A7D8-4F3E-426A-B07D-7DC70442A4DF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7FD5A7D8-4F3E-426A-B07D-7DC70442A4DF}.Test|Any CPU.ActiveCfg = Test|Any CPU
|
||||
{7FD5A7D8-4F3E-426A-B07D-7DC70442A4DF}.Test|Any CPU.Build.0 = Test|Any CPU
|
||||
{0EBB6400-95A7-4A3D-B2ED-BF31E364CC10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0EBB6400-95A7-4A3D-B2ED-BF31E364CC10}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0EBB6400-95A7-4A3D-B2ED-BF31E364CC10}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0EBB6400-95A7-4A3D-B2ED-BF31E364CC10}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0EBB6400-95A7-4A3D-B2ED-BF31E364CC10}.Test|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0EBB6400-95A7-4A3D-B2ED-BF31E364CC10}.Test|Any CPU.Build.0 = Debug|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
|
@ -1,8 +1,8 @@
|
|||
using System;
|
||||
|
||||
using TechbloxModdingAPI.Tests;
|
||||
using GamecraftModdingAPI.Tests;
|
||||
|
||||
namespace TechbloxModdingAPI.App
|
||||
namespace GamecraftModdingAPI.App
|
||||
{
|
||||
#if TEST
|
||||
/// <summary>
|
63
GamecraftModdingAPI/App/AppEngine.cs
Normal file
63
GamecraftModdingAPI/App/AppEngine.cs
Normal file
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
|
||||
using RobocraftX.GUI.MyGamesScreen;
|
||||
using RobocraftX.GUI;
|
||||
using Svelto.ECS;
|
||||
|
||||
using GamecraftModdingAPI.Engines;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.App
|
||||
{
|
||||
public class AppEngine : IFactoryEngine
|
||||
{
|
||||
public event EventHandler<MenuEventArgs> EnterMenu;
|
||||
|
||||
public event EventHandler<MenuEventArgs> ExitMenu;
|
||||
|
||||
public IEntityFactory Factory { set; private get; }
|
||||
|
||||
public string Name => "GamecraftModdingAPIAppEngine";
|
||||
|
||||
public bool isRemovable => false;
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
IsInMenu = false;
|
||||
ExceptionUtil.InvokeEvent(ExitMenu, this, new MenuEventArgs { });
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
IsInMenu = true;
|
||||
ExceptionUtil.InvokeEvent(EnterMenu, this, new MenuEventArgs { });
|
||||
}
|
||||
|
||||
// app functionality
|
||||
|
||||
public bool IsInMenu
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = false;
|
||||
|
||||
public Game[] GetMyGames()
|
||||
{
|
||||
EntityCollection<MyGameDataEntityStruct> mgsevs = entitiesDB.QueryEntities<MyGameDataEntityStruct>(MyGamesScreenExclusiveGroups.MyGames);
|
||||
Game[] games = new Game[mgsevs.count];
|
||||
for (int i = 0; i < mgsevs.count; i++)
|
||||
{
|
||||
Utility.Logging.MetaDebugLog($"Found game named {mgsevs[i].GameName}");
|
||||
games[i] = new Game(mgsevs[i].ID);
|
||||
}
|
||||
return games;
|
||||
}
|
||||
}
|
||||
|
||||
public struct MenuEventArgs
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TechbloxModdingAPI.App
|
||||
namespace GamecraftModdingAPI.App
|
||||
{
|
||||
public class AppException : TechbloxModdingAPIException
|
||||
public class AppException : GamecraftModdingAPIException
|
||||
{
|
||||
public AppException()
|
||||
{
|
82
GamecraftModdingAPI/App/Client.cs
Normal file
82
GamecraftModdingAPI/App/Client.cs
Normal file
|
@ -0,0 +1,82 @@
|
|||
using System;
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.App
|
||||
{
|
||||
/// <summary>
|
||||
/// The Gamecraft application that is running this code right now.
|
||||
/// </summary>
|
||||
public class Client
|
||||
{
|
||||
// extensible engine
|
||||
protected static AppEngine appEngine = new AppEngine();
|
||||
|
||||
/// <summary>
|
||||
/// An event that fires whenever the main menu is loaded.
|
||||
/// </summary>
|
||||
public static event EventHandler<MenuEventArgs> EnterMenu
|
||||
{
|
||||
add => appEngine.EnterMenu += value;
|
||||
remove => appEngine.EnterMenu -= value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An event that fire whenever the main menu is exited.
|
||||
/// </summary>
|
||||
public static event EventHandler<MenuEventArgs> ExitMenu
|
||||
{
|
||||
add => appEngine.ExitMenu += value;
|
||||
remove => appEngine.ExitMenu -= value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gamecraft build version string.
|
||||
/// Usually this is in the form YYYY.mm.DD.HH.MM.SS
|
||||
/// </summary>
|
||||
/// <value>The version.</value>
|
||||
public string Version
|
||||
{
|
||||
get => Application.version;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unity version string.
|
||||
/// </summary>
|
||||
/// <value>The unity version.</value>
|
||||
public string UnityVersion
|
||||
{
|
||||
get => Application.unityVersion;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Game saves currently visible in the menu.
|
||||
/// These take a second to completely populate after the EnterMenu event fires.
|
||||
/// </summary>
|
||||
/// <value>My games.</value>
|
||||
public Game[] MyGames
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!appEngine.IsInMenu) return new Game[0];
|
||||
return appEngine.GetMyGames();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether Gamecraft is in the Main Menu
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if in menu; <c>false</c> when loading or in a game.</value>
|
||||
public bool InMenu
|
||||
{
|
||||
get => appEngine.IsInMenu;
|
||||
}
|
||||
|
||||
internal static void Init()
|
||||
{
|
||||
MenuEngineManager.AddMenuEngine(appEngine);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,15 +2,17 @@
|
|||
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.Blocks;
|
||||
using TechbloxModdingAPI.Tasks;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using GamecraftModdingAPI;
|
||||
using GamecraftModdingAPI.Blocks;
|
||||
using GamecraftModdingAPI.Tasks;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.App
|
||||
namespace GamecraftModdingAPI.App
|
||||
{
|
||||
/// <summary>
|
||||
/// An in-game save.
|
||||
|
@ -21,7 +23,7 @@ namespace TechbloxModdingAPI.App
|
|||
{
|
||||
// extensible engines
|
||||
protected static GameGameEngine gameEngine = new GameGameEngine();
|
||||
protected internal static GameMenuEngine menuEngine = new GameMenuEngine();
|
||||
protected static GameMenuEngine menuEngine = new GameMenuEngine();
|
||||
protected static DebugInterfaceEngine debugOverlayEngine = new DebugInterfaceEngine();
|
||||
protected static GameBuildSimEventEngine buildSimEventEngine = new GameBuildSimEventEngine();
|
||||
|
||||
|
@ -31,7 +33,7 @@ namespace TechbloxModdingAPI.App
|
|||
private bool hasId = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:TechbloxModdingAPI.App.Game"/> class.
|
||||
/// Initializes a new instance of the <see cref="T:GamecraftModdingAPI.App.Game"/> class.
|
||||
/// </summary>
|
||||
/// <param name="id">Menu identifier.</param>
|
||||
public Game(uint id) : this(new EGID(id, MyGamesScreenExclusiveGroups.MyGames))
|
||||
|
@ -39,7 +41,7 @@ namespace TechbloxModdingAPI.App
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:TechbloxModdingAPI.App.Game"/> class.
|
||||
/// Initializes a new instance of the <see cref="T:GamecraftModdingAPI.App.Game"/> class.
|
||||
/// </summary>
|
||||
/// <param name="id">Menu identifier.</param>
|
||||
public Game(EGID id)
|
||||
|
@ -52,7 +54,7 @@ namespace TechbloxModdingAPI.App
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:TechbloxModdingAPI.App.Game"/> class without id.
|
||||
/// Initializes a new instance of the <see cref="T:GamecraftModdingAPI.App.Game"/> class without id.
|
||||
/// This is assumed to be the current game.
|
||||
/// </summary>
|
||||
public Game()
|
||||
|
@ -116,7 +118,7 @@ namespace TechbloxModdingAPI.App
|
|||
|
||||
/// <summary>
|
||||
/// An event that fires right before a game returns to the main menu.
|
||||
/// At this point, Techblox is transitioning state so many things are invalid/unstable here.
|
||||
/// At this point, Gamecraft is transitioning state so many things are invalid/unstable here.
|
||||
/// </summary>
|
||||
public static event EventHandler<GameEventArgs> Exit
|
||||
{
|
||||
|
@ -163,7 +165,7 @@ namespace TechbloxModdingAPI.App
|
|||
{
|
||||
if (!VerifyMode()) return null;
|
||||
if (menuMode) return menuEngine.GetGameInfo(EGID).GameName;
|
||||
return gameEngine.GetGameData().saveName;
|
||||
return GameMode.SaveGameDetails.Name;
|
||||
}
|
||||
|
||||
set
|
||||
|
@ -172,7 +174,11 @@ namespace TechbloxModdingAPI.App
|
|||
if (menuMode)
|
||||
{
|
||||
menuEngine.SetGameName(EGID, value);
|
||||
} // Save details are directly saved from user input or not changed at all when in game
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMode.SaveGameDetails.Name = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,7 +201,11 @@ namespace TechbloxModdingAPI.App
|
|||
if (menuMode)
|
||||
{
|
||||
menuEngine.SetGameDescription(EGID, value);
|
||||
} // No description exists in-game
|
||||
}
|
||||
else
|
||||
{
|
||||
// No description exists in-game
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,7 +219,7 @@ namespace TechbloxModdingAPI.App
|
|||
{
|
||||
if (!VerifyMode()) return null;
|
||||
if (menuMode) return menuEngine.GetGameInfo(EGID).SavedGamePath;
|
||||
return gameEngine.GetGameData().gameID;
|
||||
return GameMode.SaveGameDetails.Folder;
|
||||
}
|
||||
|
||||
set
|
||||
|
@ -219,6 +229,11 @@ namespace TechbloxModdingAPI.App
|
|||
{
|
||||
menuEngine.GetGameInfo(EGID).SavedGamePath.Set(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// this likely breaks things
|
||||
GameMode.SaveGameDetails = new SaveGameDetails(GameMode.SaveGameDetails.Name, value, GameMode.SaveGameDetails.WorkshopId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -227,16 +242,28 @@ namespace TechbloxModdingAPI.App
|
|||
/// In most cases this is invalid and returns 0, so this can be ignored.
|
||||
/// </summary>
|
||||
/// <value>The workshop identifier.</value>
|
||||
[Obsolete]
|
||||
public ulong WorkshopId
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0uL; // Not supported anymore
|
||||
if (!VerifyMode()) return 0uL;
|
||||
if (menuMode) return 0uL; // MyGames don't have workshop IDs
|
||||
return GameMode.SaveGameDetails.WorkshopId;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
VerifyMode();
|
||||
if (menuMode)
|
||||
{
|
||||
// MyGames don't have workshop IDs
|
||||
// menuEngine.GetGameInfo(EGID).GameName.Set(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// this likely breaks things
|
||||
GameMode.SaveGameDetails = new SaveGameDetails(GameMode.SaveGameDetails.Name, GameMode.SaveGameDetails.Folder, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,18 +335,6 @@ namespace TechbloxModdingAPI.App
|
|||
gameEngine.ToggleTimeMode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The mode of the game.
|
||||
/// </summary>
|
||||
public CurrentGameMode Mode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (menuMode || !VerifyMode()) return CurrentGameMode.None;
|
||||
return gameEngine.GetGameData().gameMode == GameMode.CreateWorld ? CurrentGameMode.Build : CurrentGameMode.Play;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the game save.
|
||||
/// This happens asynchronously, so when this method returns the game not loaded yet.
|
||||
|
@ -369,20 +384,19 @@ namespace TechbloxModdingAPI.App
|
|||
|
||||
/// <summary>
|
||||
/// Add information to the in-game debug display.
|
||||
/// When this object is garbage collected, this debug info is automatically removed.
|
||||
/// The provided getter function is called each frame so make sure it returns quickly.
|
||||
/// When this object is garbage collected, this debug info is automatically removed.
|
||||
/// </summary>
|
||||
/// <param name="id">Debug info identifier.</param>
|
||||
/// <param name="contentGetter">A function that returns the current information.</param>
|
||||
public void AddDebugInfo(string id, Func<string> contentGetter)
|
||||
/// <param name="contentGetter">Content getter.</param>
|
||||
public void AddDebugInfo(string id, Func<string> contentGetter)
|
||||
{
|
||||
if (!VerifyMode()) return;
|
||||
if (menuMode)
|
||||
{
|
||||
throw new GameNotFoundException("Game object references a menu item but AddDebugInfo only works on the currently-loaded game");
|
||||
}
|
||||
debugOverlayEngine.SetInfo("game_" + id, contentGetter);
|
||||
debugIds.Add(id);
|
||||
if (!VerifyMode()) return;
|
||||
if (menuMode)
|
||||
{
|
||||
throw new GameNotFoundException("Game object references a menu item but AddDebugInfo only works on the currently-loaded game");
|
||||
}
|
||||
debugOverlayEngine.SetInfo(id, contentGetter);
|
||||
debugIds.Add(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -392,36 +406,14 @@ namespace TechbloxModdingAPI.App
|
|||
/// <param name="id">Debug info identifier.</param>
|
||||
public bool RemoveDebugInfo(string id)
|
||||
{
|
||||
if (!VerifyMode()) return false;
|
||||
if (menuMode)
|
||||
{
|
||||
throw new GameNotFoundException("Game object references a menu item but RemoveDebugInfo only works on the currently-loaded game");
|
||||
}
|
||||
if (!debugIds.Contains(id)) return false;
|
||||
debugOverlayEngine.RemoveInfo("game_" + id);
|
||||
return debugIds.Remove(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add information to the in-game debug display.
|
||||
/// This debug info will be present for all games until it is manually removed.
|
||||
/// The provided getter function is called each frame so make sure it returns quickly.
|
||||
/// </summary>
|
||||
/// <param name="id">Debug info identifier.</param>
|
||||
/// <param name="contentGetter">A function that returns the current information.</param>
|
||||
public static void AddPersistentDebugInfo(string id, Func<string> contentGetter)
|
||||
{
|
||||
debugOverlayEngine.SetInfo("persistent_" + id, contentGetter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove persistent information from the in-game debug display.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if debug info was removed, <c>false</c> otherwise.</returns>
|
||||
/// <param name="id">Debug info identifier.</param>
|
||||
public static bool RemovePersistentDebugInfo(string id)
|
||||
{
|
||||
return debugOverlayEngine.RemoveInfo("persistent_" + id);
|
||||
if (!VerifyMode()) return false;
|
||||
if (menuMode)
|
||||
{
|
||||
throw new GameNotFoundException("Game object references a menu item but RemoveDebugInfo only works on the currently-loaded game");
|
||||
}
|
||||
if (!debugIds.Contains(id)) return false;
|
||||
debugOverlayEngine.RemoveInfo(id);
|
||||
return debugIds.Remove(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -441,20 +433,11 @@ namespace TechbloxModdingAPI.App
|
|||
Block[] blocks = new Block[blockEGIDs.Length];
|
||||
for (int b = 0; b < blockEGIDs.Length; b++)
|
||||
{
|
||||
blocks[b] = Block.New(blockEGIDs[b]);
|
||||
blocks[b] = new Block(blockEGIDs[b]);
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable the screenshot taker for updating the game's screenshot. Breaks the pause menu in a new save.
|
||||
/// </summary>
|
||||
public void EnableScreenshotTaker()
|
||||
{
|
||||
if (!VerifyMode()) return;
|
||||
gameEngine.EnableScreenshotTaker();
|
||||
}
|
||||
|
||||
~Game()
|
||||
{
|
||||
foreach (string id in debugIds)
|
||||
|
@ -483,8 +466,12 @@ namespace TechbloxModdingAPI.App
|
|||
{
|
||||
GameEngineManager.AddGameEngine(gameEngine);
|
||||
GameEngineManager.AddGameEngine(debugOverlayEngine);
|
||||
GameEngineManager.AddGameEngine(buildSimEventEngine);
|
||||
MenuEngineManager.AddMenuEngine(menuEngine);
|
||||
}
|
||||
|
||||
internal static void InitDeterministic(StateSyncRegistrationHelper stateSyncReg)
|
||||
{
|
||||
stateSyncReg.AddDeterministicEngine(buildSimEventEngine);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,18 +4,19 @@ using RobocraftX.Common;
|
|||
using RobocraftX.StateSync;
|
||||
using Svelto.ECS;
|
||||
using Unity.Jobs;
|
||||
using TechbloxModdingAPI.Engines;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.App
|
||||
using GamecraftModdingAPI.Engines;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.App
|
||||
{
|
||||
public class GameBuildSimEventEngine : IApiEngine, IUnorderedInitializeOnTimeRunningModeEntered, IUnorderedInitializeOnTimeStoppedModeEntered
|
||||
{
|
||||
public WrappedHandler<GameEventArgs> SimulationMode;
|
||||
public event EventHandler<GameEventArgs> SimulationMode;
|
||||
|
||||
public WrappedHandler<GameEventArgs> BuildMode;
|
||||
public event EventHandler<GameEventArgs> BuildMode;
|
||||
|
||||
public string Name => "TechbloxModdingAPIBuildSimEventGameEngine";
|
||||
public string Name => "GamecraftModdingAPIBuildSimEventGameEngine";
|
||||
|
||||
public bool isRemovable => false;
|
||||
|
||||
|
@ -27,15 +28,13 @@ namespace TechbloxModdingAPI.App
|
|||
|
||||
public JobHandle OnInitializeTimeRunningMode(JobHandle inputDeps)
|
||||
{
|
||||
Console.WriteLine("Init time running mode");
|
||||
SimulationMode.Invoke(this, new GameEventArgs { GameName = "", GamePath = "" }); // TODO
|
||||
ExceptionUtil.InvokeEvent(SimulationMode, this, new GameEventArgs { GameName = GameMode.SaveGameDetails.Name, GamePath = GameMode.SaveGameDetails.Folder });
|
||||
return inputDeps;
|
||||
}
|
||||
|
||||
public JobHandle OnInitializeTimeStoppedMode(JobHandle inputDeps)
|
||||
{
|
||||
Console.WriteLine("Init time stopped mode");
|
||||
BuildMode.Invoke(this, new GameEventArgs { GameName = "", GamePath = "" });
|
||||
ExceptionUtil.InvokeEvent(BuildMode, this, new GameEventArgs { GameName = GameMode.SaveGameDetails.Name, GamePath = GameMode.SaveGameDetails.Folder });
|
||||
return inputDeps;
|
||||
}
|
||||
}
|
119
GamecraftModdingAPI/App/GameGameEngine.cs
Normal file
119
GamecraftModdingAPI/App/GameGameEngine.cs
Normal file
|
@ -0,0 +1,119 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using HarmonyLib;
|
||||
|
||||
using RobocraftX;
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.Schedulers;
|
||||
using RobocraftX.SimulationModeState;
|
||||
using Svelto.ECS;
|
||||
using Svelto.Tasks;
|
||||
using Svelto.Tasks.Lean;
|
||||
|
||||
using GamecraftModdingAPI.Blocks;
|
||||
using GamecraftModdingAPI.Engines;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.App
|
||||
{
|
||||
public class GameGameEngine : IApiEngine
|
||||
{
|
||||
public event EventHandler<GameEventArgs> EnterGame;
|
||||
|
||||
public event EventHandler<GameEventArgs> ExitGame;
|
||||
|
||||
public string Name => "GamecraftModdingAPIGameInfoMenuEngine";
|
||||
|
||||
public bool isRemovable => false;
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ExceptionUtil.InvokeEvent(ExitGame, this, new GameEventArgs { GameName = GameMode.SaveGameDetails.Name, GamePath = GameMode.SaveGameDetails.Folder });
|
||||
IsInGame = false;
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
ExceptionUtil.InvokeEvent(EnterGame, this, new GameEventArgs { GameName = GameMode.SaveGameDetails.Name, GamePath = GameMode.SaveGameDetails.Folder });
|
||||
IsInGame = true;
|
||||
}
|
||||
|
||||
// game functionality
|
||||
|
||||
public bool IsInGame
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = false;
|
||||
|
||||
public void ExitCurrentGame(bool async = false)
|
||||
{
|
||||
if (async)
|
||||
{
|
||||
ExitCurrentGameAsync().RunOn(Lean.EveryFrameStepRunner_RUNS_IN_TIME_STOPPED_AND_RUNNING);
|
||||
}
|
||||
else
|
||||
{
|
||||
entitiesDB.QueryEntity<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID).WantsToQuit = true;
|
||||
entitiesDB.PublishEntityChange<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public IEnumerator<TaskContract> ExitCurrentGameAsync()
|
||||
{
|
||||
/*
|
||||
while (Lean.EveryFrameStepRunner_RUNS_IN_TIME_STOPPED_AND_RUNNING.isStopping) { yield return Yield.It; }
|
||||
AccessTools.Method(typeof(FullGameCompositionRoot), "SwitchToMenu").Invoke(FullGameFields.Instance, new object[0]);*/
|
||||
yield return Yield.It;
|
||||
entitiesDB.QueryEntity<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID).WantsToQuit = true;
|
||||
entitiesDB.PublishEntityChange<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID);
|
||||
}
|
||||
|
||||
public void SaveCurrentGame()
|
||||
{
|
||||
ref GameSceneEntityStruct gses = ref entitiesDB.QueryEntity<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID);
|
||||
gses.LoadAfterSaving = false;
|
||||
gses.SaveNow = true;
|
||||
entitiesDB.PublishEntityChange<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID);
|
||||
}
|
||||
|
||||
public bool IsTimeRunningMode()
|
||||
{
|
||||
return TimeRunningModeUtil.IsTimeRunningMode(entitiesDB);
|
||||
}
|
||||
|
||||
public bool IsTimeStoppedMode()
|
||||
{
|
||||
return TimeRunningModeUtil.IsTimeStoppedMode(entitiesDB);
|
||||
}
|
||||
|
||||
public void ToggleTimeMode()
|
||||
{
|
||||
TimeRunningModeUtil.ToggleTimeRunningState(entitiesDB);
|
||||
}
|
||||
|
||||
public EGID[] GetAllBlocksInGame(BlockIDs filter = BlockIDs.Invalid)
|
||||
{
|
||||
var allBlocks = entitiesDB.QueryEntities<DBEntityStruct>();
|
||||
List<EGID> blockEGIDs = new List<EGID>();
|
||||
if (filter == BlockIDs.Invalid)
|
||||
{
|
||||
foreach (var (blocks, _) in allBlocks)
|
||||
foreach (var block in blocks)
|
||||
blockEGIDs.Add(block.ID);
|
||||
return blockEGIDs.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var (blocks, _) in allBlocks)
|
||||
foreach (var block in blocks)
|
||||
if (block.DBID == (ulong) filter)
|
||||
blockEGIDs.Add(block.ID);
|
||||
return blockEGIDs.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
128
GamecraftModdingAPI/App/GameMenuEngine.cs
Normal file
128
GamecraftModdingAPI/App/GameMenuEngine.cs
Normal file
|
@ -0,0 +1,128 @@
|
|||
using System;
|
||||
using HarmonyLib;
|
||||
|
||||
using RobocraftX;
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.GUI;
|
||||
using RobocraftX.GUI.MyGamesScreen;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.Experimental;
|
||||
|
||||
using GamecraftModdingAPI.Engines;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.App
|
||||
{
|
||||
public class GameMenuEngine : IFactoryEngine
|
||||
{
|
||||
public IEntityFactory Factory { set; private get; }
|
||||
|
||||
public string Name => "GamecraftModdingAPIGameInfoGameEngine";
|
||||
|
||||
public bool isRemovable => false;
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
IsInMenu = false;
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
IsInMenu = true;
|
||||
}
|
||||
|
||||
// game functionality
|
||||
|
||||
public bool IsInMenu
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = false;
|
||||
|
||||
public bool CreateMyGame(EGID id, string path = "", uint thumbnailId = 0, string gameName = "", string creatorName = "", string description = "", long createdDate = 0L)
|
||||
{
|
||||
EntityComponentInitializer 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);
|
||||
uint max = 0;
|
||||
for (int i = 0; i < games.count; i++)
|
||||
{
|
||||
if (games[i].ID.entityID > max)
|
||||
{
|
||||
max = games[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.SavedGamePath);
|
||||
}
|
||||
|
||||
public bool EnterGame(string gameName, string path, ulong workshopId = 0uL, bool autoEnterSim = false)
|
||||
{
|
||||
GameMode.CurrentMode = autoEnterSim ? RCXMode.Play : RCXMode.Build;
|
||||
GameMode.SaveGameDetails = new SaveGameDetails(gameName, path, workshopId);
|
||||
// the private FullGameCompositionRoot.SwitchToGame() method gets passed to menu items for this reason
|
||||
AccessTools.Method(typeof(FullGameCompositionRoot), "SwitchToGame").Invoke(FullGameFields.Instance, new object[0]);
|
||||
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 ref MyGamesSlotEntityViewStruct GetGameViewInfo(EGID id)
|
||||
{
|
||||
return ref GetComponent<MyGamesSlotEntityViewStruct>(new EGID(id.entityID, MyGamesScreenExclusiveGroups.GameSlotGuiEntities));
|
||||
}
|
||||
|
||||
public ref T GetComponent<T>(EGID id) where T: struct, IEntityComponent
|
||||
{
|
||||
return ref entitiesDB.QueryEntity<T>(id);
|
||||
}
|
||||
}
|
||||
|
||||
internal class MyGameDataEntityDescriptor_DamnItFJWhyDidYouMakeThisInternal : GenericEntityDescriptor<MyGameDataEntityStruct> { }
|
||||
}
|
26
GamecraftModdingAPI/App/StateSyncRegPatch.cs
Normal file
26
GamecraftModdingAPI/App/StateSyncRegPatch.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using RobocraftX.CR.MainGame;
|
||||
using RobocraftX.StateSync;
|
||||
|
||||
using HarmonyLib;
|
||||
|
||||
namespace GamecraftModdingAPI.App
|
||||
{
|
||||
[HarmonyPatch]
|
||||
class StateSyncRegPatch
|
||||
{
|
||||
public static void Postfix(StateSyncRegistrationHelper stateSyncReg)
|
||||
{
|
||||
// register sim/build events engines
|
||||
Game.InitDeterministic(stateSyncReg);
|
||||
}
|
||||
|
||||
[HarmonyTargetMethod]
|
||||
public static MethodBase Target()
|
||||
{
|
||||
return AccessTools.Method(typeof(MainGameCompositionRoot), "DeterministicCompose").MakeGenericMethod(typeof(object));
|
||||
}
|
||||
}
|
||||
}
|
369
GamecraftModdingAPI/Block.cs
Normal file
369
GamecraftModdingAPI/Block.cs
Normal file
|
@ -0,0 +1,369 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.EntityStructs;
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.Blocks;
|
||||
using Unity.Mathematics;
|
||||
using Unity.Entities;
|
||||
using Gamecraft.Blocks.GUI;
|
||||
|
||||
using GamecraftModdingAPI.Blocks;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI
|
||||
{
|
||||
/// <summary>
|
||||
/// A single (perhaps scaled) block. Properties may return default values if the block is removed and then setting them is ignored.
|
||||
/// For specific block type operations, use the specialised block classes in the GamecraftModdingAPI.Blocks namespace.
|
||||
/// </summary>
|
||||
public class Block : IEquatable<Block>, IEquatable<EGID>
|
||||
{
|
||||
protected static readonly PlacementEngine PlacementEngine = new PlacementEngine();
|
||||
protected static readonly MovementEngine MovementEngine = new MovementEngine();
|
||||
protected static readonly RotationEngine RotationEngine = new RotationEngine();
|
||||
protected static readonly RemovalEngine RemovalEngine = new RemovalEngine();
|
||||
protected static readonly SignalEngine SignalEngine = new SignalEngine();
|
||||
protected static readonly BlockEventsEngine BlockEventsEngine = new BlockEventsEngine();
|
||||
protected static readonly ScalingEngine ScalingEngine = new ScalingEngine();
|
||||
|
||||
protected internal static readonly BlockEngine BlockEngine = new BlockEngine();
|
||||
|
||||
/// <summary>
|
||||
/// Place a new block at the given position. If scaled, position means the center of the block. The default block size is 0.2 in terms of position.
|
||||
/// Place blocks next to each other to connect them.
|
||||
/// The placed block will be a complete block with a placement grid and collision which will be saved along with the game.
|
||||
/// <para></para>
|
||||
/// <para>When placing multiple blocks, do not access properties immediately after creation as this
|
||||
/// triggers a sync each time which can affect performance and may cause issues with the game.
|
||||
/// You may either use AsyncUtils.WaitForSubmission() after placing all of the blocks
|
||||
/// or simply access the block properties which will trigger the synchronization the first time a property is used.</para>
|
||||
/// </summary>
|
||||
/// <param name="block">The block's type</param>
|
||||
/// <param name="color">The block's color</param>
|
||||
/// <param name="darkness">The block color's darkness (0-9) - 0 is default color</param>
|
||||
/// <param name="position">The block's position in the grid - default block size is 0.2</param>
|
||||
/// <param name="rotation">The block's rotation in degrees</param>
|
||||
/// <param name="uscale">The block's uniform scale - default scale is 1 (with 0.2 width)</param>
|
||||
/// <param name="scale">The block's non-uniform scale - 0 means <paramref name="uscale"/> is used</param>
|
||||
/// <param name="player">The player who placed the block</param>
|
||||
/// <returns>The placed block or null if failed</returns>
|
||||
public static Block PlaceNew(BlockIDs block, float3 position,
|
||||
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
||||
int uscale = 1, float3 scale = default, Player player = null)
|
||||
{
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
return new Block(PlacementEngine.PlaceBlock(block, color, darkness,
|
||||
position, uscale, scale, player, rotation));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Place a new block at the given position. If scaled, position means the center of the block. The default block size is 0.2 in terms of position.
|
||||
/// Place blocks next to each other to connect them.
|
||||
/// The placed block will be a complete block with a placement grid and collision which will be saved along with the game.
|
||||
/// <para></para>
|
||||
/// <para>This method waits for the block to be constructed in the game which may take a significant amount of time.
|
||||
/// Only use this to place a single block.
|
||||
/// For placing multiple blocks, use PlaceNew() then AsyncUtils.WaitForSubmission() when done with placing blocks.</para>
|
||||
/// </summary>
|
||||
/// <param name="block">The block's type</param>
|
||||
/// <param name="color">The block's color</param>
|
||||
/// <param name="darkness">The block color's darkness (0-9) - 0 is default color</param>
|
||||
/// <param name="position">The block's position in the grid - default block size is 0.2</param>
|
||||
/// <param name="rotation">The block's rotation in degrees</param>
|
||||
/// <param name="uscale">The block's uniform scale - default scale is 1 (with 0.2 width)</param>
|
||||
/// <param name="scale">The block's non-uniform scale - 0 means <paramref name="uscale"/> is used</param>
|
||||
/// <param name="player">The player who placed the block</param>
|
||||
/// <returns>The placed block or null if failed</returns>
|
||||
public static async Task<Block> PlaceNewAsync(BlockIDs block, float3 position,
|
||||
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
||||
int uscale = 1, float3 scale = default, Player player = null)
|
||||
{
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
try
|
||||
{
|
||||
var ret = new Block(PlacementEngine.PlaceBlock(block, color, darkness,
|
||||
position, uscale, scale, player, rotation));
|
||||
await AsyncUtils.WaitForSubmission();
|
||||
return ret;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.MetaDebugLog(e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the most recently placed block.
|
||||
/// </summary>
|
||||
/// <returns>The block object</returns>
|
||||
public static Block GetLastPlacedBlock()
|
||||
{
|
||||
return new Block(BlockIdentifiers.LatestBlockID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An event that fires each time a block is placed.
|
||||
/// </summary>
|
||||
public static event EventHandler<BlockPlacedRemovedEventArgs> Placed
|
||||
{
|
||||
add => BlockEventsEngine.Placed += value;
|
||||
remove => BlockEventsEngine.Placed -= value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An event that fires each time a block is removed.
|
||||
/// </summary>
|
||||
public static event EventHandler<BlockPlacedRemovedEventArgs> Removed
|
||||
{
|
||||
add => BlockEventsEngine.Removed += value;
|
||||
remove => BlockEventsEngine.Removed -= value;
|
||||
}
|
||||
|
||||
public Block(EGID id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This overload searches for the correct group the block is in.
|
||||
/// It will throw an exception if the block doesn't exist.
|
||||
/// Use the EGID constructor where possible or subclasses of Block as those specify the group.
|
||||
/// </summary>
|
||||
public Block(uint id)
|
||||
{
|
||||
Id = BlockEngine.FindBlockEGID(id) ?? throw new BlockTypeException("Could not find the appropriate group for the block. The block probably doesn't exist or hasn't been submitted.");
|
||||
}
|
||||
|
||||
public EGID Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The block's current position or zero if the block no longer exists.
|
||||
/// A block is 0.2 wide by default in terms of position.
|
||||
/// </summary>
|
||||
public float3 Position
|
||||
{
|
||||
get => Exists ? MovementEngine.GetPosition(Id) : float3.zero;
|
||||
set
|
||||
{
|
||||
if (Exists) MovementEngine.MoveBlock(Id, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The block's current rotation in degrees or zero if the block doesn't exist.
|
||||
/// </summary>
|
||||
public float3 Rotation
|
||||
{
|
||||
get => Exists ? RotationEngine.GetRotation(Id) : float3.zero;
|
||||
set
|
||||
{
|
||||
if (Exists) RotationEngine.RotateBlock(Id, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The block's non-uniform scale or zero if the block's invalid. Independent of the uniform scaling.
|
||||
/// The default scale of 1 means 0.2 in terms of position.
|
||||
/// </summary>
|
||||
public float3 Scale
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<ScalingEntityStruct>(Id).scale;
|
||||
set
|
||||
{
|
||||
if (!Exists) return; //UpdateCollision needs the block to exist
|
||||
ref var scaling = ref BlockEngine.GetBlockInfo<ScalingEntityStruct>(Id);
|
||||
scaling.scale = value;
|
||||
ScalingEngine.UpdateCollision(Id);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The block's uniform scale or zero if the block's invalid. Also sets the non-uniform scale.
|
||||
/// The default scale of 1 means 0.2 in terms of position.
|
||||
/// </summary>
|
||||
public int UniformScale
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<UniformBlockScaleEntityStruct>(Id).scaleFactor;
|
||||
set
|
||||
{
|
||||
ref var scaleStruct = ref BlockEngine.GetBlockInfo<UniformBlockScaleEntityStruct>(Id);
|
||||
scaleStruct.scaleFactor = value;
|
||||
Scale = new float3(value, value, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The block's type (ID). Returns BlockIDs.Invalid if the block doesn't exist anymore.
|
||||
/// </summary>
|
||||
public BlockIDs Type
|
||||
{
|
||||
get
|
||||
{
|
||||
var id = (BlockIDs) BlockEngine.GetBlockInfo<DBEntityStruct>(Id, out var exists).DBID;
|
||||
return exists ? id : BlockIDs.Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The block's color. Returns BlockColors.Default if the block no longer exists.
|
||||
/// </summary>
|
||||
public BlockColor Color
|
||||
{
|
||||
get
|
||||
{
|
||||
byte index = BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(Id, out var exists).indexInPalette;
|
||||
if (!exists) index = byte.MaxValue;
|
||||
return new BlockColor(index);
|
||||
}
|
||||
set
|
||||
{
|
||||
ref var color = ref BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(Id);
|
||||
color.indexInPalette = (byte)(value.Color + value.Darkness * 10);
|
||||
color.overridePaletteColour = false;
|
||||
color.needsUpdate = true;
|
||||
BlockEngine.SetBlockColorFromPalette(ref color);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The block's exact color. Gets reset to the palette color (Color property) after reentering the game.
|
||||
/// </summary>
|
||||
public float4 CustomColor
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(Id).overriddenColour;
|
||||
set
|
||||
{
|
||||
ref var color = ref BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(Id);
|
||||
color.overriddenColour = value;
|
||||
color.overridePaletteColour = true;
|
||||
color.needsUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The short text displayed on the block if applicable, or null.
|
||||
/// Setting it is temporary to the session, it won't be saved.
|
||||
/// </summary>
|
||||
public string Label
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<TextLabelEntityViewStruct>(Id).textLabelComponent?.text;
|
||||
set
|
||||
{
|
||||
ref var text = ref BlockEngine.GetBlockInfo<TextLabelEntityViewStruct>(Id);
|
||||
if (text.textLabelComponent != null) text.textLabelComponent.text = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the block exists. The other properties will return a default value if the block doesn't exist.
|
||||
/// </summary>
|
||||
public bool Exists => BlockEngine.BlockExists(Id);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array of blocks that are connected to this one. Returns an empty array if the block doesn't exist.
|
||||
/// </summary>
|
||||
public Block[] GetConnectedCubes() => BlockEngine.GetConnectedBlocks(Id);
|
||||
|
||||
/// <summary>
|
||||
/// Removes this block.
|
||||
/// </summary>
|
||||
/// <returns>True if the block exists and could be removed.</returns>
|
||||
public bool Remove() => RemovalEngine.RemoveBlock(Id);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the rigid body of the cluster of blocks this one belongs to during simulation.
|
||||
/// Can be used to apply forces or move the block around while the simulation is running.
|
||||
/// </summary>
|
||||
/// <returns>The SimBody of the cluster or null if the block doesn't exist.</returns>
|
||||
public SimBody GetSimBody()
|
||||
{
|
||||
uint id = BlockEngine.GetBlockInfo<GridConnectionsEntityStruct>(Id, out var exists).machineRigidBodyId;
|
||||
return exists ? new SimBody(id) : null;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Id)}: {Id}, {nameof(Position)}: {Position}, {nameof(Type)}: {Type}, {nameof(Color)}: {Color}, {nameof(Exists)}: {Exists}";
|
||||
}
|
||||
|
||||
public bool Equals(Block other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return Id.Equals(other.Id);
|
||||
}
|
||||
|
||||
public bool Equals(EGID other)
|
||||
{
|
||||
return Id.Equals(other);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((Block) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Id.GetHashCode();
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
GameEngineManager.AddGameEngine(PlacementEngine);
|
||||
GameEngineManager.AddGameEngine(MovementEngine);
|
||||
GameEngineManager.AddGameEngine(RotationEngine);
|
||||
GameEngineManager.AddGameEngine(RemovalEngine);
|
||||
GameEngineManager.AddGameEngine(BlockEngine);
|
||||
GameEngineManager.AddGameEngine(BlockEventsEngine);
|
||||
GameEngineManager.AddGameEngine(ScalingEngine);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the block to a specialised block class.
|
||||
/// </summary>
|
||||
/// <returns>The block.</returns>
|
||||
/// <typeparam name="T">The specialised block type.</typeparam>
|
||||
public T Specialise<T>() where T : Block
|
||||
{
|
||||
// What have I gotten myself into?
|
||||
// C# can't cast to a child of Block unless the object was originally that child type
|
||||
// And C# doesn't let me make implicit cast operators for child types
|
||||
// So thanks to Microsoft, we've got this horrible implementation using reflection
|
||||
ConstructorInfo ctor = typeof(T).GetConstructor(types: new System.Type[] { typeof(EGID) });
|
||||
if (ctor == null)
|
||||
{
|
||||
throw new BlockSpecializationException("Specialized block constructor does not accept an EGID");
|
||||
}
|
||||
return (T)ctor.Invoke(new object[] { Id });
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
public static EntitiesDB entitiesDB
|
||||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetEntitiesDB();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
internal static void Setup(World physicsWorld)
|
||||
{
|
||||
ScalingEngine.Setup(physicsWorld.EntityManager);
|
||||
}
|
||||
}
|
||||
}
|
51
GamecraftModdingAPI/Blocks/BlockColor.cs
Normal file
51
GamecraftModdingAPI/Blocks/BlockColor.cs
Normal file
|
@ -0,0 +1,51 @@
|
|||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
public struct BlockColor
|
||||
{
|
||||
public BlockColors Color;
|
||||
public byte Darkness;
|
||||
|
||||
public BlockColor(byte index)
|
||||
{
|
||||
if (index == byte.MaxValue)
|
||||
{
|
||||
Color = BlockColors.Default;
|
||||
Darkness = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Color = (BlockColors) (index % 10);
|
||||
Darkness = (byte) (index / 10);
|
||||
}
|
||||
}
|
||||
|
||||
public BlockColor(BlockColors color, byte darkness)
|
||||
{
|
||||
Color = color;
|
||||
Darkness = darkness;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Color)}: {Color}, {nameof(Darkness)}: {Darkness}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Preset block colours
|
||||
/// </summary>
|
||||
public enum BlockColors
|
||||
{
|
||||
Default = byte.MaxValue,
|
||||
White = 0,
|
||||
Pink,
|
||||
Purple,
|
||||
Blue,
|
||||
Aqua,
|
||||
Green,
|
||||
Lime,
|
||||
Yellow,
|
||||
Orange,
|
||||
Red
|
||||
}
|
||||
}
|
204
GamecraftModdingAPI/Blocks/BlockEngine.cs
Normal file
204
GamecraftModdingAPI/Blocks/BlockEngine.cs
Normal file
|
@ -0,0 +1,204 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
using Gamecraft.Wires;
|
||||
using RobocraftX.Blocks;
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.GUI.Hotbar.Colours;
|
||||
using RobocraftX.Physics;
|
||||
using RobocraftX.Scene.Simulation;
|
||||
using Svelto.DataStructures;
|
||||
using Svelto.ECS;
|
||||
|
||||
using GamecraftModdingAPI.Engines;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
/// <summary>
|
||||
/// Engine for executing general block actions
|
||||
/// </summary>
|
||||
public class BlockEngine : IApiEngine
|
||||
{
|
||||
public string Name { get; } = "GamecraftModdingAPIBlockGameEngine";
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
public bool isRemovable => false;
|
||||
|
||||
internal bool Synced = true;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
}
|
||||
|
||||
public Block[] GetConnectedBlocks(EGID blockID)
|
||||
{
|
||||
if (!BlockExists(blockID)) return new Block[0];
|
||||
Stack<EGID> cubeStack = new Stack<EGID>();
|
||||
FasterList<EGID> cubes = new FasterList<EGID>(10);
|
||||
var coll = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
|
||||
foreach (var (ecoll, _) in coll)
|
||||
foreach (ref var conn in ecoll)
|
||||
conn.isProcessed = false;
|
||||
|
||||
ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubeStack, cubes,
|
||||
(in GridConnectionsEntityStruct g) => { return false; });
|
||||
|
||||
var ret = new Block[cubes.count];
|
||||
for (int i = 0; i < cubes.count; i++)
|
||||
ret[i] = new Block(cubes[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void SetBlockColorFromPalette(ref ColourParameterEntityStruct color)
|
||||
{
|
||||
ref var paletteEntry = ref entitiesDB.QueryEntity<PaletteEntryEntityStruct>(color.indexInPalette,
|
||||
CommonExclusiveGroups.COLOUR_PALETTE_GROUP);
|
||||
color.paletteColour = paletteEntry.Colour;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a struct of a block. Can be used to set properties.
|
||||
/// Returns a default value if not found.
|
||||
/// </summary>
|
||||
/// <param name="blockID">The block's ID</param>
|
||||
/// <typeparam name="T">The struct to query</typeparam>
|
||||
/// <returns>An editable reference to the struct</returns>
|
||||
public ref T GetBlockInfo<T>(EGID blockID) where T : struct, IEntityComponent
|
||||
{
|
||||
if (!Synced)
|
||||
{
|
||||
Sync();
|
||||
Synced = true;
|
||||
}
|
||||
if (entitiesDB.Exists<T>(blockID))
|
||||
return ref entitiesDB.QueryEntity<T>(blockID);
|
||||
T[] structHolder = new T[1]; //Create something that can be referenced
|
||||
return ref structHolder[0]; //Gets a default value automatically
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a struct of a block. Can be used to set properties.
|
||||
/// Returns a default value if not found.
|
||||
/// </summary>
|
||||
/// <param name="blockID">The block's ID</param>
|
||||
/// <param name="exists">Whether the specified struct exists for the block</param>
|
||||
/// <typeparam name="T">The struct to query</typeparam>
|
||||
/// <returns>An editable reference to the struct</returns>
|
||||
public ref T GetBlockInfo<T>(EGID blockID, out bool exists) where T : struct, IEntityComponent
|
||||
{
|
||||
if (!Synced)
|
||||
{
|
||||
Sync();
|
||||
Synced = true;
|
||||
}
|
||||
exists = entitiesDB.Exists<T>(blockID);
|
||||
if (exists)
|
||||
return ref entitiesDB.QueryEntity<T>(blockID);
|
||||
T[] structHolder = new T[1];
|
||||
return ref structHolder[0];
|
||||
}
|
||||
|
||||
public bool BlockExists(EGID id)
|
||||
{
|
||||
if (!Synced)
|
||||
{
|
||||
Sync();
|
||||
Synced = true;
|
||||
}
|
||||
return entitiesDB.Exists<DBEntityStruct>(id);
|
||||
}
|
||||
|
||||
public bool GetBlockInfoExists<T>(EGID blockID) where T : struct, IEntityComponent
|
||||
{
|
||||
if (!Synced)
|
||||
{
|
||||
Sync();
|
||||
Synced = true;
|
||||
}
|
||||
return entitiesDB.Exists<T>(blockID);
|
||||
}
|
||||
|
||||
public SimBody[] GetSimBodiesFromID(byte id)
|
||||
{
|
||||
var ret = new FasterList<SimBody>(4);
|
||||
if (!entitiesDB.HasAny<ObjectIdEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP))
|
||||
return new SimBody[0];
|
||||
var oids = entitiesDB.QueryEntities<ObjectIdEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP);
|
||||
var connections = entitiesDB.QueryMappedEntities<GridConnectionsEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP);
|
||||
foreach (ref ObjectIdEntityStruct oid in oids)
|
||||
{
|
||||
if (oid.objectId != id) continue;
|
||||
var rid = connections.Entity(oid.ID.entityID).machineRigidBodyId;
|
||||
foreach (var rb in ret)
|
||||
{
|
||||
if (rb.Id.entityID == rid)
|
||||
goto DUPLICATE; //Multiple Object Identifiers on one rigid body
|
||||
}
|
||||
ret.Add(new SimBody(rid));
|
||||
DUPLICATE: ;
|
||||
}
|
||||
return ret.ToArray();
|
||||
}
|
||||
|
||||
public ObjectIdentifier[] GetObjectIDsFromID(byte id, bool sim)
|
||||
{
|
||||
var ret = new FasterList<ObjectIdentifier>(4);
|
||||
if (!entitiesDB.HasAny<ObjectIdEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP))
|
||||
return new ObjectIdentifier[0];
|
||||
var oids = entitiesDB.QueryEntities<ObjectIdEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP);
|
||||
foreach (ref ObjectIdEntityStruct oid in oids)
|
||||
if (sim ? oid.simObjectId == id : oid.objectId == id)
|
||||
ret.Add(new ObjectIdentifier(oid.ID));
|
||||
return ret.ToArray();
|
||||
}
|
||||
|
||||
public SimBody[] GetConnectedSimBodies(uint id)
|
||||
{
|
||||
var joints = entitiesDB.QueryEntities<JointEntityStruct>(MachineSimulationGroups.JOINTS_GROUP);
|
||||
var list = new FasterList<SimBody>(4);
|
||||
foreach (var joint in joints)
|
||||
{
|
||||
if (joint.jointState == JointState.Broken) continue;
|
||||
if (joint.connectedEntityA == id) list.Add(new SimBody(joint.connectedEntityB));
|
||||
else if (joint.connectedEntityB == id) list.Add(new SimBody(joint.connectedEntityA));
|
||||
}
|
||||
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
public EGID? FindBlockEGID(uint id)
|
||||
{
|
||||
var groups = entitiesDB.FindGroups<DBEntityStruct>();
|
||||
foreach (ExclusiveGroupStruct group in groups)
|
||||
{
|
||||
if (entitiesDB.Exists<DBEntityStruct>(id, group))
|
||||
return new EGID(id, group);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Synchronize newly created entity components with entities DB.
|
||||
/// This forces a partial game tick, so it may be slow.
|
||||
/// This also has the potential to make Gamecraft unstable.
|
||||
/// Use this sparingly.
|
||||
/// </summary>
|
||||
private static void Sync()
|
||||
{
|
||||
DeterministicStepCompositionRootPatch.SubmitEntitiesNow();
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
public EntitiesDB GetEntitiesDB()
|
||||
{
|
||||
return entitiesDB;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
42
GamecraftModdingAPI/Blocks/BlockEventsEngine.cs
Normal file
42
GamecraftModdingAPI/Blocks/BlockEventsEngine.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using GamecraftModdingAPI.Engines;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
using RobocraftX.Common;
|
||||
using Svelto.ECS;
|
||||
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
public class BlockEventsEngine : IReactionaryEngine<DBEntityStruct>
|
||||
{
|
||||
public event EventHandler<BlockPlacedRemovedEventArgs> Placed;
|
||||
public event EventHandler<BlockPlacedRemovedEventArgs> Removed;
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
}
|
||||
|
||||
public EntitiesDB entitiesDB { get; set; }
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public string Name { get; } = "GamecraftModdingAPIBlockEventsEngine";
|
||||
public bool isRemovable { get; } = false;
|
||||
|
||||
public void Add(ref DBEntityStruct entityComponent, EGID egid)
|
||||
{
|
||||
ExceptionUtil.InvokeEvent(Placed, this, new BlockPlacedRemovedEventArgs {ID = egid, Type = (BlockIDs) entityComponent.DBID});
|
||||
}
|
||||
|
||||
public void Remove(ref DBEntityStruct entityComponent, EGID egid)
|
||||
{
|
||||
ExceptionUtil.InvokeEvent(Removed, this, new BlockPlacedRemovedEventArgs {ID = egid, Type = (BlockIDs) entityComponent.DBID});
|
||||
}
|
||||
}
|
||||
|
||||
public struct BlockPlacedRemovedEventArgs
|
||||
{
|
||||
public EGID ID;
|
||||
public BlockIDs Type;
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
using System;
|
||||
|
||||
using TechbloxModdingAPI;
|
||||
using GamecraftModdingAPI;
|
||||
|
||||
namespace TechbloxModdingAPI.Blocks
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
public class BlockException : TechbloxModdingAPIException
|
||||
public class BlockException : GamecraftModdingAPIException
|
||||
{
|
||||
public BlockException()
|
||||
{
|
||||
|
@ -40,26 +40,4 @@ namespace TechbloxModdingAPI.Blocks
|
|||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class WiringException : BlockException
|
||||
{
|
||||
public WiringException()
|
||||
{
|
||||
}
|
||||
|
||||
public WiringException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class WireInvalidException : WiringException
|
||||
{
|
||||
public WireInvalidException()
|
||||
{
|
||||
}
|
||||
|
||||
public WireInvalidException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
270
GamecraftModdingAPI/Blocks/BlockIDs.cs
Normal file
270
GamecraftModdingAPI/Blocks/BlockIDs.cs
Normal file
|
@ -0,0 +1,270 @@
|
|||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
/// <summary>
|
||||
/// Possible block types
|
||||
/// </summary>
|
||||
public enum BlockIDs : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// A custom value for the API. Doesn't exist for Gamecraft.
|
||||
/// </summary>
|
||||
Invalid = ushort.MaxValue,
|
||||
AluminiumCube = 0,
|
||||
AxleS,
|
||||
HingeS = 3,
|
||||
MotorS,
|
||||
HingeM,
|
||||
MotorM,
|
||||
TyreM,
|
||||
AxleM,
|
||||
IronCube,
|
||||
RubberCube,
|
||||
OiledCube,
|
||||
AluminiumConeSegment, //12
|
||||
AluminiumCorner,
|
||||
AluminiumRoundedCorner,
|
||||
AluminiumSlicedCube,
|
||||
AluminiumRoundedSlicedCube,
|
||||
AluminiumCylinder,
|
||||
AluminiumPyramidSegment,
|
||||
AluminiumSlope,
|
||||
AluminiumRoundedSlope,
|
||||
AluminiumSphere,
|
||||
RubberConeSegment, //22
|
||||
RubberCorner,
|
||||
RubberRoundedCorner,
|
||||
RubberSlicedCube,
|
||||
RubberRoundedSlicedCube,
|
||||
RubberCylinder,
|
||||
RubberPyramidSegment,
|
||||
RubberSlope,
|
||||
RubberRoundedSlope,
|
||||
RubberSphere,
|
||||
OiledConeSegment, //32
|
||||
OiledCorner,
|
||||
OiledRoundedCorner,
|
||||
OiledSlicedCube,
|
||||
OiledRoundedSlicedCube,
|
||||
OiledCylinder,
|
||||
OiledPyramidSegment,
|
||||
OiledSlope,
|
||||
OiledRoundedSlope,
|
||||
OiledSphere,
|
||||
IronConeSegment, //42
|
||||
IronCorner,
|
||||
IronRoundedCorner,
|
||||
IronSlicedCube,
|
||||
IronRoundedSlicedCube,
|
||||
IronCylinder,
|
||||
IronPyramidSegment,
|
||||
IronSlope,
|
||||
IronRoundedSlope,
|
||||
IronSphere,
|
||||
GlassCube, //52
|
||||
GlassSlicedCube,
|
||||
GlassSlope,
|
||||
GlassCorner,
|
||||
GlassPyramidSegment,
|
||||
GlassRoundedSlicedCube,
|
||||
GlassRoundedSlope,
|
||||
GlassRoundedCorner,
|
||||
GlassConeSegment,
|
||||
GlassCylinder,
|
||||
GlassSphere,
|
||||
Lever, //63 - two IDs skipped
|
||||
PlayerSpawn = 66, //Crashes without special handling
|
||||
SmallSpawn,
|
||||
MediumSpawn,
|
||||
LargeSpawn,
|
||||
BallJoint,
|
||||
UniversalJoint,
|
||||
ServoAxle,
|
||||
ServoHinge,
|
||||
StepperAxle,
|
||||
StepperHinge,
|
||||
TelescopicJoint,
|
||||
DampedSpring,
|
||||
ServoPiston,
|
||||
StepperPiston,
|
||||
PneumaticPiston,
|
||||
PneumaticHinge,
|
||||
PneumaticAxle, //82
|
||||
PilotSeat = 90, //Might crash
|
||||
PassengerSeat,
|
||||
PilotControls,
|
||||
GrassCube,
|
||||
DirtCube,
|
||||
GrassConeSegment,
|
||||
GrassCorner,
|
||||
GrassRoundedCorner,
|
||||
GrassSlicedCube,
|
||||
GrassRoundedSlicedCube,
|
||||
GrassPyramidSegment,
|
||||
GrassSlope,
|
||||
GrassRoundedSlope,
|
||||
DirtConeSegment,
|
||||
DirtCorner,
|
||||
DirtRoundedCorner,
|
||||
DirtSlicedCube,
|
||||
DirtRoundedSlicedCube,
|
||||
DirtPyramidSegment,
|
||||
DirtSlope,
|
||||
DirtRoundedSlope,
|
||||
RubberHemisphere,
|
||||
AluminiumHemisphere,
|
||||
GrassInnerCornerBulged,
|
||||
DirtInnerCornerBulged,
|
||||
IronHemisphere,
|
||||
OiledHemisphere,
|
||||
GlassHemisphere,
|
||||
TyreS,
|
||||
ThreeWaySwitch,
|
||||
Dial, //120
|
||||
CharacterOnEnterTrigger, //Probably crashes
|
||||
CharacterOnLeaveTrigger,
|
||||
CharacterOnStayTrigger,
|
||||
ObjectOnEnterTrigger,
|
||||
ObjectOnLeaveTrigger,
|
||||
ObjectOnStayTrigger,
|
||||
Button,
|
||||
Switch,
|
||||
TextBlock, //Brings up a screen
|
||||
ConsoleBlock, //Brings up a screen
|
||||
Door,
|
||||
GlassDoor,
|
||||
PoweredDoor,
|
||||
PoweredGlassDoor,
|
||||
AluminiumTubeCorner,
|
||||
IronTubeCorner,
|
||||
WoodCube,
|
||||
WoodSlicedCube,
|
||||
WoodSlope,
|
||||
WoodCorner,
|
||||
WoodPyramidSegment,
|
||||
WoodConeSegment,
|
||||
WoodRoundedSlicedCube,
|
||||
WoodRoundedSlope,
|
||||
WoodRoundedCorner,
|
||||
WoodCylinder,
|
||||
WoodHemisphere,
|
||||
WoodSphere,
|
||||
BrickCube, //149
|
||||
BrickSlicedCube = 151,
|
||||
BrickSlope,
|
||||
BrickCorner,
|
||||
ConcreteCube,
|
||||
ConcreteSlicedCube,
|
||||
ConcreteSlope,
|
||||
ConcreteCorner,
|
||||
RoadCarTyre,
|
||||
OffRoadCarTyre,
|
||||
RacingCarTyre,
|
||||
BicycleTyre,
|
||||
FrontBikeTyre,
|
||||
RearBikeTyre,
|
||||
ChopperBikeTyre,
|
||||
TractorTyre,
|
||||
MonsterTruckTyre,
|
||||
MotocrossBikeTyre,
|
||||
CartTyre, //168
|
||||
ObjectIdentifier,
|
||||
ANDLogicBlock,
|
||||
NANDLogicBlock,
|
||||
NORLogicBlock,
|
||||
NOTLogicBlock,
|
||||
ORLogicBlock,
|
||||
XNORLogicBlock,
|
||||
XORLogicBlock,
|
||||
AbsoluteMathsBlock,
|
||||
AdderMathsBlock,
|
||||
DividerMathsBlock,
|
||||
SignMathsBlock, //180
|
||||
MaxMathsBlock,
|
||||
MinMathsBlock,
|
||||
MultiplierMathsBlock,
|
||||
SubtractorMathsBlock,
|
||||
SimpleConnector,
|
||||
MeanMathsBlock,
|
||||
Bit,
|
||||
Counter,
|
||||
Timer,
|
||||
ObjectFilter,
|
||||
PlayerFilter,
|
||||
TeamFilter,
|
||||
Number2Text, //193
|
||||
BeachTree1 = 200,
|
||||
BeachTree2,
|
||||
BeachTree3,
|
||||
Rock1,
|
||||
Rock2,
|
||||
Rock3,
|
||||
Rock4,
|
||||
BirchTree1,
|
||||
BirchTree2,
|
||||
BirchTree3,
|
||||
PineTree1,
|
||||
PineTree2,
|
||||
PineTree3,
|
||||
Flower1,
|
||||
Flower2,
|
||||
Flower3,
|
||||
Shrub1,
|
||||
Shrub2,
|
||||
Shrub3,
|
||||
CliffCube,
|
||||
CliffSlicedCorner,
|
||||
CliffCornerA,
|
||||
CliffCornerB,
|
||||
CliffSlopeA,
|
||||
CliffSlopeB,
|
||||
GrassEdge,
|
||||
GrassEdgeInnerCorner,
|
||||
GrassEdgeCorner,
|
||||
GrassEdgeSlope,
|
||||
CentreHUD,
|
||||
ObjectiveHUD,
|
||||
GameStatsHUD, //231
|
||||
GameOverBlock,
|
||||
SFXBlockGameplay=240,
|
||||
SFXBlock8Bit,
|
||||
SFXBlockInstrument,
|
||||
SFXBlockSciFi,
|
||||
SFXBlockLoops,
|
||||
SFXBlockVocal,
|
||||
MovementConstrainer, //246
|
||||
RotationConstrainer,
|
||||
AdvancedMovementDampener,
|
||||
AdvancedRotationDampener,
|
||||
Mover = 250,
|
||||
Rotator,
|
||||
MovementDampener,
|
||||
RotationDampener,
|
||||
AdvancedMover,
|
||||
AdvancedRotator,
|
||||
MusicBlock, //256
|
||||
PlasmaCannonBlock,
|
||||
MagmaRockCube=777,
|
||||
MagmaRockCubeSliced,
|
||||
MagmaRockSlope,
|
||||
MagmaRockCorner,
|
||||
MagmaRockPyramidSegment,
|
||||
MagmaRockConeSegment,
|
||||
MagmaRockSlicedRounded,
|
||||
MagmaRockSlopeRounded,
|
||||
MagmaRockCornerRounded,
|
||||
HexNetCube,
|
||||
HexNetCubeSliced,
|
||||
HexNetSlope,
|
||||
HexNetCorner,
|
||||
HexNetPyramidSegment,
|
||||
HexNetConeSegment,
|
||||
HexNetSlicedRounded,
|
||||
HexNetSlopeRounded,
|
||||
HexNetCornerRounded, //794
|
||||
MagmaRockBulgedInner,
|
||||
HexNetCylinder=797,
|
||||
HexNetHemisphere,
|
||||
HexNetSphere,
|
||||
HexNetTubeCorner //800
|
||||
}
|
||||
}
|
42
GamecraftModdingAPI/Blocks/BlockIdentifiers.cs
Normal file
42
GamecraftModdingAPI/Blocks/BlockIdentifiers.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
using Svelto.ECS;
|
||||
using RobocraftX.Common;
|
||||
|
||||
using HarmonyLib;
|
||||
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
/// <summary>
|
||||
/// ExclusiveGroups and IDs used with blocks
|
||||
/// </summary>
|
||||
public static class BlockIdentifiers
|
||||
{
|
||||
/// <summary>
|
||||
/// Blocks placed by the player
|
||||
/// </summary> - TODO
|
||||
//public static ExclusiveGroup OWNED_BLOCKS { get { return CommonExclusiveGroups.REAL_BLOCKS_GROUPS_DON_T_USE_IN_NEW_CODE; } }
|
||||
|
||||
/// <summary>
|
||||
/// Extra parts used in functional blocks
|
||||
/// </summary>
|
||||
public static ExclusiveGroup FUNCTIONAL_BLOCK_PARTS { get { return CommonExclusiveGroups.FUNCTIONAL_BLOCK_PART_GROUP; } }
|
||||
|
||||
/// <summary>
|
||||
/// Blocks which are disabled in Simulation mode
|
||||
/// </summary>
|
||||
public static ExclusiveGroup SIM_BLOCKS_DISABLED { get { return CommonExclusiveGroups.DISABLED_JOINTS_IN_SIM_GROUP; } }
|
||||
|
||||
//public static ExclusiveGroup SPAWN_POINTS { get { return CommonExclusiveGroups.SPAWN_POINTS_GROUP; } }
|
||||
|
||||
//public static ExclusiveGroup SPAWN_POINTS_DISABLED { get { return CommonExclusiveGroups.SPAWN_POINTS_DISABLED_GROUP; } }
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the most recently placed block
|
||||
/// </summary>
|
||||
public static uint LatestBlockID {
|
||||
get
|
||||
{ //Need the private field as the property increments itself
|
||||
return ((uint) AccessTools.Field(typeof(CommonExclusiveGroups), "_nextBlockEntityID").GetValue(null)) - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
77
GamecraftModdingAPI/Blocks/BlockTests.cs
Normal file
77
GamecraftModdingAPI/Blocks/BlockTests.cs
Normal file
|
@ -0,0 +1,77 @@
|
|||
using System;
|
||||
|
||||
using GamecraftModdingAPI;
|
||||
using GamecraftModdingAPI.Tests;
|
||||
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
#if TEST
|
||||
/// <summary>
|
||||
/// Block test cases. Not accessible in release versions.
|
||||
/// </summary>
|
||||
[APITestClass]
|
||||
public static class BlockTests
|
||||
{
|
||||
[APITestCase(TestType.EditMode)]
|
||||
public static void TestPlaceNew()
|
||||
{
|
||||
Block newBlock = Block.PlaceNew(BlockIDs.AluminiumCube, Unity.Mathematics.float3.zero);
|
||||
Assert.NotNull(newBlock.Id, "Newly placed block is missing Id. This should be populated when the block is placed.", "Newly placed block Id is not null, block successfully placed.");
|
||||
}
|
||||
|
||||
[APITestCase(TestType.EditMode)]
|
||||
public static void TestSync()
|
||||
{
|
||||
Block newBlock = Block.PlaceNew(BlockIDs.AluminiumCube, Unity.Mathematics.float3.zero + 2);
|
||||
if (!Assert.CloseTo(newBlock.Position, (Unity.Mathematics.float3.zero + 2), $"Newly placed block at {newBlock.Position} is expected at {Unity.Mathematics.float3.zero + 2}.", "Newly placed block position matches.")) return;
|
||||
Assert.Equal(newBlock.Exists, true, "Newly placed block does not exist, possibly because Sync() skipped/missed/failed.", "Newly placed block exists, Sync() successful.");
|
||||
}
|
||||
|
||||
[APITestCase(TestType.EditMode)]
|
||||
public static void TestTextBlock()
|
||||
{
|
||||
Block newBlock = Block.PlaceNew(BlockIDs.TextBlock, Unity.Mathematics.float3.zero + 1);
|
||||
TextBlock textBlock = null; // Note: the assignment operation is a lambda, which slightly confuses the compiler
|
||||
Assert.Errorless(() => { textBlock = newBlock.Specialise<TextBlock>(); }, "Block.Specialize<TextBlock>() raised an exception: ", "Block.Specialize<TextBlock>() completed without issue.");
|
||||
if (!Assert.NotNull(textBlock, "Block.Specialize<TextBlock>() returned null, possibly because it failed silently.", "Specialized TextBlock is not null.")) return;
|
||||
if (!Assert.NotNull(textBlock.Text, "TextBlock.Text is null, possibly because it failed silently.", "TextBlock.Text is not null.")) return;
|
||||
if (!Assert.NotNull(textBlock.TextBlockId, "TextBlock.TextBlockId is null, possibly because it failed silently.", "TextBlock.TextBlockId is not null.")) return;
|
||||
}
|
||||
|
||||
[APITestCase(TestType.EditMode)]
|
||||
public static void TestMotor()
|
||||
{
|
||||
Block newBlock = Block.PlaceNew(BlockIDs.MotorS, Unity.Mathematics.float3.zero + 1);
|
||||
Motor b = null; // Note: the assignment operation is a lambda, which slightly confuses the compiler
|
||||
Assert.Errorless(() => { b = newBlock.Specialise<Motor>(); }, "Block.Specialize<Motor>() raised an exception: ", "Block.Specialize<Motor>() completed without issue.");
|
||||
if (!Assert.NotNull(b, "Block.Specialize<Motor>() returned null, possibly because it failed silently.", "Specialized Motor is not null.")) return;
|
||||
if (!Assert.CloseTo(b.Torque, 75f, $"Motor.Torque {b.Torque} does not equal default value, possibly because it failed silently.", "Motor.Torque close enough to default.")) return;
|
||||
if (!Assert.CloseTo(b.TopSpeed, 30f, $"Motor.TopSpeed {b.TopSpeed} does not equal default value, possibly because it failed silently.", "Motor.Torque is close enough to default.")) return;
|
||||
if (!Assert.Equal(b.Reverse, false, $"Motor.Reverse {b.Reverse} does not equal default value, possibly because it failed silently.", "Motor.Reverse is default.")) return;
|
||||
}
|
||||
|
||||
[APITestCase(TestType.EditMode)]
|
||||
public static void TestPiston()
|
||||
{
|
||||
Block newBlock = Block.PlaceNew(BlockIDs.PneumaticPiston, Unity.Mathematics.float3.zero + 1);
|
||||
Piston b = null; // Note: the assignment operation is a lambda, which slightly confuses the compiler
|
||||
Assert.Errorless(() => { b = newBlock.Specialise<Piston>(); }, "Block.Specialize<Piston>() raised an exception: ", "Block.Specialize<Piston>() completed without issue.");
|
||||
if (!Assert.NotNull(b, "Block.Specialize<Piston>() returned null, possibly because it failed silently.", "Specialized Piston is not null.")) return;
|
||||
if (!Assert.CloseTo(b.MaximumExtension, 1.01f, $"Piston.MaximumExtension {b.MaximumExtension} does not equal default value, possibly because it failed silently.", "Piston.MaximumExtension is close enough to default.")) return;
|
||||
if (!Assert.CloseTo(b.MaximumForce, 750f, $"Piston.MaximumForce {b.MaximumForce} does not equal default value, possibly because it failed silently.", "Piston.MaximumForce is close enough to default.")) return;
|
||||
}
|
||||
|
||||
[APITestCase(TestType.EditMode)]
|
||||
public static void TestServo()
|
||||
{
|
||||
Block newBlock = Block.PlaceNew(BlockIDs.ServoAxle, Unity.Mathematics.float3.zero + 1);
|
||||
Servo b = null; // Note: the assignment operation is a lambda, which slightly confuses the compiler
|
||||
Assert.Errorless(() => { b = newBlock.Specialise<Servo>(); }, "Block.Specialize<Servo>() raised an exception: ", "Block.Specialize<Servo>() completed without issue.");
|
||||
if (!Assert.NotNull(b, "Block.Specialize<Servo>() returned null, possibly because it failed silently.", "Specialized Servo is not null.")) return;
|
||||
if (!Assert.CloseTo(b.MaximumAngle, 180f, $"Servo.MaximumAngle {b.MaximumAngle} does not equal default value, possibly because it failed silently.", "Servo.MaximumAngle is close enough to default.")) return;
|
||||
if (!Assert.CloseTo(b.MinimumAngle, -180f, $"Servo.MinimumAngle {b.MinimumAngle} does not equal default value, possibly because it failed silently.", "Servo.MinimumAngle is close enough to default.")) return;
|
||||
if (!Assert.CloseTo(b.MaximumForce, 750f, $"Servo.MaximumForce {b.MaximumForce} does not equal default value, possibly because it failed silently.", "Servo.MaximumForce is close enough to default.")) return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
90
GamecraftModdingAPI/Blocks/ConsoleBlock.cs
Normal file
90
GamecraftModdingAPI/Blocks/ConsoleBlock.cs
Normal file
|
@ -0,0 +1,90 @@
|
|||
using System;
|
||||
|
||||
using RobocraftX.Blocks;
|
||||
using RobocraftX.Common;
|
||||
using Svelto.ECS;
|
||||
using Unity.Mathematics;
|
||||
|
||||
using GamecraftModdingAPI;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
public class ConsoleBlock : Block
|
||||
{
|
||||
public static ConsoleBlock PlaceNew(float3 position,
|
||||
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
||||
int uscale = 1, float3 scale = default, Player player = null)
|
||||
{
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
EGID id = PlacementEngine.PlaceBlock(BlockIDs.ConsoleBlock, color, darkness,
|
||||
position, uscale, scale, player, rotation);
|
||||
return new ConsoleBlock(id);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ConsoleBlock(EGID id): base(id)
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<ConsoleBlockEntityStruct>(this.Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
public ConsoleBlock(uint id): base(new EGID(id, CommonExclusiveGroups.BUILD_CONSOLE_BLOCK_GROUP))
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<ConsoleBlockEntityStruct>(this.Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
// custom console block properties
|
||||
|
||||
public string Command
|
||||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo<ConsoleBlockEntityStruct>(Id).commandName;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.GetBlockInfo<ConsoleBlockEntityStruct>(Id).commandName.Set(value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Arg1
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<ConsoleBlockEntityStruct>(Id).arg1;
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.GetBlockInfo<ConsoleBlockEntityStruct>(Id).arg1.Set(value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Arg2
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<ConsoleBlockEntityStruct>(Id).arg2;
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.GetBlockInfo<ConsoleBlockEntityStruct>(Id).arg2.Set(value);
|
||||
}
|
||||
}
|
||||
|
||||
public string Arg3
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<ConsoleBlockEntityStruct>(Id).arg3;
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.GetBlockInfo<ConsoleBlockEntityStruct>(Id).arg3.Set(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
106
GamecraftModdingAPI/Blocks/Motor.cs
Normal file
106
GamecraftModdingAPI/Blocks/Motor.cs
Normal file
|
@ -0,0 +1,106 @@
|
|||
using System;
|
||||
|
||||
using RobocraftX.Blocks;
|
||||
using RobocraftX.Common;
|
||||
using Svelto.ECS;
|
||||
using Unity.Mathematics;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
public class Motor : Block
|
||||
{
|
||||
/// <summary>
|
||||
/// Places a new motor.
|
||||
/// Any valid motor type is accepted.
|
||||
/// This re-implements Block.PlaceNew(...)
|
||||
/// </summary>
|
||||
public static new Motor PlaceNew(BlockIDs block, float3 position,
|
||||
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
||||
int uscale = 1, float3 scale = default, Player player = null)
|
||||
{
|
||||
if (!(block == BlockIDs.MotorS || block == BlockIDs.MotorM))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {typeof(Motor).Name} block");
|
||||
}
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
|
||||
position, uscale, scale, player, rotation);
|
||||
return new Motor(id);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Motor(EGID id) : base(id)
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<MotorReadOnlyStruct>(this.Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
public Motor(uint id): base(new EGID(id, CommonExclusiveGroups.BUILD_MOTOR_BLOCK_GROUP))
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<MotorReadOnlyStruct>(this.Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
// custom motor properties
|
||||
|
||||
/// <summary>
|
||||
/// The motor's maximum rotational velocity.
|
||||
/// </summary>
|
||||
public float TopSpeed
|
||||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo<MotorReadOnlyStruct>(Id).maxVelocity;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ref MotorReadOnlyStruct motor = ref BlockEngine.GetBlockInfo<MotorReadOnlyStruct>(Id);
|
||||
motor.maxVelocity = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The motor's maximum rotational force.
|
||||
/// </summary>
|
||||
public float Torque
|
||||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo<MotorReadOnlyStruct>(Id).maxForce;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ref MotorReadOnlyStruct motor = ref BlockEngine.GetBlockInfo<MotorReadOnlyStruct>(Id);
|
||||
motor.maxForce = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The motor's direction.
|
||||
/// </summary>
|
||||
public bool Reverse
|
||||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo<MotorReadOnlyStruct>(Id).reverse;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ref MotorReadOnlyStruct motor = ref BlockEngine.GetBlockInfo<MotorReadOnlyStruct>(Id);
|
||||
motor.reverse = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +1,21 @@
|
|||
using RobocraftX.Common;
|
||||
using RobocraftX.DOTS;
|
||||
using RobocraftX.UECS;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.EntityStructs;
|
||||
using Unity.Mathematics;
|
||||
using Unity.Transforms;
|
||||
using Unity.Mathematics;
|
||||
|
||||
using TechbloxModdingAPI.Engines;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
using GamecraftModdingAPI.Engines;
|
||||
|
||||
namespace TechbloxModdingAPI.Blocks.Engines
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
/// <summary>
|
||||
/// Engine which executes block movement actions
|
||||
/// </summary>
|
||||
public class MovementEngine : IApiEngine
|
||||
{
|
||||
public string Name { get; } = "TechbloxModdingAPIMovementGameEngine";
|
||||
public string Name { get; } = "GamecraftModdingAPIMovementGameEngine";
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
|
@ -35,12 +35,12 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
|
||||
// implementations for Movement static class
|
||||
|
||||
internal float3 MoveBlock(Block block, float3 vector)
|
||||
public float3 MoveBlock(EGID blockID, float3 vector)
|
||||
{
|
||||
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 DOTSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntityOrDefault<DOTSPhysicsEntityStruct>(block);
|
||||
ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntity<PositionEntityStruct>(blockID);
|
||||
ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntity<GridRotationStruct>(blockID);
|
||||
ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntity<LocalTransformEntityStruct>(blockID);
|
||||
ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntity<UECSPhysicsEntityStruct>(blockID);
|
||||
// main (persistent) position
|
||||
posStruct.position = vector;
|
||||
// placement grid position
|
||||
|
@ -48,21 +48,18 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
// rendered position
|
||||
transStruct.position = vector;
|
||||
// collision position
|
||||
if (phyStruct.ID != default)
|
||||
{ //It exists
|
||||
FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.dotsEntity, new Translation
|
||||
{
|
||||
Value = posStruct.position
|
||||
});
|
||||
}
|
||||
|
||||
entitiesDB.QueryEntityOrDefault<GridConnectionsEntityStruct>(block).isProcessed = false;
|
||||
FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.uecsEntity, new Translation
|
||||
{
|
||||
Value = posStruct.position
|
||||
});
|
||||
entitiesDB.QueryEntity<GridConnectionsEntityStruct>(blockID).isProcessed = false;
|
||||
return posStruct.position;
|
||||
}
|
||||
|
||||
internal float3 GetPosition(Block block)
|
||||
public float3 GetPosition(EGID blockID)
|
||||
{
|
||||
return entitiesDB.QueryEntityOrDefault<PositionEntityStruct>(block).position;
|
||||
ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntity<PositionEntityStruct>(blockID);
|
||||
return posStruct.position;
|
||||
}
|
||||
}
|
||||
}
|
57
GamecraftModdingAPI/Blocks/ObjectIdentifier.cs
Normal file
57
GamecraftModdingAPI/Blocks/ObjectIdentifier.cs
Normal file
|
@ -0,0 +1,57 @@
|
|||
using Gamecraft.Wires;
|
||||
using RobocraftX.Common;
|
||||
using Svelto.ECS;
|
||||
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
public class ObjectIdentifier : Block
|
||||
{
|
||||
public ObjectIdentifier(EGID id) : base(id)
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<ObjectIdEntityStruct>(Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectIdentifier(uint id) : base(new EGID(id, CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP))
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<ObjectIdEntityStruct>(Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
public char Identifier
|
||||
{
|
||||
get => (char) (BlockEngine.GetBlockInfo<ObjectIdEntityStruct>(Id).objectId + 'A');
|
||||
set
|
||||
{
|
||||
BlockEngine.GetBlockInfo<ObjectIdEntityStruct>(Id).objectId = (byte) (value - 'A');
|
||||
Label = value + ""; //The label isn't updated automatically
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulation-time ID. Assigned by the game starting from 0.
|
||||
/// </summary>
|
||||
public byte SimID
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<ObjectIdEntityStruct>(Id).simObjectId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the identifier blocks with the given ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID to look for</param>
|
||||
/// <returns>An array that may be empty</returns>
|
||||
public static ObjectIdentifier[] GetByID(char id) => BlockEngine.GetObjectIDsFromID((byte) (id - 'A'), false);
|
||||
|
||||
/// <summary>
|
||||
/// Finds the identifier blocks with the given simulation-time ID. This ID is assigned by the game starting from 0.
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public static ObjectIdentifier[] GetBySimID(byte id) => BlockEngine.GetObjectIDsFromID(id, true);
|
||||
}
|
||||
}
|
83
GamecraftModdingAPI/Blocks/Piston.cs
Normal file
83
GamecraftModdingAPI/Blocks/Piston.cs
Normal file
|
@ -0,0 +1,83 @@
|
|||
using System;
|
||||
|
||||
using RobocraftX.Blocks;
|
||||
using Svelto.ECS;
|
||||
using Unity.Mathematics;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
using RobocraftX.Common;
|
||||
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
public class Piston : Block
|
||||
{
|
||||
/// <summary>
|
||||
/// Places a new piston.
|
||||
/// Any valid piston type is accepted.
|
||||
/// This re-implements Block.PlaceNew(...)
|
||||
/// </summary>
|
||||
public static new Piston PlaceNew(BlockIDs block, float3 position,
|
||||
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
||||
int uscale = 1, float3 scale = default, Player player = null)
|
||||
{
|
||||
if (!(block == BlockIDs.ServoPiston || block == BlockIDs.StepperPiston || block == BlockIDs.PneumaticPiston))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {typeof(Piston).Name} block");
|
||||
}
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
|
||||
position, uscale, scale, player, rotation);
|
||||
return new Piston(id);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Piston(EGID id) : base(id)
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<PistonReadOnlyStruct>(this.Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
public Piston(uint id) : base(new EGID(id, CommonExclusiveGroups.BUILD_PISTON_BLOCK_GROUP))
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<PistonReadOnlyStruct>(this.Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
// custom piston properties
|
||||
|
||||
/// <summary>
|
||||
/// The piston's max extension distance.
|
||||
/// </summary>
|
||||
public float MaximumExtension
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<PistonReadOnlyStruct>(Id).maxDeviation;
|
||||
|
||||
set
|
||||
{
|
||||
ref PistonReadOnlyStruct piston = ref BlockEngine.GetBlockInfo<PistonReadOnlyStruct>(Id);
|
||||
piston.maxDeviation = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The piston's max extension force.
|
||||
/// </summary>
|
||||
public float MaximumForce
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<PistonReadOnlyStruct>(Id).maxForce;
|
||||
|
||||
set
|
||||
{
|
||||
ref PistonReadOnlyStruct piston = ref BlockEngine.GetBlockInfo<PistonReadOnlyStruct>(Id);
|
||||
piston.maxForce = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
132
GamecraftModdingAPI/Blocks/PlacementEngine.cs
Normal file
132
GamecraftModdingAPI/Blocks/PlacementEngine.cs
Normal file
|
@ -0,0 +1,132 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using DataLoader;
|
||||
using HarmonyLib;
|
||||
using RobocraftX.Blocks;
|
||||
using RobocraftX.Blocks.Scaling;
|
||||
using RobocraftX.Character;
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.CR.MachineEditing;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.EntityStructs;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
using GamecraftModdingAPI.Engines;
|
||||
using GamecraftModdingAPI.Players;
|
||||
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
/// <summary>
|
||||
/// Engine which executes block placement actions
|
||||
/// </summary>
|
||||
public class PlacementEngine : IApiEngine
|
||||
{
|
||||
public bool IsInGame;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
IsInGame = false;
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
IsInGame = true;
|
||||
}
|
||||
|
||||
public EntitiesDB entitiesDB { get; set; }
|
||||
private static BlockEntityFactory _blockEntityFactory; //Injected from PlaceBlockEngine
|
||||
|
||||
public EGID PlaceBlock(BlockIDs block, BlockColors color, byte darkness, float3 position, int uscale,
|
||||
float3 scale, Player player, float3 rotation)
|
||||
{ //It appears that only the non-uniform scale has any visible effect, but if that's not given here it will be set to the uniform one
|
||||
if (darkness > 9)
|
||||
throw new Exception("That is too dark. Make sure to use 0-9 as darkness. (0 is default.)");
|
||||
return BuildBlock((ushort) block, (byte) (color + darkness * 10), position, uscale, scale, rotation,
|
||||
(player ?? new Player(PlayerType.Local)).Id);
|
||||
}
|
||||
|
||||
private EGID BuildBlock(ushort block, byte color, float3 position, int uscale, float3 scale, float3 rot, uint playerId)
|
||||
{
|
||||
if (_blockEntityFactory == null)
|
||||
throw new Exception("The factory is null.");
|
||||
if (uscale < 1)
|
||||
throw new Exception("Scale needs to be at least 1");
|
||||
if (scale.x < 4e-5) scale.x = uscale;
|
||||
if (scale.y < 4e-5) scale.y = uscale;
|
||||
if (scale.z < 4e-5) scale.z = uscale;
|
||||
uint dbid = block;
|
||||
if (!PrefabsID.DBIDMAP.ContainsKey(dbid))
|
||||
throw new Exception("Block with ID " + dbid + " not found!");
|
||||
//RobocraftX.CR.MachineEditing.PlaceBlockEngine
|
||||
ScalingEntityStruct scaling = new ScalingEntityStruct {scale = scale};
|
||||
Quaternion rotQ = Quaternion.Euler(rot);
|
||||
RotationEntityStruct rotation = new RotationEntityStruct {rotation = rotQ};
|
||||
GridRotationStruct gridRotation = new GridRotationStruct
|
||||
{position = position, rotation = rotQ};
|
||||
DBEntityStruct dbEntity = new DBEntityStruct {DBID = dbid};
|
||||
BlockPlacementScaleEntityStruct placementScale = new BlockPlacementScaleEntityStruct
|
||||
{
|
||||
blockPlacementHeight = uscale, blockPlacementWidth = uscale, desiredScaleFactor = uscale,
|
||||
snapGridScale = uscale,
|
||||
unitSnapOffset = 0, isUsingUnitSize = true
|
||||
};
|
||||
EquippedColourStruct colour = new EquippedColourStruct {indexInPalette = color};
|
||||
|
||||
EntityComponentInitializer
|
||||
structInitializer =
|
||||
_blockEntityFactory.Build(CommonExclusiveGroups.nextBlockEntityID, dbid); //The ghost block index is only used for triggers
|
||||
if (colour.indexInPalette != byte.MaxValue)
|
||||
structInitializer.Init(new ColourParameterEntityStruct
|
||||
{
|
||||
indexInPalette = colour.indexInPalette,
|
||||
needsUpdate = true
|
||||
});
|
||||
uint prefabId = PrefabsID.GetPrefabId(dbid, 0);
|
||||
structInitializer.Init(new GFXPrefabEntityStructGPUI(prefabId));
|
||||
structInitializer.Init(new PhysicsPrefabEntityStruct(prefabId));
|
||||
structInitializer.Init(dbEntity);
|
||||
structInitializer.Init(new PositionEntityStruct {position = position});
|
||||
structInitializer.Init(rotation);
|
||||
structInitializer.Init(scaling);
|
||||
structInitializer.Init(gridRotation);
|
||||
structInitializer.Init(new UniformBlockScaleEntityStruct
|
||||
{
|
||||
scaleFactor = placementScale.desiredScaleFactor
|
||||
});
|
||||
structInitializer.Init(new BlockPlacementInfoStruct()
|
||||
{
|
||||
loadedFromDisk = false,
|
||||
placedBy = playerId
|
||||
});
|
||||
PrimaryRotationUtility.InitialisePrimaryDirection(rotation.rotation, ref structInitializer);
|
||||
EGID playerEGID = new EGID(playerId, CharacterExclusiveGroups.OnFootGroup);
|
||||
ref PickedBlockExtraDataStruct pickedBlock = ref entitiesDB.QueryEntity<PickedBlockExtraDataStruct>(playerEGID);
|
||||
pickedBlock.placedBlockEntityID = structInitializer.EGID;
|
||||
pickedBlock.placedBlockWasAPickedBlock = false;
|
||||
Block.BlockEngine.Synced = false; // Block entities will need to be submitted before properties can be used
|
||||
return structInitializer.EGID;
|
||||
}
|
||||
|
||||
public string Name { get; } = "GamecraftModdingAPIPlacementGameEngine";
|
||||
|
||||
public bool isRemovable => false;
|
||||
|
||||
[HarmonyPatch]
|
||||
public class FactoryObtainerPatch
|
||||
{
|
||||
static void Postfix(BlockEntityFactory blockEntityFactory)
|
||||
{
|
||||
_blockEntityFactory = blockEntityFactory;
|
||||
Logging.MetaDebugLog("Block entity factory injected.");
|
||||
}
|
||||
|
||||
static MethodBase TargetMethod(Harmony instance)
|
||||
{
|
||||
return AccessTools.TypeByName("RobocraftX.CR.MachineEditing.PlaceBlockEngine").GetConstructors()[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,14 +3,12 @@ using System.Reflection;
|
|||
using HarmonyLib;
|
||||
using RobocraftX.Blocks;
|
||||
using RobocraftX.Common;
|
||||
using Svelto.Common;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.Native;
|
||||
|
||||
using TechbloxModdingAPI.Engines;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
using GamecraftModdingAPI.Engines;
|
||||
|
||||
namespace TechbloxModdingAPI.Blocks.Engines
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
public class RemovalEngine : IApiEngine
|
||||
{
|
||||
|
@ -22,11 +20,8 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
if (!entitiesDB.Exists<MachineGraphConnectionsEntityStruct>(target))
|
||||
return false;
|
||||
var connections = entitiesDB.QueryEntity<MachineGraphConnectionsEntityStruct>(target);
|
||||
var groups = entitiesDB.FindGroups<MachineGraphConnectionsEntityStruct>();
|
||||
using var connStructMapper = //The allocator needs to be persistent because that's what is used in the Dispose() method
|
||||
entitiesDB.QueryNativeMappedEntities<MachineGraphConnectionsEntityStruct>(groups, Allocator.Persistent);
|
||||
for (int i = connections.connections.Count<MachineConnectionStruct>() - 1; i >= 0; i--)
|
||||
_connectionFactory.RemoveConnection(connections, i, connStructMapper);
|
||||
_connectionFactory.RemoveConnection(connections, i, entitiesDB);
|
||||
_entityFunctions.RemoveEntity<BlockEntityDescriptor>(target);
|
||||
return true;
|
||||
}
|
||||
|
@ -41,12 +36,12 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
{
|
||||
}
|
||||
|
||||
public string Name { get; } = "TechbloxModdingAPIRemovalGameEngine";
|
||||
public string Name { get; } = "GamecraftModdingAPIRemovalGameEngine";
|
||||
|
||||
public bool isRemovable => false;
|
||||
|
||||
[HarmonyPatch]
|
||||
class FactoryObtainerPatch
|
||||
public class FactoryObtainerPatch
|
||||
{
|
||||
static void Postfix(IEntityFunctions entityFunctions,
|
||||
MachineGraphConnectionEntityFactory machineGraphConnectionEntityFactory)
|
72
GamecraftModdingAPI/Blocks/RotationEngine.cs
Normal file
72
GamecraftModdingAPI/Blocks/RotationEngine.cs
Normal file
|
@ -0,0 +1,72 @@
|
|||
using RobocraftX.Common;
|
||||
using RobocraftX.UECS;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.EntityStructs;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
using GamecraftModdingAPI.Engines;
|
||||
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
/// <summary>
|
||||
/// Engine which executes block movement actions
|
||||
/// </summary>
|
||||
public class RotationEngine : IApiEngine
|
||||
{
|
||||
public string Name { get; } = "GamecraftModdingAPIRotationGameEngine";
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
public bool isRemovable => false;
|
||||
|
||||
public bool IsInGame = false;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
IsInGame = false;
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
IsInGame = true;
|
||||
}
|
||||
|
||||
// implementations for Rotation static class
|
||||
|
||||
public float3 RotateBlock(EGID blockID, Vector3 vector)
|
||||
{
|
||||
ref RotationEntityStruct rotStruct = ref this.entitiesDB.QueryEntity<RotationEntityStruct>(blockID);
|
||||
ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntity<GridRotationStruct>(blockID);
|
||||
ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntity<LocalTransformEntityStruct>(blockID);
|
||||
ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntity<UECSPhysicsEntityStruct>(blockID);
|
||||
// main (persistent) position
|
||||
Quaternion newRotation = (Quaternion)rotStruct.rotation;
|
||||
newRotation.eulerAngles += vector;
|
||||
rotStruct.rotation = (quaternion)newRotation;
|
||||
// placement grid rotation
|
||||
Quaternion newGridRotation = (Quaternion)gridStruct.rotation;
|
||||
newGridRotation.eulerAngles += vector;
|
||||
gridStruct.rotation = (quaternion)newGridRotation;
|
||||
// rendered position
|
||||
Quaternion newTransRotation = (Quaternion)rotStruct.rotation;
|
||||
newTransRotation.eulerAngles += vector;
|
||||
transStruct.rotation = newTransRotation;
|
||||
// collision position
|
||||
FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.uecsEntity, new Unity.Transforms.Rotation
|
||||
{
|
||||
Value = rotStruct.rotation
|
||||
});
|
||||
entitiesDB.QueryEntity<GridConnectionsEntityStruct>(blockID).isProcessed = false;
|
||||
return ((Quaternion)rotStruct.rotation).eulerAngles;
|
||||
|
||||
}
|
||||
|
||||
public float3 GetRotation(EGID blockID)
|
||||
{
|
||||
ref RotationEntityStruct rotStruct = ref entitiesDB.QueryEntity<RotationEntityStruct>(blockID);
|
||||
return ((Quaternion) rotStruct.rotation).eulerAngles;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,18 +2,18 @@
|
|||
|
||||
using HarmonyLib;
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.DOTS;
|
||||
using RobocraftX.UECS;
|
||||
using Svelto.ECS;
|
||||
using Unity.Entities;
|
||||
|
||||
using TechbloxModdingAPI.Engines;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using GamecraftModdingAPI.Engines;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Blocks.Engines
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
public class ScalingEngine : IApiEngine
|
||||
{
|
||||
private static IReactOnAddAndRemove<DOTSPhysicsEntityCreationStruct> physicsEngine;
|
||||
private static IReactOnAddAndRemove<UECSPhysicsEntityCreationStruct> physicsEngine;
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
|
@ -24,26 +24,29 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
{
|
||||
}
|
||||
|
||||
public string Name { get; } = "TechbloxModdingAPIScalingEngine";
|
||||
public string Name { get; } = "GamecraftModdingAPIScalingEngine";
|
||||
public bool isRemovable { get; } = false;
|
||||
|
||||
private EntityManager _entityManager; //Unity entity manager
|
||||
private static EntityManager _entityManager; //Unity entity manager
|
||||
|
||||
public void UpdateCollision(EGID egid)
|
||||
{
|
||||
if (_entityManager == default)
|
||||
_entityManager = FullGameFields._physicsWorld.EntityManager;
|
||||
//Assuming the block exists
|
||||
var entity = entitiesDB.QueryEntity<DOTSPhysicsEntityStruct>(egid).dotsEntity;
|
||||
var pes = new DOTSPhysicsEntityCreationStruct();
|
||||
physicsEngine.Add(ref pes, egid); //Create new DOTS entity
|
||||
var entity = entitiesDB.QueryEntity<UECSPhysicsEntityStruct>(egid).uecsEntity;
|
||||
var pes = new UECSPhysicsEntityCreationStruct();
|
||||
physicsEngine.Add(ref pes, egid); //Create new UECS entity
|
||||
_entityManager.DestroyEntity(entity);
|
||||
}
|
||||
|
||||
internal void Setup(EntityManager entityManager)
|
||||
{
|
||||
_entityManager = entityManager;
|
||||
}
|
||||
|
||||
[HarmonyPatch]
|
||||
class PhysicsEnginePatch
|
||||
public class PhysicsEnginePatch
|
||||
{
|
||||
static void Postfix(IReactOnAddAndRemove<DOTSPhysicsEntityCreationStruct> __instance)
|
||||
static void Postfix(IReactOnAddAndRemove<UECSPhysicsEntityCreationStruct> __instance)
|
||||
{
|
||||
physicsEngine = __instance;
|
||||
Logging.MetaDebugLog("Physics engine injected.");
|
||||
|
@ -51,7 +54,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
|
||||
static MethodBase TargetMethod(Harmony instance)
|
||||
{
|
||||
return AccessTools.Method("RobocraftX.StateSync.HandleDOTSPhysicEntitiesWithPrefabCreationEngine" +
|
||||
return AccessTools.Method("RobocraftX.StateSync.HandleUECSPhysicEntitiesWithPrefabCreationEngine" +
|
||||
":Ready");
|
||||
}
|
||||
}
|
111
GamecraftModdingAPI/Blocks/Servo.cs
Normal file
111
GamecraftModdingAPI/Blocks/Servo.cs
Normal file
|
@ -0,0 +1,111 @@
|
|||
using System;
|
||||
|
||||
using RobocraftX.Blocks;
|
||||
using RobocraftX.Common;
|
||||
using Svelto.ECS;
|
||||
using Unity.Mathematics;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
public class Servo : Block
|
||||
{
|
||||
/// <summary>
|
||||
/// Places a new servo.
|
||||
/// Any valid servo type is accepted.
|
||||
/// This re-implements Block.PlaceNew(...)
|
||||
/// </summary>
|
||||
public static new Servo PlaceNew(BlockIDs block, float3 position,
|
||||
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
||||
int uscale = 1, float3 scale = default, Player player = null)
|
||||
{
|
||||
if (!(block == BlockIDs.ServoAxle || block == BlockIDs.ServoHinge || block == BlockIDs.ServoPiston))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {nameof(Servo)} block");
|
||||
}
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
|
||||
position, uscale, scale, player, rotation);
|
||||
return new Servo(id);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Servo(EGID id) : base(id)
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<ServoReadOnlyStruct>(this.Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
public Servo(uint id) : base(new EGID(id, CommonExclusiveGroups.BUILD_SERVO_BLOCK_GROUP))
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<ServoReadOnlyStruct>(this.Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
// custom servo properties
|
||||
|
||||
/// <summary>
|
||||
/// The servo's minimum angle.
|
||||
/// </summary>
|
||||
public float MinimumAngle
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(Id).minDeviation;
|
||||
|
||||
set
|
||||
{
|
||||
ref ServoReadOnlyStruct servo = ref BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(Id);
|
||||
servo.minDeviation = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The servo's maximum angle.
|
||||
/// </summary>
|
||||
public float MaximumAngle
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(Id).maxDeviation;
|
||||
|
||||
set
|
||||
{
|
||||
ref ServoReadOnlyStruct servo = ref BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(Id);
|
||||
servo.maxDeviation = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The servo's maximum force.
|
||||
/// </summary>
|
||||
public float MaximumForce
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(Id).maxForce;
|
||||
|
||||
set
|
||||
{
|
||||
ref ServoReadOnlyStruct servo = ref BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(Id);
|
||||
servo.maxForce = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The servo's direction.
|
||||
/// </summary>
|
||||
public bool Reverse
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(Id).reverse;
|
||||
|
||||
set
|
||||
{
|
||||
ref ServoReadOnlyStruct servo = ref BlockEngine.GetBlockInfo<ServoReadOnlyStruct>(Id);
|
||||
servo.reverse = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
195
GamecraftModdingAPI/Blocks/SignalEngine.cs
Normal file
195
GamecraftModdingAPI/Blocks/SignalEngine.cs
Normal file
|
@ -0,0 +1,195 @@
|
|||
using Svelto.ECS;
|
||||
using Svelto.DataStructures;
|
||||
using Gamecraft.Wires;
|
||||
|
||||
using GamecraftModdingAPI.Engines;
|
||||
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
/// <summary>
|
||||
/// Engine which executes signal actions
|
||||
/// </summary>
|
||||
public class SignalEngine : IApiEngine
|
||||
{
|
||||
public const float POSITIVE_HIGH = 1.0f;
|
||||
public const float NEGATIVE_HIGH = -1.0f;
|
||||
public const float HIGH = 1.0f;
|
||||
public const float ZERO = 0.0f;
|
||||
|
||||
public string Name { get; } = "GamecraftModdingAPISignalGameEngine";
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
public bool isRemovable => false;
|
||||
|
||||
public bool IsInGame = false;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
IsInGame = false;
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
IsInGame = true;
|
||||
}
|
||||
|
||||
// implementations for Signal static class
|
||||
|
||||
public bool SetSignal(EGID blockID, float signal, out uint signalID, bool input = true)
|
||||
{
|
||||
signalID = GetSignalIDs(blockID, input)[0];
|
||||
return SetSignal(signalID, signal);
|
||||
}
|
||||
|
||||
public bool SetSignal(uint signalID, float signal, bool input = true)
|
||||
{
|
||||
var array = GetSignalStruct(signalID, out uint index, input);
|
||||
if (array.count > 0) array[index].valueAsFloat = signal;
|
||||
return false;
|
||||
}
|
||||
|
||||
public float AddSignal(EGID blockID, float signal, out uint signalID, bool clamp = true, bool input = true)
|
||||
{
|
||||
signalID = GetSignalIDs(blockID, input)[0];
|
||||
return AddSignal(signalID, signal, clamp, input);
|
||||
}
|
||||
|
||||
public float AddSignal(uint signalID, float signal, bool clamp = true, bool input = true)
|
||||
{
|
||||
var array = GetSignalStruct(signalID, out uint index, input);
|
||||
if (array.count > 0)
|
||||
{
|
||||
ref var channelData = ref array[index];
|
||||
channelData.valueAsFloat += signal;
|
||||
if (clamp)
|
||||
{
|
||||
if (channelData.valueAsFloat > POSITIVE_HIGH)
|
||||
{
|
||||
channelData.valueAsFloat = POSITIVE_HIGH;
|
||||
}
|
||||
else if (channelData.valueAsFloat < NEGATIVE_HIGH)
|
||||
{
|
||||
channelData.valueAsFloat = NEGATIVE_HIGH;
|
||||
}
|
||||
|
||||
return channelData.valueAsFloat;
|
||||
}
|
||||
}
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
public float GetSignal(EGID blockID, out uint signalID, bool input = true)
|
||||
{
|
||||
signalID = GetSignalIDs(blockID, input)[0];
|
||||
return GetSignal(signalID, input);
|
||||
}
|
||||
|
||||
public float GetSignal(uint signalID, bool input = true)
|
||||
{
|
||||
var array = GetSignalStruct(signalID, out uint index, input);
|
||||
return array.count > 0 ? array[index].valueAsFloat : 0f;
|
||||
}
|
||||
|
||||
public uint[] GetSignalIDs(EGID blockID, bool input = true)
|
||||
{
|
||||
ref BlockPortsStruct bps = ref entitiesDB.QueryEntity<BlockPortsStruct>(blockID);
|
||||
uint[] signals;
|
||||
if (input) {
|
||||
signals = new uint[bps.inputCount];
|
||||
for (uint i = 0u; i < bps.inputCount; i++)
|
||||
{
|
||||
signals[i] = bps.firstInputID + i;
|
||||
}
|
||||
} else {
|
||||
signals = new uint[bps.outputCount];
|
||||
for (uint i = 0u; i < bps.outputCount; i++)
|
||||
{
|
||||
signals[i] = bps.firstOutputID + i;
|
||||
}
|
||||
}
|
||||
return signals;
|
||||
}
|
||||
|
||||
public EGID[] GetSignalInputs(EGID blockID)
|
||||
{
|
||||
BlockPortsStruct ports = entitiesDB.QueryEntity<BlockPortsStruct>(blockID);
|
||||
EGID[] inputs = new EGID[ports.inputCount];
|
||||
for (uint i = 0; i < ports.inputCount; i++)
|
||||
{
|
||||
inputs[i] = new EGID(i + ports.firstInputID, NamedExclusiveGroup<InputPortsGroup>.Group);
|
||||
}
|
||||
return inputs;
|
||||
}
|
||||
|
||||
public EGID[] GetSignalOutputs(EGID blockID)
|
||||
{
|
||||
BlockPortsStruct ports = entitiesDB.QueryEntity<BlockPortsStruct>(blockID);
|
||||
EGID[] outputs = new EGID[ports.outputCount];
|
||||
for (uint i = 0; i < ports.outputCount; i++)
|
||||
{
|
||||
outputs[i] = new EGID(i + ports.firstOutputID, NamedExclusiveGroup<OutputPortsGroup>.Group);
|
||||
}
|
||||
return outputs;
|
||||
}
|
||||
|
||||
public ref WireEntityStruct MatchPortToWire(EGID portID, EGID blockID, out bool exists)
|
||||
{
|
||||
ref PortEntityStruct port = ref entitiesDB.QueryEntity<PortEntityStruct>(portID);
|
||||
var wires = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<WiresGroup>.Group);
|
||||
for (uint i = 0; i < wires.count; i++)
|
||||
{
|
||||
if ((wires[i].destinationPortUsage == port.usage && wires[i].destinationBlockEGID == blockID)
|
||||
|| (wires[i].sourcePortUsage == port.usage && wires[i].sourceBlockEGID == blockID))
|
||||
{
|
||||
exists = true;
|
||||
return ref wires[i];
|
||||
}
|
||||
}
|
||||
exists = false;
|
||||
WireEntityStruct[] defRef = new WireEntityStruct[1];
|
||||
return ref defRef[0];
|
||||
}
|
||||
|
||||
public ref ChannelDataStruct GetChannelDataStruct(EGID portID, out bool exists)
|
||||
{
|
||||
ref PortEntityStruct port = ref entitiesDB.QueryEntity<PortEntityStruct>(portID);
|
||||
var channels = entitiesDB.QueryEntities<ChannelDataStruct>(NamedExclusiveGroup<ChannelDataGroup>.Group);
|
||||
if (port.firstChannelIndexCachedInSim < channels.count)
|
||||
{
|
||||
exists = true;
|
||||
return ref channels[port.firstChannelIndexCachedInSim];
|
||||
}
|
||||
exists = false;
|
||||
ChannelDataStruct[] defRef = new ChannelDataStruct[1];
|
||||
return ref defRef[0];
|
||||
}
|
||||
|
||||
public EGID[] GetElectricBlocks()
|
||||
{
|
||||
var res = new FasterList<EGID>();
|
||||
foreach (var (coll, _) in entitiesDB.QueryEntities<BlockPortsStruct>())
|
||||
foreach (ref BlockPortsStruct s in coll)
|
||||
res.Add(s.ID);
|
||||
return res.ToArray();
|
||||
}
|
||||
|
||||
private EntityCollection<ChannelDataStruct> GetSignalStruct(uint signalID, out uint index, bool input = true)
|
||||
{
|
||||
ExclusiveGroup group = input
|
||||
? NamedExclusiveGroup<InputPortsGroup>.Group
|
||||
: NamedExclusiveGroup<OutputPortsGroup>.Group;
|
||||
if (entitiesDB.Exists<PortEntityStruct>(signalID, group))
|
||||
{
|
||||
index = entitiesDB.QueryEntity<PortEntityStruct>(signalID, group).anyChannelIndex;
|
||||
var channelData =
|
||||
entitiesDB.QueryEntities<ChannelDataStruct>(NamedExclusiveGroup<ChannelDataGroup>.Group);
|
||||
return channelData;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
return default; //count: 0
|
||||
}
|
||||
}
|
||||
}
|
123
GamecraftModdingAPI/Blocks/SignalingBlock.cs
Normal file
123
GamecraftModdingAPI/Blocks/SignalingBlock.cs
Normal file
|
@ -0,0 +1,123 @@
|
|||
using System;
|
||||
|
||||
using Gamecraft.Wires;
|
||||
using Svelto.ECS;
|
||||
using Unity.Mathematics;
|
||||
|
||||
using GamecraftModdingAPI;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
/// <summary>
|
||||
/// Common implementation for blocks that support wiring.
|
||||
/// </summary>
|
||||
public class SignalingBlock : Block
|
||||
{
|
||||
/// <summary>
|
||||
/// Places a new signaling block.
|
||||
/// Any valid functional block type with IO ports will work.
|
||||
/// This re-implements Block.PlaceNew(...)
|
||||
/// </summary>
|
||||
public static new SignalingBlock PlaceNew(BlockIDs block, float3 position,
|
||||
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
||||
int uscale = 1, float3 scale = default, Player player = null)
|
||||
{
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
|
||||
position, uscale, scale, player, rotation);
|
||||
return new SignalingBlock(id);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public SignalingBlock(EGID id) : base(id)
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<BlockPortsStruct>(this.Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
public SignalingBlock(uint id) : base(id)
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<BlockPortsStruct>(this.Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
protected ref BlockPortsStruct GetBlockPortsStruct()
|
||||
{
|
||||
return ref BlockEngine.GetBlockInfo<BlockPortsStruct>(Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates the input port identifiers.
|
||||
/// </summary>
|
||||
/// <returns>The input identifiers.</returns>
|
||||
protected EGID[] GetInputIds()
|
||||
{
|
||||
return SignalEngine.GetSignalInputs(Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates the output port identifiers.
|
||||
/// </summary>
|
||||
/// <returns>The output identifiers.</returns>
|
||||
protected EGID[] GetOutputIds()
|
||||
{
|
||||
return SignalEngine.GetSignalOutputs(Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the port struct.
|
||||
/// </summary>
|
||||
/// <returns>The port struct.</returns>
|
||||
/// <param name="portId">Port identifier.</param>
|
||||
protected ref PortEntityStruct GetPortStruct(EGID portId)
|
||||
{
|
||||
return ref BlockEngine.GetBlockInfo<PortEntityStruct>(portId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the connected wire.
|
||||
/// </summary>
|
||||
/// <returns>The connected wire.</returns>
|
||||
/// <param name="portId">Port identifier.</param>
|
||||
/// <param name="connected">Whether the port has a wire connected to it.</param>
|
||||
protected ref WireEntityStruct GetConnectedWire(EGID portId, out bool connected)
|
||||
{
|
||||
return ref SignalEngine.MatchPortToWire(portId, Id, out connected);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [EXPERIMENTAL] Gets the channel data.
|
||||
/// </summary>
|
||||
/// <returns>The channel data.</returns>
|
||||
/// <param name="portId">Port identifier.</param>
|
||||
/// <param name="exists">Whether the channel actually exists.</param>
|
||||
protected ref ChannelDataStruct GetChannelData(EGID portId, out bool exists)
|
||||
{
|
||||
return ref SignalEngine.GetChannelDataStruct(portId, out exists);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The input port count.
|
||||
/// </summary>
|
||||
public uint InputCount
|
||||
{
|
||||
get => GetBlockPortsStruct().inputCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The output port count.
|
||||
/// </summary>
|
||||
public uint OutputCount
|
||||
{
|
||||
get => GetBlockPortsStruct().outputCount;
|
||||
}
|
||||
}
|
||||
}
|
125
GamecraftModdingAPI/Blocks/SpawnPoint.cs
Normal file
125
GamecraftModdingAPI/Blocks/SpawnPoint.cs
Normal file
|
@ -0,0 +1,125 @@
|
|||
using System;
|
||||
|
||||
using RobocraftX.Blocks;
|
||||
using RobocraftX.Common;
|
||||
using Gamecraft.CharacterVulnerability;
|
||||
using Svelto.ECS;
|
||||
using Unity.Mathematics;
|
||||
|
||||
using GamecraftModdingAPI;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
public class SpawnPoint : Block
|
||||
{
|
||||
/// <summary>
|
||||
/// Places a new spawn point.
|
||||
/// Any valid spawn block type is accepted.
|
||||
/// This re-implements Block.PlaceNew(...)
|
||||
/// </summary>
|
||||
public static new SpawnPoint PlaceNew(BlockIDs block, float3 position,
|
||||
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
||||
int uscale = 1, float3 scale = default, Player player = null)
|
||||
{
|
||||
if (!(block == BlockIDs.LargeSpawn || block == BlockIDs.SmallSpawn || block == BlockIDs.MediumSpawn || block == BlockIDs.PlayerSpawn))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {nameof(SpawnPoint)} block");
|
||||
}
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
|
||||
position, uscale, scale, player, rotation);
|
||||
return new SpawnPoint(id);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public SpawnPoint(EGID id) : base(id)
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<SpawnPointStatsEntityStruct>(this.Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
public SpawnPoint(uint id) : base(new EGID(id, CommonExclusiveGroups.BUILD_SPAWNPOINT_BLOCK_GROUP))
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<SpawnPointStatsEntityStruct>(this.Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
// custom spawn point properties
|
||||
|
||||
/// <summary>
|
||||
/// The lives the player spawns in with.
|
||||
/// </summary>
|
||||
public uint Lives
|
||||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo<SpawnPointStatsEntityStruct>(Id).lives;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ref SpawnPointStatsEntityStruct spses = ref BlockEngine.GetBlockInfo<SpawnPointStatsEntityStruct>(Id);
|
||||
spses.lives = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the spawned player can take damage.
|
||||
/// </summary>
|
||||
public bool Damageable
|
||||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo<SpawnPointStatsEntityStruct>(Id).canTakeDamage;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ref SpawnPointStatsEntityStruct spses = ref BlockEngine.GetBlockInfo<SpawnPointStatsEntityStruct>(Id);
|
||||
spses.canTakeDamage = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the game over screen will be displayed
|
||||
/// </summary>
|
||||
public bool GameOverEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo<SpawnPointStatsEntityStruct>(Id).gameOverScreen;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ref SpawnPointStatsEntityStruct spses = ref BlockEngine.GetBlockInfo<SpawnPointStatsEntityStruct>(Id);
|
||||
spses.gameOverScreen = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The team id for players who spawn here.
|
||||
/// </summary>
|
||||
public byte Team
|
||||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo<SpawnPointIdsEntityStruct>(Id).teamId;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ref SpawnPointIdsEntityStruct spses = ref BlockEngine.GetBlockInfo<SpawnPointIdsEntityStruct>(Id);
|
||||
spses.teamId = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
84
GamecraftModdingAPI/Blocks/TextBlock.cs
Normal file
84
GamecraftModdingAPI/Blocks/TextBlock.cs
Normal file
|
@ -0,0 +1,84 @@
|
|||
using System;
|
||||
|
||||
using Gamecraft.Blocks.GUI;
|
||||
using RobocraftX.Common;
|
||||
using Svelto.ECS;
|
||||
using Unity.Mathematics;
|
||||
|
||||
using GamecraftModdingAPI;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
public class TextBlock : Block
|
||||
{
|
||||
|
||||
public static TextBlock PlaceNew(float3 position,
|
||||
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
||||
int uscale = 1, float3 scale = default, Player player = null)
|
||||
{
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
EGID id = PlacementEngine.PlaceBlock(BlockIDs.TextBlock, color, darkness,
|
||||
position, uscale, scale, player, rotation);
|
||||
return new TextBlock(id);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public TextBlock(EGID id) : base(id)
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<TextBlockDataStruct>(this.Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
public TextBlock(uint id) : base(new EGID(id, CommonExclusiveGroups.BUILD_TEXT_BLOCK_GROUP))
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<TextBlockDataStruct>(this.Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
// custom text block properties
|
||||
|
||||
/// <summary>
|
||||
/// The text block's current text.
|
||||
/// </summary>
|
||||
public string Text
|
||||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo<TextBlockDataStruct>(Id).textCurrent;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ref TextBlockDataStruct tbds = ref BlockEngine.GetBlockInfo<TextBlockDataStruct>(Id);
|
||||
tbds.textCurrent.Set(value);
|
||||
tbds.textStored.Set(value);
|
||||
BlockEngine.GetBlockInfo<TextBlockNetworkDataStruct>(Id).newTextBlockStringContent.Set(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The text block's current text block ID (used in ChangeTextBlockCommand).
|
||||
/// </summary>
|
||||
public string TextBlockId
|
||||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo<TextBlockDataStruct>(Id).textBlockID;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
BlockEngine.GetBlockInfo<TextBlockDataStruct>(Id).textBlockID.Set(value);
|
||||
BlockEngine.GetBlockInfo<TextBlockNetworkDataStruct>(Id).newTextBlockID.Set(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
119
GamecraftModdingAPI/Blocks/Timer.cs
Normal file
119
GamecraftModdingAPI/Blocks/Timer.cs
Normal file
|
@ -0,0 +1,119 @@
|
|||
using System;
|
||||
|
||||
using RobocraftX.Blocks;
|
||||
using RobocraftX.Common;
|
||||
using Gamecraft.Blocks.TimerBlock;
|
||||
using Svelto.ECS;
|
||||
using Unity.Mathematics;
|
||||
|
||||
using GamecraftModdingAPI;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Blocks
|
||||
{
|
||||
public class Timer : Block
|
||||
{
|
||||
/// <summary>
|
||||
/// Places a new timer block.
|
||||
/// </summary>
|
||||
public static Timer PlaceNew(float3 position,
|
||||
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
||||
int uscale = 1, float3 scale = default, Player player = null)
|
||||
{
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
EGID id = PlacementEngine.PlaceBlock(BlockIDs.Timer, color, darkness,
|
||||
position, uscale, scale, player, rotation);
|
||||
return new Timer(id);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Timer(EGID id) : base(id)
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<TimerBlockDataStruct>(this.Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
public Timer(uint id) : base(new EGID(id, CommonExclusiveGroups.BUILD_TIMER_BLOCK_GROUP))
|
||||
{
|
||||
if (!BlockEngine.GetBlockInfoExists<TimerBlockDataStruct>(this.Id))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||
}
|
||||
}
|
||||
|
||||
// custom timer properties
|
||||
|
||||
/// <summary>
|
||||
/// The player-specified start time.
|
||||
/// </summary>
|
||||
public float Start
|
||||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo<TimerBlockDataStruct>(Id).startTime;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ref TimerBlockDataStruct tbds = ref BlockEngine.GetBlockInfo<TimerBlockDataStruct>(Id);
|
||||
tbds.startTime = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The player-specified end time.
|
||||
/// </summary>
|
||||
public float End
|
||||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo<TimerBlockDataStruct>(Id).endTime;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ref TimerBlockDataStruct tbds = ref BlockEngine.GetBlockInfo<TimerBlockDataStruct>(Id);
|
||||
tbds.endTime = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether to display time with millisecond precision.
|
||||
/// </summary>
|
||||
public bool DisplayMilliseconds
|
||||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo<TimerBlockDataStruct>(Id).outputFormatHasMS;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ref TimerBlockDataStruct tbds = ref BlockEngine.GetBlockInfo<TimerBlockDataStruct>(Id);
|
||||
tbds.outputFormatHasMS = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current time (as of the last video frame), in milliseconds.
|
||||
/// </summary>
|
||||
public int CurrentTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return BlockEngine.GetBlockInfo<TimerBlockLabelCacheEntityStruct>(Id).timeLastRenderFrameMS;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ref TimerBlockLabelCacheEntityStruct tblces = ref BlockEngine.GetBlockInfo<TimerBlockLabelCacheEntityStruct>(Id);
|
||||
tblces.timeLastRenderFrameMS = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
using System;
|
||||
|
||||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Commands
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// Custom Command builder.
|
|
@ -4,7 +4,7 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TechbloxModdingAPI.Commands
|
||||
namespace GamecraftModdingAPI.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// UNIMPLEMENTED!
|
|
@ -1,7 +1,7 @@
|
|||
using System;
|
||||
namespace TechbloxModdingAPI.Commands
|
||||
namespace GamecraftModdingAPI.Commands
|
||||
{
|
||||
public class CommandException : TechbloxModdingAPIException
|
||||
public class CommandException : GamecraftModdingAPIException
|
||||
{
|
||||
public CommandException() : base() {}
|
||||
|
|
@ -5,9 +5,10 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
|
||||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Commands
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// Keeps track of custom commands
|
38
GamecraftModdingAPI/Commands/CommandPatch.cs
Normal file
38
GamecraftModdingAPI/Commands/CommandPatch.cs
Normal file
|
@ -0,0 +1,38 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Reflection;
|
||||
|
||||
using HarmonyLib;
|
||||
using Svelto.Context;
|
||||
using Svelto.ECS;
|
||||
using RobocraftX;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// Patch of RobocraftX.GUI.CommandLine.CommandLineCompositionRoot.Compose<T>()
|
||||
/// </summary>
|
||||
// TODO: fix
|
||||
[HarmonyPatch]
|
||||
//[HarmonyPatch(typeof(RobocraftX.GUI.CommandLine.CommandLineCompositionRoot))]
|
||||
//[HarmonyPatch("Compose")]
|
||||
//[HarmonyPatch("Compose", new Type[] { typeof(UnityContext<FullGameCompositionRoot>), typeof(EnginesRoot), typeof(World), typeof(Action), typeof(MultiplayerInitParameters), typeof(StateSyncRegistrationHelper)})]
|
||||
static class CommandPatch
|
||||
{
|
||||
public static void Postfix(EnginesRoot enginesRoot)
|
||||
{
|
||||
// When a game is loaded, register the command engines
|
||||
CommandManager.RegisterEngines(enginesRoot);
|
||||
}
|
||||
|
||||
public static MethodBase TargetMethod(Harmony instance)
|
||||
{
|
||||
return typeof(RobocraftX.GUI.CommandLine.CommandLineCompositionRoot).GetMethod("Compose").MakeGenericMethod(typeof(object));
|
||||
//return func.Method;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,17 +4,22 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TechbloxModdingAPI.Commands
|
||||
using uREPL;
|
||||
using RobocraftX.CommandLine.Custom;
|
||||
|
||||
namespace GamecraftModdingAPI.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// Convenient methods for registering commands to Techblox.
|
||||
/// Convenient methods for registering commands to Gamecraft.
|
||||
/// All methods register to the command line and console block by default.
|
||||
/// </summary>
|
||||
public static class CommandRegistrationHelper
|
||||
{
|
||||
public static void Register(string name, Action action, string desc, bool noConsole = false)
|
||||
{
|
||||
CustomCommands.Register(name, action, desc);
|
||||
RuntimeCommands.Register(name, action, desc);
|
||||
if (noConsole) { return; }
|
||||
ConsoleCommands.Register(name, action, desc);
|
||||
}
|
||||
|
||||
public static void Register(string name, Action<object> action, string desc, bool noConsole = false)
|
||||
|
@ -34,42 +39,50 @@ namespace TechbloxModdingAPI.Commands
|
|||
|
||||
public static void Register<Param0>(string name, Action<Param0> action, string desc, bool noConsole = false)
|
||||
{
|
||||
CustomCommands.Register(name, action, desc);
|
||||
RuntimeCommands.Register<Param0>(name, action, desc);
|
||||
if (noConsole) { return; }
|
||||
ConsoleCommands.Register<Param0>(name, action, desc);
|
||||
}
|
||||
|
||||
public static void Register<Param0, Param1>(string name, Action<Param0, Param1> action, string desc, bool noConsole = false)
|
||||
{
|
||||
CustomCommands.Register(name, action, desc);
|
||||
RuntimeCommands.Register<Param0, Param1>(name, action, desc);
|
||||
if (noConsole) { return; }
|
||||
ConsoleCommands.Register<Param0, Param1>(name, action, desc);
|
||||
}
|
||||
|
||||
public static void Register<Param0, Param1, Param2>(string name, Action<Param0, Param1, Param2> action, string desc, bool noConsole = false)
|
||||
{
|
||||
CustomCommands.Register(name, action, desc);
|
||||
RuntimeCommands.Register<Param0, Param1, Param2>(name, action, desc);
|
||||
if (noConsole) { return; }
|
||||
ConsoleCommands.Register<Param0, Param1, Param2>(name, action, desc);
|
||||
}
|
||||
|
||||
public static void Unregister(string name, bool noConsole = false)
|
||||
{
|
||||
CustomCommands.Unregister(name);
|
||||
RuntimeCommands.Unregister(name);
|
||||
if (noConsole) { return; }
|
||||
ConsoleCommands.Unregister(name);
|
||||
}
|
||||
|
||||
public static void Call(string name)
|
||||
{
|
||||
CustomCommands.Call(name);
|
||||
RuntimeCommands.Call(name);
|
||||
}
|
||||
|
||||
public static void Call<Param0>(string name, Param0 param0)
|
||||
{
|
||||
CustomCommands.Call(name, param0);
|
||||
RuntimeCommands.Call<Param0>(name, param0);
|
||||
}
|
||||
|
||||
public static void Call<Param0, Param1>(string name, Param0 param0, Param1 param1)
|
||||
{
|
||||
CustomCommands.Call(name, param0, param1);
|
||||
RuntimeCommands.Call<Param0, Param1>(name, param0, param1);
|
||||
}
|
||||
|
||||
public static void Call<Param0, Param1, Param2>(string name, Param0 param0, Param1 param1, Param2 param2)
|
||||
{
|
||||
CustomCommands.Call(name, param0, param1, param2);
|
||||
RuntimeCommands.Call<Param0, Param1, Param2>(name, param0, param1, param2);
|
||||
}
|
||||
}
|
||||
}
|
42
GamecraftModdingAPI/Commands/ExistingCommands.cs
Normal file
42
GamecraftModdingAPI/Commands/ExistingCommands.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
|
||||
using uREPL;
|
||||
|
||||
namespace GamecraftModdingAPI.Commands
|
||||
{
|
||||
public static class ExistingCommands
|
||||
{
|
||||
public static void Call(string commandName)
|
||||
{
|
||||
RuntimeCommands.Call(commandName);
|
||||
}
|
||||
|
||||
public static void Call<Arg0>(string commandName, Arg0 arg0)
|
||||
{
|
||||
RuntimeCommands.Call<Arg0>(commandName, arg0);
|
||||
}
|
||||
|
||||
public static void Call<Arg0, Arg1>(string commandName, Arg0 arg0, Arg1 arg1)
|
||||
{
|
||||
RuntimeCommands.Call<Arg0, Arg1>(commandName, arg0, arg1);
|
||||
}
|
||||
|
||||
public static void Call<Arg0, Arg1, Arg2>(string commandName, Arg0 arg0, Arg1 arg1, Arg2 arg2)
|
||||
{
|
||||
RuntimeCommands.Call<Arg0, Arg1, Arg2>(commandName, arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
public static bool Exists(string commandName)
|
||||
{
|
||||
return RuntimeCommands.HasRegistered(commandName);
|
||||
}
|
||||
|
||||
public static string[] GetCommandNames()
|
||||
{
|
||||
var keys = RuntimeCommands.table.Keys;
|
||||
string[] res = new string[keys.Count];
|
||||
keys.CopyTo(res, 0);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,10 +6,10 @@ using System.Threading.Tasks;
|
|||
|
||||
using Svelto.ECS;
|
||||
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using TechbloxModdingAPI.Engines;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
using GamecraftModdingAPI.Engines;
|
||||
|
||||
namespace TechbloxModdingAPI.Commands
|
||||
namespace GamecraftModdingAPI.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// Engine interface to handle command operations.
|
|
@ -5,9 +5,10 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
|
||||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Commands
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple implementation of ICustomCommandEngine sufficient for most commands.
|
||||
|
@ -36,13 +37,13 @@ namespace TechbloxModdingAPI.Commands
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
Logging.MetaDebugLog($"Unregistering SimpleCustomCommandEngine {this.Name}");
|
||||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Unregistering SimpleCustomCommandEngine {this.Name}");
|
||||
CommandRegistrationHelper.Unregister(this.Name);
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}");
|
||||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}");
|
||||
CommandRegistrationHelper.Register(this.Name, this.InvokeCatchError, this.Description);
|
||||
}
|
||||
|
|
@ -5,9 +5,10 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
|
||||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Commands
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple implementation of ICustomCommandEngine sufficient for most commands.
|
||||
|
@ -27,13 +28,13 @@ namespace TechbloxModdingAPI.Commands
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
Logging.MetaDebugLog($"Unregistering SimpleCustomCommandEngine {this.Name}");
|
||||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Unregistering SimpleCustomCommandEngine {this.Name}");
|
||||
CommandRegistrationHelper.Unregister(this.Name);
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}");
|
||||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}");
|
||||
CommandRegistrationHelper.Register<A>(this.Name, this.InvokeCatchError, this.Description);
|
||||
}
|
||||
|
|
@ -5,9 +5,10 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
|
||||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Commands
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple implementation of ICustomCommandEngine sufficient for most commands.
|
||||
|
@ -27,13 +28,13 @@ namespace TechbloxModdingAPI.Commands
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
Logging.MetaDebugLog($"Unregistering SimpleCustomCommandEngine {this.Name}");
|
||||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Unregistering SimpleCustomCommandEngine {this.Name}");
|
||||
CommandRegistrationHelper.Unregister(this.Name);
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}");
|
||||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}");
|
||||
CommandRegistrationHelper.Register<A,B>(this.Name, this.InvokeCatchError, this.Description);
|
||||
}
|
||||
|
|
@ -5,9 +5,10 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
|
||||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Commands
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple implementation of ICustomCommandEngine sufficient for most commands.
|
||||
|
@ -27,13 +28,13 @@ namespace TechbloxModdingAPI.Commands
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
Logging.MetaDebugLog($"Unregistering SimpleCustomCommandEngine {this.Name}");
|
||||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Unregistering SimpleCustomCommandEngine {this.Name}");
|
||||
CommandRegistrationHelper.Unregister(this.Name);
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}");
|
||||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}");
|
||||
CommandRegistrationHelper.Register<A,B,C>(this.Name, this.InvokeCatchError, this.Description);
|
||||
}
|
||||
|
|
@ -6,10 +6,10 @@ using System.Threading.Tasks;
|
|||
|
||||
using Svelto.ECS;
|
||||
|
||||
namespace TechbloxModdingAPI.Engines
|
||||
namespace GamecraftModdingAPI.Engines
|
||||
{
|
||||
/// <summary>
|
||||
/// Base engine interface used by all TechbloxModdingAPI engines
|
||||
/// Base engine interface used by all GamecraftModdingAPI engines
|
||||
/// </summary>
|
||||
public interface IApiEngine : IEngine, IQueryingEntitiesEngine, IDisposable
|
||||
{
|
|
@ -6,9 +6,9 @@ using System.Threading.Tasks;
|
|||
|
||||
using Svelto.ECS;
|
||||
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Engines
|
||||
namespace GamecraftModdingAPI.Engines
|
||||
{
|
||||
/// <summary>
|
||||
/// Engine interface to create a ModEventEntityStruct in entitiesDB when Emit() is called.
|
|
@ -7,9 +7,9 @@ using System.Threading.Tasks;
|
|||
using Svelto.ECS;
|
||||
using Svelto.ECS.Internal;
|
||||
|
||||
using TechbloxModdingAPI.Events;
|
||||
using GamecraftModdingAPI.Events;
|
||||
|
||||
namespace TechbloxModdingAPI.Engines
|
||||
namespace GamecraftModdingAPI.Engines
|
||||
{
|
||||
/// <summary>
|
||||
/// Engine interface to handle ModEventEntityStruct events emitted by IEventEmitterEngines.
|
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HarmonyLib;
|
||||
using Svelto.ECS;
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.StateSync;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Patch of RobocraftX.StateSync.DeterministicStepCompositionRoot.ComposeEnginesGroups(...)
|
||||
/// </summary>
|
||||
//[HarmonyPatch(typeof(DeterministicStepCompositionRoot), "DeterministicCompose")]
|
||||
[HarmonyPatch]
|
||||
class GameHostTransitionDeterministicGroupEnginePatch
|
||||
{
|
||||
|
||||
public static readonly GameStateBuildEmitterEngine buildEngine = new GameStateBuildEmitterEngine();
|
||||
|
||||
public static readonly GameStateSimulationEmitterEngine simEngine = new GameStateSimulationEmitterEngine();
|
||||
|
||||
public static void Postfix()
|
||||
{
|
||||
//stateSyncReg.buildModeInitializationEngines.Add(buildEngine);
|
||||
//stateSyncReg.simulationModeInitializationEngines.Add(simEngine);
|
||||
//enginesRoot.AddEngine(buildEngine);
|
||||
//enginesRoot.AddEngine(simEngine);
|
||||
buildEngine.EmitIfBuildMode();
|
||||
simEngine.EmitIfSimMode();
|
||||
}
|
||||
|
||||
[HarmonyTargetMethod]
|
||||
public static MethodBase TargetMethod(Harmony harmonyInstance)
|
||||
{
|
||||
return AccessTools.Method(AccessTools.TypeByName("RobocraftX.StateSync.GameHostTransitionDeterministicGroupEngine"), "EndTransition");
|
||||
//.MakeGenericMethod(typeof(CosmeticEnginesSequenceBuildOrder), typeof(CosmeticEnginesSequenceSimOrder), typeof(DeterministicToCosmeticSyncBuildOrder), typeof(DeterministicToCosmeticSyncSimOrder));
|
||||
}
|
||||
}
|
||||
}
|
105
GamecraftModdingAPI/Events/EmitterBuilder.cs
Normal file
105
GamecraftModdingAPI/Events/EmitterBuilder.cs
Normal file
|
@ -0,0 +1,105 @@
|
|||
using System;
|
||||
|
||||
using Svelto.ECS;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
public class EmitterBuilder
|
||||
{
|
||||
private string name;
|
||||
|
||||
private int? type;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new event emitter builder.
|
||||
/// </summary>
|
||||
public EmitterBuilder()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new event emitter builder.
|
||||
/// This is equivalent to new <code>EmitterBuilder().Name(name)</code>
|
||||
/// </summary>
|
||||
/// <param name="name">The emitter name.</param>
|
||||
public EmitterBuilder(string name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create and return an event emitter builder.
|
||||
/// </summary>
|
||||
/// <returns>The builder.</returns>
|
||||
public static EmitterBuilder Builder()
|
||||
{
|
||||
return new EmitterBuilder();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create and return an event emitter builder.
|
||||
/// This is equivalent to <code>Builder().Name(name)</code>
|
||||
/// </summary>
|
||||
/// <returns>The builder.</returns>
|
||||
/// <param name="name">The emitter name.</param>
|
||||
public static EmitterBuilder Builder(string name)
|
||||
{
|
||||
return new EmitterBuilder(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name the event emitter.
|
||||
/// </summary>
|
||||
/// <returns>The builder.</returns>
|
||||
/// <param name="name">The event emitter name.</param>
|
||||
public EmitterBuilder Name(string name)
|
||||
{
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the type of event to handle.
|
||||
/// </summary>
|
||||
/// <returns>The builder.</returns>
|
||||
/// <param name="eventType">The event type.</param>
|
||||
public EmitterBuilder Handle(EventType eventType)
|
||||
{
|
||||
return Handle((int)eventType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the type of event to handle.
|
||||
/// </summary>
|
||||
/// <returns>The builder.</returns>
|
||||
/// <param name="eventType">The event type.</param>
|
||||
public EmitterBuilder Handle(int eventType)
|
||||
{
|
||||
this.type = eventType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Build the event emitter.
|
||||
/// </summary>
|
||||
/// <returns>The event emitter.</returns>
|
||||
/// <param name="register">Automatically register the event emitter with EventManager.AddEventemitter().</param>
|
||||
public IEventEmitterEngine Build(bool register = true)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
throw new EventParameterMissingException("Event emitter name must be defined before Build() is called");
|
||||
}
|
||||
if (!type.HasValue)
|
||||
{
|
||||
throw new EventParameterMissingException("Event emitter event type must be defined before Build() is called");
|
||||
}
|
||||
SimpleEventEmitterEngine result = new SimpleEventEmitterEngine(type.Value, name);
|
||||
if (register)
|
||||
{
|
||||
EventManager.AddEventEmitter(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
60
GamecraftModdingAPI/Events/EventEngineFactory.cs
Normal file
60
GamecraftModdingAPI/Events/EventEngineFactory.cs
Normal file
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Svelto.ECS;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Convenient factories for mod event engines
|
||||
/// </summary>
|
||||
public static class EventEngineFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Factory method which automatically adds the SimpleEventHandlerEngine to the Manager
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the engine</param>
|
||||
/// <param name="type">The type of event to handle</param>
|
||||
/// <param name="onActivated">The operation to do when the event is created</param>
|
||||
/// <param name="onDestroyed">The operation to do when the event is destroyed (if applicable)</param>
|
||||
/// <returns>The created object</returns>
|
||||
public static SimpleEventHandlerEngine CreateAddSimpleHandler(string name, int type, Action onActivated, Action onDestroyed)
|
||||
{
|
||||
var engine = new SimpleEventHandlerEngine(onActivated, onDestroyed, type, name);
|
||||
EventManager.AddEventHandler(engine);
|
||||
return engine;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Factory method which automatically adds the SimpleEventHandlerEngine to the Manager
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the engine</param>
|
||||
/// <param name="type">The type of event to handle</param>
|
||||
/// <param name="onActivated">The operation to do when the event is created</param>
|
||||
/// <param name="onDestroyed">The operation to do when the event is destroyed (if applicable)</param>
|
||||
/// <returns>The created object</returns>
|
||||
public static SimpleEventHandlerEngine CreateAddSimpleHandler(string name, int type, Action<EntitiesDB> onActivated, Action<EntitiesDB> onDestroyed)
|
||||
{
|
||||
var engine = new SimpleEventHandlerEngine(onActivated, onDestroyed, type, name);
|
||||
EventManager.AddEventHandler(engine);
|
||||
return engine;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Factory method which automatically adds the SimpleEventEmitterEngine to the Manager
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the engine</param>
|
||||
/// <param name="type">The type of event to emit</param>
|
||||
/// <param name="isRemovable">Will removing this engine not break your code?</param>
|
||||
/// <returns>The created object</returns>
|
||||
public static SimpleEventEmitterEngine CreateAddSimpleEmitter(string name, int type, bool isRemovable = true)
|
||||
{
|
||||
var engine = new SimpleEventEmitterEngine(type, name, isRemovable);
|
||||
EventManager.AddEventEmitter(engine);
|
||||
return engine;
|
||||
}
|
||||
}
|
||||
}
|
66
GamecraftModdingAPI/Events/EventExceptions.cs
Normal file
66
GamecraftModdingAPI/Events/EventExceptions.cs
Normal file
|
@ -0,0 +1,66 @@
|
|||
using System;
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
public class EventException : GamecraftModdingAPIException
|
||||
{
|
||||
public EventException()
|
||||
{
|
||||
}
|
||||
|
||||
public EventException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public EventException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EventNotFoundException : EventException
|
||||
{
|
||||
public EventNotFoundException()
|
||||
{
|
||||
}
|
||||
|
||||
public EventNotFoundException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EventAlreadyExistsException : EventException
|
||||
{
|
||||
public EventAlreadyExistsException()
|
||||
{
|
||||
}
|
||||
|
||||
public EventAlreadyExistsException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EventRuntimeException : EventException
|
||||
{
|
||||
public EventRuntimeException()
|
||||
{
|
||||
}
|
||||
|
||||
public EventRuntimeException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public EventRuntimeException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EventParameterMissingException : EventException
|
||||
{
|
||||
public EventParameterMissingException()
|
||||
{
|
||||
}
|
||||
|
||||
public EventParameterMissingException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
128
GamecraftModdingAPI/Events/EventManager.cs
Normal file
128
GamecraftModdingAPI/Events/EventManager.cs
Normal file
|
@ -0,0 +1,128 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Svelto.ECS;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Keeps track of event handlers and emitters.
|
||||
/// This is used to add, remove and get API event handlers and emitters.
|
||||
/// </summary>
|
||||
public static class EventManager
|
||||
{
|
||||
private static Dictionary<string, IEventEmitterEngine> _eventEmitters = new Dictionary<string, IEventEmitterEngine>();
|
||||
|
||||
private static Dictionary<string, IEventHandlerEngine> _eventHandlers = new Dictionary<string, IEventHandlerEngine>();
|
||||
|
||||
private static EnginesRoot _lastEngineRoot;
|
||||
|
||||
// event handler management
|
||||
|
||||
public static void AddEventHandler(IEventHandlerEngine engine)
|
||||
{
|
||||
if (ExistsEventHandler(engine))
|
||||
{
|
||||
throw new EventAlreadyExistsException($"IEventHandlerEngine {engine.Name} already exists");
|
||||
}
|
||||
_eventHandlers[engine.Name] = engine;
|
||||
if (_lastEngineRoot != null)
|
||||
{
|
||||
Logging.MetaDebugLog($"Registering IEventHandlerEngine {engine.Name}");
|
||||
_lastEngineRoot.AddEngine(engine);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ExistsEventHandler(string name)
|
||||
{
|
||||
return _eventHandlers.ContainsKey(name);
|
||||
}
|
||||
|
||||
public static bool ExistsEventHandler(IEventHandlerEngine engine)
|
||||
{
|
||||
return ExistsEventHandler(engine.Name);
|
||||
}
|
||||
|
||||
public static IEventHandlerEngine GetEventHandler(string name)
|
||||
{
|
||||
return _eventHandlers[name];
|
||||
}
|
||||
|
||||
public static string[] GetEventHandlerNames()
|
||||
{
|
||||
return _eventHandlers.Keys.ToArray();
|
||||
}
|
||||
|
||||
public static void RemoveEventHandler(string name)
|
||||
{
|
||||
_eventHandlers.Remove(name);
|
||||
}
|
||||
|
||||
// event emitter management
|
||||
|
||||
public static void AddEventEmitter(IEventEmitterEngine engine)
|
||||
{
|
||||
if (ExistsEventEmitter(engine))
|
||||
{
|
||||
throw new EventAlreadyExistsException($"IEventEmitterEngine {engine.Name} already exists");
|
||||
}
|
||||
_eventEmitters[engine.Name] = engine;
|
||||
if (_lastEngineRoot != null)
|
||||
{
|
||||
Logging.MetaDebugLog($"Registering IEventEmitterEngine {engine.Name}");
|
||||
_lastEngineRoot.AddEngine(engine);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ExistsEventEmitter(string name)
|
||||
{
|
||||
return _eventEmitters.ContainsKey(name);
|
||||
}
|
||||
|
||||
public static bool ExistsEventEmitter(IEventEmitterEngine engine)
|
||||
{
|
||||
return ExistsEventEmitter(engine.Name);
|
||||
}
|
||||
|
||||
public static IEventEmitterEngine GetEventEmitter(string name)
|
||||
{
|
||||
return _eventEmitters[name];
|
||||
}
|
||||
|
||||
public static string[] GetEventEmitterNames()
|
||||
{
|
||||
return _eventEmitters.Keys.ToArray();
|
||||
}
|
||||
|
||||
public static void RemoveEventEmitter(string name)
|
||||
{
|
||||
if (_eventEmitters[name].isRemovable)
|
||||
{
|
||||
_eventEmitters.Remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RegisterEngines(EnginesRoot enginesRoot)
|
||||
{
|
||||
_lastEngineRoot = enginesRoot;
|
||||
// Register handlers before emitters so no events are missed
|
||||
var entityFactory = enginesRoot.GenerateEntityFactory();
|
||||
foreach (var key in _eventHandlers.Keys)
|
||||
{
|
||||
Logging.MetaDebugLog($"Registering IEventHandlerEngine {_eventHandlers[key].Name}");
|
||||
enginesRoot.AddEngine(_eventHandlers[key]);
|
||||
}
|
||||
foreach (var key in _eventEmitters.Keys)
|
||||
{
|
||||
Logging.MetaDebugLog($"Registering IEventEmitterEngine {_eventEmitters[key].Name}");
|
||||
_eventEmitters[key].Factory = entityFactory;
|
||||
enginesRoot.AddEngine(_eventEmitters[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
24
GamecraftModdingAPI/Events/EventType.cs
Normal file
24
GamecraftModdingAPI/Events/EventType.cs
Normal file
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Built-in event types.
|
||||
/// These are configured to fire when the API is initialized.
|
||||
/// </summary>
|
||||
public enum EventType
|
||||
{
|
||||
ApplicationInitialized,
|
||||
Menu,
|
||||
MenuSwitchedTo,
|
||||
Game,
|
||||
GameReloaded,
|
||||
GameSwitchedTo,
|
||||
SimulationSwitchedTo,
|
||||
BuildSwitchedTo
|
||||
}
|
||||
}
|
60
GamecraftModdingAPI/Events/GameActivatedComposePatch.cs
Normal file
60
GamecraftModdingAPI/Events/GameActivatedComposePatch.cs
Normal file
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HarmonyLib;
|
||||
using RobocraftX.CR.MainGame;
|
||||
using Svelto.ECS;
|
||||
using Unity.Entities;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Patch of RobocraftX.FullGameCompositionRoot.ActivateGame()
|
||||
/// </summary>
|
||||
[HarmonyPatch]
|
||||
class GameActivatedComposePatch
|
||||
{
|
||||
public static bool IsGameSwitching = false;
|
||||
|
||||
public static bool IsGameReloading = false;
|
||||
|
||||
public static void Postfix(ref object contextHolder, ref EnginesRoot enginesRoot, World physicsWorld)
|
||||
{
|
||||
// register custom game engines
|
||||
GameEngineManager.RegisterEngines(enginesRoot);
|
||||
// initialize AsyncUtils
|
||||
AsyncUtils.Setup(enginesRoot);
|
||||
// initialize Block
|
||||
Block.Setup(physicsWorld);
|
||||
// A new EnginesRoot is always created when ActivateGame is called
|
||||
// so all event emitters and handlers must be re-registered.
|
||||
EventManager.RegisterEngines(enginesRoot);
|
||||
Logging.Log("Dispatching Game Activated event");
|
||||
EventManager.GetEventEmitter("GamecraftModdingAPIGameActivatedEventEmitter").Emit();
|
||||
if (IsGameSwitching)
|
||||
{
|
||||
IsGameSwitching = false;
|
||||
Logging.Log("Dispatching Game Switched To event");
|
||||
EventManager.GetEventEmitter("GamecraftModdingAPIGameSwitchedToEventEmitter").Emit();
|
||||
}
|
||||
if (IsGameReloading)
|
||||
{
|
||||
IsGameReloading = false;
|
||||
Logging.Log("Dispatching Game Reloaded event");
|
||||
EventManager.GetEventEmitter("GamecraftModdingAPIGameReloadedEventEmitter").Emit();
|
||||
}
|
||||
}
|
||||
|
||||
public static MethodBase TargetMethod()
|
||||
{
|
||||
return typeof(MainGameCompositionRoot).GetMethods().First(m => m.Name == "Compose")
|
||||
.MakeGenericMethod(typeof(object));
|
||||
}
|
||||
}
|
||||
}
|
25
GamecraftModdingAPI/Events/GameReloadedPatch.cs
Normal file
25
GamecraftModdingAPI/Events/GameReloadedPatch.cs
Normal file
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HarmonyLib;
|
||||
using RobocraftX;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Patch of RobocraftX.FullGameCompositionRoot.ReloadGame()
|
||||
/// </summary>
|
||||
[HarmonyPatch(typeof(FullGameCompositionRoot), "ReloadGame")]
|
||||
class GameReloadedPatch
|
||||
{
|
||||
public static void Postfix()
|
||||
{
|
||||
GameActivatedComposePatch.IsGameReloading = true;
|
||||
}
|
||||
}
|
||||
}
|
54
GamecraftModdingAPI/Events/GameStateBuildEmitterEngine.cs
Normal file
54
GamecraftModdingAPI/Events/GameStateBuildEmitterEngine.cs
Normal file
|
@ -0,0 +1,54 @@
|
|||
using System;
|
||||
|
||||
using Unity.Jobs;
|
||||
using RobocraftX.SimulationModeState;
|
||||
using RobocraftX.StateSync;
|
||||
using Svelto.ECS;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Event emitter engine for switching to to build mode.
|
||||
/// </summary>
|
||||
public class GameStateBuildEmitterEngine : IEventEmitterEngine, IUnorderedInitializeOnTimeStoppedModeEntered
|
||||
{
|
||||
public string Name { get; } = "GamecraftModdingAPIGameStateBuildEventEmitter" ;
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
public int type { get; } = (int)EventType.BuildSwitchedTo;
|
||||
|
||||
public bool isRemovable { get; } = false;
|
||||
|
||||
public IEntityFactory Factory { set; private get; }
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
public void Emit()
|
||||
{
|
||||
Logging.Log("Dispatching Build Switched To event");
|
||||
if (Factory == null) { return; }
|
||||
Factory.BuildEntity<ModEventEntityDescriptor>(ApiExclusiveGroups.eventID++, ApiExclusiveGroups.eventsExclusiveGroup)
|
||||
.Init(new ModEventEntityStruct { type = type });
|
||||
}
|
||||
|
||||
public void EmitIfBuildMode()
|
||||
{
|
||||
//Logging.MetaDebugLog($"nextSimulationMode: {entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP).nextSimulationMode}");
|
||||
if (entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP).nextSimulationMode == SimulationMode.TimeStopped)
|
||||
{
|
||||
Emit();
|
||||
}
|
||||
}
|
||||
|
||||
public JobHandle OnInitializeTimeStoppedMode(JobHandle inputDeps)
|
||||
{
|
||||
Emit();
|
||||
return inputDeps;
|
||||
}
|
||||
|
||||
public void Ready() { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
using System;
|
||||
|
||||
using Unity.Jobs;
|
||||
using RobocraftX.SimulationModeState;
|
||||
using RobocraftX.StateSync;
|
||||
using Svelto.ECS;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Event emitter engine for switching to simulation mode.
|
||||
/// </summary>
|
||||
public class GameStateSimulationEmitterEngine : IEventEmitterEngine, IUnorderedInitializeOnTimeRunningModeEntered
|
||||
{
|
||||
public string Name { get; } = "GamecraftModdingAPIGameStateSimulationEventEmitter" ;
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
public int type { get; } = (int)EventType.SimulationSwitchedTo;
|
||||
|
||||
public bool isRemovable { get; } = false;
|
||||
|
||||
public IEntityFactory Factory { set; private get; }
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
public void Emit()
|
||||
{
|
||||
Logging.Log("Dispatching Simulation Switched To event");
|
||||
if (Factory == null) { return; }
|
||||
Factory.BuildEntity<ModEventEntityDescriptor>(ApiExclusiveGroups.eventID++, ApiExclusiveGroups.eventsExclusiveGroup)
|
||||
.Init(new ModEventEntityStruct { type = type });
|
||||
}
|
||||
|
||||
public void EmitIfSimMode()
|
||||
{
|
||||
if (entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP).nextSimulationMode == SimulationMode.TimeRunning)
|
||||
{
|
||||
Emit();
|
||||
}
|
||||
}
|
||||
|
||||
public JobHandle OnInitializeTimeRunningMode(JobHandle inputDeps)
|
||||
{
|
||||
Emit();
|
||||
return inputDeps;
|
||||
}
|
||||
|
||||
public void Ready() { }
|
||||
}
|
||||
}
|
29
GamecraftModdingAPI/Events/GameSwitchedToPatch.cs
Normal file
29
GamecraftModdingAPI/Events/GameSwitchedToPatch.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Reflection;
|
||||
|
||||
using HarmonyLib;
|
||||
using RobocraftX;
|
||||
using RobocraftX.CR.MainGame;
|
||||
using Svelto.ECS;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Patch of RobocraftX.FullGameCompositionRoot.ActivateGame()
|
||||
/// (scheduled for execution during RobocraftX.FullGameCompositionRoot.SwitchToGame())
|
||||
/// </summary>
|
||||
[HarmonyPatch(typeof(FullGameCompositionRoot), "SwitchToGame")]
|
||||
class GameSwitchedToPatch
|
||||
{
|
||||
public static void Prefix()
|
||||
{
|
||||
GameActivatedComposePatch.IsGameSwitching = true;
|
||||
}
|
||||
}
|
||||
}
|
165
GamecraftModdingAPI/Events/HandlerBuilder.cs
Normal file
165
GamecraftModdingAPI/Events/HandlerBuilder.cs
Normal file
|
@ -0,0 +1,165 @@
|
|||
using System;
|
||||
|
||||
using Svelto.ECS;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
public class HandlerBuilder
|
||||
{
|
||||
private string name;
|
||||
|
||||
private int? type;
|
||||
|
||||
private Action<EntitiesDB> activated;
|
||||
|
||||
private Action<EntitiesDB> destroyed;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new event handler builder.
|
||||
/// </summary>
|
||||
public HandlerBuilder()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new event handler builder.
|
||||
/// This is equivalent to new <code>HandlerBuilder().Name(name)</code>
|
||||
/// </summary>
|
||||
/// <param name="name">The handler name.</param>
|
||||
public HandlerBuilder(string name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create and return an event handler builder.
|
||||
/// </summary>
|
||||
/// <returns>The builder.</returns>
|
||||
public static HandlerBuilder Builder()
|
||||
{
|
||||
return new HandlerBuilder();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create and return an event handler builder.
|
||||
/// This is equivalent to <code>Builder().Name(name)</code>
|
||||
/// </summary>
|
||||
/// <returns>The builder.</returns>
|
||||
/// <param name="name">The handler name.</param>
|
||||
public static HandlerBuilder Builder(string name)
|
||||
{
|
||||
return new HandlerBuilder(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name the event handler.
|
||||
/// </summary>
|
||||
/// <returns>The builder.</returns>
|
||||
/// <param name="name">The event handler name.</param>
|
||||
public HandlerBuilder Name(string name)
|
||||
{
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the action to perform on when the activated event occurs.
|
||||
/// </summary>
|
||||
/// <returns>The builder.</returns>
|
||||
/// <param name="action">The activated event action.</param>
|
||||
public HandlerBuilder OnActivation(Action action)
|
||||
{
|
||||
return OnActivation((_) => { action(); });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the action to perform on when the activated event occurs.
|
||||
/// </summary>
|
||||
/// <returns>The builder.</returns>
|
||||
/// <param name="action">The activated event action.</param>
|
||||
public HandlerBuilder OnActivation(Action<EntitiesDB> action)
|
||||
{
|
||||
this.activated = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the action to perform when the destroyed event occurs.
|
||||
/// </summary>
|
||||
/// <returns>The builder.</returns>
|
||||
/// <param name="action">The destroyed event action.</param>
|
||||
public HandlerBuilder OnDestruction(Action action)
|
||||
{
|
||||
return OnDestruction((_) => { action(); });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the action to perform when the destroyed event occurs.
|
||||
/// </summary>
|
||||
/// <returns>The builder.</returns>
|
||||
/// <param name="action">The destroyed event action.</param>
|
||||
public HandlerBuilder OnDestruction(Action<EntitiesDB> action)
|
||||
{
|
||||
this.destroyed = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the type of event to handle.
|
||||
/// </summary>
|
||||
/// <returns>The builder.</returns>
|
||||
/// <param name="eventType">The event type.</param>
|
||||
public HandlerBuilder Handle(EventType eventType)
|
||||
{
|
||||
return Handle((int)eventType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the type of event to handle.
|
||||
/// </summary>
|
||||
/// <returns>The builder.</returns>
|
||||
/// <param name="eventType">The event type.</param>
|
||||
public HandlerBuilder Handle(int eventType)
|
||||
{
|
||||
this.type = eventType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Build the event handler.
|
||||
/// </summary>
|
||||
/// <returns>The event handler.</returns>
|
||||
/// <param name="register">Automatically register the event handler with EventManager.AddEventHandler().</param>
|
||||
public IEventHandlerEngine Build(bool register = true)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
throw new EventParameterMissingException("Event handler name must be defined before Build() is called");
|
||||
}
|
||||
if (activated == null && destroyed == null)
|
||||
{
|
||||
throw new EventParameterMissingException("Event handler destruction or activated event action must be defined before Build() is called");
|
||||
}
|
||||
if (!type.HasValue)
|
||||
{
|
||||
throw new EventParameterMissingException("Event handler event type must be defined before Build() is called");
|
||||
}
|
||||
Action<EntitiesDB> validActivated = activated;
|
||||
if (validActivated == null)
|
||||
{
|
||||
validActivated = (_) => { };
|
||||
}
|
||||
Action<EntitiesDB> validDestroyed = destroyed;
|
||||
if (validDestroyed == null)
|
||||
{
|
||||
validDestroyed = (_) => { };
|
||||
}
|
||||
SimpleEventHandlerEngine result = new SimpleEventHandlerEngine(validActivated, validDestroyed, type.Value, name);
|
||||
if (register)
|
||||
{
|
||||
EventManager.AddEventHandler(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
23
GamecraftModdingAPI/Events/IEventEmitterEngine.cs
Normal file
23
GamecraftModdingAPI/Events/IEventEmitterEngine.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Svelto.ECS;
|
||||
|
||||
using GamecraftModdingAPI.Engines;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Engine interface to create a ModEventEntityStruct in entitiesDB when a specific event occurs.
|
||||
/// </summary>
|
||||
public interface IEventEmitterEngine : IFactoryEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// Emit the event. (Optional)
|
||||
/// </summary>
|
||||
void Emit();
|
||||
}
|
||||
}
|
20
GamecraftModdingAPI/Events/IEventHandlerEngine.cs
Normal file
20
GamecraftModdingAPI/Events/IEventHandlerEngine.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.Internal;
|
||||
|
||||
using GamecraftModdingAPI.Engines;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Engine interface to handle ModEventEntityStruct events emitted by IEventEmitterEngines.
|
||||
/// </summary>
|
||||
public interface IEventHandlerEngine : IReactionaryEngine<ModEventEntityStruct>
|
||||
{
|
||||
}
|
||||
}
|
42
GamecraftModdingAPI/Events/MenuActivatedPatch.cs
Normal file
42
GamecraftModdingAPI/Events/MenuActivatedPatch.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HarmonyLib;
|
||||
using RobocraftX;
|
||||
using Svelto.ECS;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Patch of RobocraftX.FullGameCompositionRoot.ActivateMenu()
|
||||
/// </summary>
|
||||
[HarmonyPatch(typeof(FullGameCompositionRoot), "ActivateMenu")]
|
||||
class MenuActivatedPatch
|
||||
{
|
||||
|
||||
private static bool firstLoad = true;
|
||||
public static void Postfix(ref EnginesRoot ____frontEndEnginesRoot, FullGameCompositionRoot __instance)
|
||||
{
|
||||
// register custom menu engines
|
||||
MenuEngineManager.RegisterEngines(____frontEndEnginesRoot);
|
||||
// A new EnginesRoot is always created when ActivateMenu is called
|
||||
// so all event emitters and handlers must be re-registered.
|
||||
EventManager.RegisterEngines(____frontEndEnginesRoot);
|
||||
if (firstLoad)
|
||||
{
|
||||
firstLoad = false;
|
||||
FullGameFields.Init(__instance);
|
||||
//Application.Application.SetFullGameCompositionRoot(__instance);
|
||||
Logging.Log("Dispatching App Init event");
|
||||
EventManager.GetEventEmitter("GamecraftModdingAPIApplicationInitializedEventEmitter").Emit();
|
||||
}
|
||||
Logging.Log("Dispatching Menu Activated event");
|
||||
EventManager.GetEventEmitter("GamecraftModdingAPIMenuActivatedEventEmitter").Emit();
|
||||
}
|
||||
}
|
||||
}
|
28
GamecraftModdingAPI/Events/MenuSwitchedToPatch.cs
Normal file
28
GamecraftModdingAPI/Events/MenuSwitchedToPatch.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HarmonyLib;
|
||||
using RobocraftX;
|
||||
using Svelto.ECS;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Patch of RobocraftX.FullGameCompositionRoot.SwitchToMenu()
|
||||
/// </summary>
|
||||
[HarmonyPatch(typeof(FullGameCompositionRoot), "SwitchToMenu")]
|
||||
class MenuSwitchedToPatch
|
||||
{
|
||||
public static void Postfix()
|
||||
{
|
||||
// Event emitters and handlers should already be registered by MenuActivated event
|
||||
Logging.Log("Dispatching Menu Switched To event");
|
||||
EventManager.GetEventEmitter("GamecraftModdingAPIMenuSwitchedToEventEmitter").Emit();
|
||||
}
|
||||
}
|
||||
}
|
17
GamecraftModdingAPI/Events/ModEventEntityDescriptor.cs
Normal file
17
GamecraftModdingAPI/Events/ModEventEntityDescriptor.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Svelto.ECS;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// EntityDescriptor for creating ModEventEntityStructs
|
||||
/// </summary>
|
||||
public class ModEventEntityDescriptor : GenericEntityDescriptor<ModEventEntityStruct>
|
||||
{
|
||||
}
|
||||
}
|
23
GamecraftModdingAPI/Events/ModEventEntityStruct.cs
Normal file
23
GamecraftModdingAPI/Events/ModEventEntityStruct.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Svelto.ECS;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// The event entity struct
|
||||
/// </summary>
|
||||
public struct ModEventEntityStruct : IEntityComponent, INeedEGID
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of event that has been emitted
|
||||
/// </summary>
|
||||
public int type;
|
||||
|
||||
public EGID ID { get; set; }
|
||||
}
|
||||
}
|
65
GamecraftModdingAPI/Events/SimpleEventEmitterEngine.cs
Normal file
65
GamecraftModdingAPI/Events/SimpleEventEmitterEngine.cs
Normal file
|
@ -0,0 +1,65 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Svelto.ECS;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple implementation of IEventEmitterEngine sufficient for most uses
|
||||
/// </summary>
|
||||
public class SimpleEventEmitterEngine : IEventEmitterEngine
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int type { get; set; }
|
||||
|
||||
public bool isRemovable { get; }
|
||||
|
||||
public IEntityFactory Factory { private get; set; }
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
public void Ready() { }
|
||||
|
||||
/// <summary>
|
||||
/// Emit the event
|
||||
/// </summary>
|
||||
public void Emit()
|
||||
{
|
||||
Factory.BuildEntity<ModEventEntityDescriptor>(ApiExclusiveGroups.eventID++, ApiExclusiveGroups.eventsExclusiveGroup)
|
||||
.Init(new ModEventEntityStruct { type = type });
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
/// <summary>
|
||||
/// Construct the engine
|
||||
/// </summary>
|
||||
/// <param name="type">The EventType to use for ModEventEntityStruct.type</param>
|
||||
/// <param name="name">The name of this engine</param>
|
||||
/// <param name="isRemovable">Will removing this engine not break your code?</param>
|
||||
public SimpleEventEmitterEngine(EventType type, string name, bool isRemovable = true)
|
||||
{
|
||||
this.type = (int)type;
|
||||
this.Name = name;
|
||||
this.isRemovable = isRemovable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct the engine
|
||||
/// </summary>
|
||||
/// <param name="type">The object to use for ModEventEntityStruct.type</param>
|
||||
/// <param name="name">The name of this engine</param>
|
||||
/// <param name="isRemovable">Will removing this engine not break your code?</param>
|
||||
public SimpleEventEmitterEngine(int type, string name, bool isRemovable = true)
|
||||
{
|
||||
this.type = type;
|
||||
this.Name = name;
|
||||
this.isRemovable = isRemovable;
|
||||
}
|
||||
}
|
||||
}
|
145
GamecraftModdingAPI/Events/SimpleEventHandlerEngine.cs
Normal file
145
GamecraftModdingAPI/Events/SimpleEventHandlerEngine.cs
Normal file
|
@ -0,0 +1,145 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Svelto.ECS;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple implementation of IEventHandlerEngine sufficient for most uses
|
||||
/// </summary>
|
||||
public class SimpleEventHandlerEngine : IEventHandlerEngine
|
||||
{
|
||||
public int type { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
private bool isActivated = false;
|
||||
|
||||
private bool jankActivateFix = false;
|
||||
|
||||
private bool jankDestroyFix = false;
|
||||
|
||||
private readonly Action<EntitiesDB> onActivated;
|
||||
|
||||
private readonly Action<EntitiesDB> onDestroyed;
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
public bool isRemovable => true;
|
||||
|
||||
public void Add(ref ModEventEntityStruct entityView, EGID egid)
|
||||
{
|
||||
if (entityView.type.Equals(this.type))
|
||||
{
|
||||
jankActivateFix = !jankActivateFix;
|
||||
if (jankActivateFix) return;
|
||||
isActivated = true;
|
||||
onActivatedInvokeCatchError(entitiesDB);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manually activate the EventHandler.
|
||||
/// Once activated, the next remove event will not be ignored.
|
||||
/// </summary>
|
||||
/// <param name="handle">Whether to invoke the activated action</param>
|
||||
public void Activate(bool handle = false)
|
||||
{
|
||||
isActivated = true;
|
||||
if (handle && entitiesDB != null)
|
||||
{
|
||||
onActivatedInvokeCatchError(entitiesDB);
|
||||
}
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
isActivated = false;
|
||||
}
|
||||
|
||||
public void Ready() { }
|
||||
|
||||
public void Remove(ref ModEventEntityStruct entityView, EGID egid)
|
||||
{
|
||||
if (entityView.type.Equals(this.type) && isActivated)
|
||||
{
|
||||
jankDestroyFix = !jankDestroyFix;
|
||||
if (jankDestroyFix) return;
|
||||
isActivated = false;
|
||||
onDestroyedInvokeCatchError(entitiesDB);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (isActivated)
|
||||
{
|
||||
isActivated = false;
|
||||
onDestroyedInvokeCatchError(entitiesDB);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct the engine
|
||||
/// </summary>
|
||||
/// <param name="activated">The operation to do when the event is created</param>
|
||||
/// <param name="removed">The operation to do when the event is destroyed (if applicable)</param>
|
||||
/// <param name="type">The type of event to handle</param>
|
||||
/// <param name="name">The name of the engine</param>
|
||||
/// <param name="simple">A useless parameter to use to avoid Python overload resolution errors</param>
|
||||
public SimpleEventHandlerEngine(Action activated, Action removed, int type, string name, bool simple = true)
|
||||
: this((EntitiesDB _) => { activated.Invoke(); }, (EntitiesDB _) => { removed.Invoke(); }, type, name) { }
|
||||
|
||||
/// <summary>
|
||||
/// Construct the engine
|
||||
/// </summary>
|
||||
/// <param name="activated">The operation to do when the event is created</param>
|
||||
/// <param name="removed">The operation to do when the event is destroyed (if applicable)</param>
|
||||
/// <param name="type">The type of event to handler</param>
|
||||
/// <param name="name">The name of the engine</param>
|
||||
public SimpleEventHandlerEngine(Action<EntitiesDB> activated, Action<EntitiesDB> removed, int type, string name)
|
||||
{
|
||||
this.type = type;
|
||||
this.Name = name;
|
||||
this.onActivated = activated;
|
||||
this.onDestroyed = removed;
|
||||
}
|
||||
|
||||
private void onActivatedInvokeCatchError(EntitiesDB _entitiesDB)
|
||||
{
|
||||
try
|
||||
{
|
||||
onActivated.Invoke(_entitiesDB);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
EventRuntimeException wrappedException = new EventRuntimeException($"EventHandler {Name} threw an exception when activated", e);
|
||||
Logging.LogWarning(wrappedException.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void onDestroyedInvokeCatchError(EntitiesDB _entitiesDB)
|
||||
{
|
||||
try
|
||||
{
|
||||
onDestroyed.Invoke(_entitiesDB);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
EventRuntimeException wrappedException = new EventRuntimeException($"EventHandler {Name} threw an exception when destroyed", e);
|
||||
Logging.LogWarning(wrappedException.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public SimpleEventHandlerEngine(Action activated, Action removed, EventType type, string name, bool simple = true)
|
||||
: this((EntitiesDB _) => { activated.Invoke(); }, (EntitiesDB _) => { removed.Invoke(); }, (int)type, name) { }
|
||||
|
||||
public SimpleEventHandlerEngine(Action<EntitiesDB> activated, Action<EntitiesDB> removed, EventType type, string name, bool simple = true)
|
||||
: this(activated, removed, (int)type, name) { }
|
||||
}
|
||||
}
|
868
GamecraftModdingAPI/GamecraftModdingAPI.csproj
Normal file
868
GamecraftModdingAPI/GamecraftModdingAPI.csproj
Normal file
|
@ -0,0 +1,868 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Version>1.4.0-preview</Version>
|
||||
<Authors>Exmods</Authors>
|
||||
<PackageLicenseExpression>GNU General Public Licence 3+</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://git.exmods.org/modtainers/GamecraftModdingAPI</PackageProjectUrl>
|
||||
<NeutralLanguage>en-CA</NeutralLanguage>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Test|AnyCPU' ">
|
||||
<DefineConstants>DEBUG;TEST;TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Lib.Harmony" Version="2.0.0.10" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
<!--Start Dependencies-->
|
||||
<ItemGroup>
|
||||
<Reference Include="Analytics">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Analytics.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Analytics.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp-firstpass">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Assembly-CSharp-firstpass.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Assembly-CSharp-firstpass.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Assembly-CSharp.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Assembly-CSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Authentication">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Authentication.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Authentication.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="BlockEntityFactory">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\BlockEntityFactory.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\BlockEntityFactory.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Blocks.HUDFeedbackBlocks">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Blocks.HUDFeedbackBlocks.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Blocks.HUDFeedbackBlocks.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="CommandLine">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\CommandLine.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\CommandLine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DataLoader">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\DataLoader.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\DataLoader.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DDNA">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\DDNA.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\DDNA.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FMOD">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\FMOD.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\FMOD.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FullGame">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\FullGame.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\FullGame.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.AudioBlocks">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.AudioBlocks.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.AudioBlocks.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.Blocks.ConsoleBlock">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.Blocks.ConsoleBlock.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.Blocks.ConsoleBlock.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.Blocks.DamagingSurfaceBlock">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.Blocks.DamagingSurfaceBlock.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.Blocks.DamagingSurfaceBlock.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.Blocks.GenericPhysicsBlocks">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.Blocks.GenericPhysicsBlocks.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.Blocks.GenericPhysicsBlocks.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.Blocks.LogicBlock">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.Blocks.LogicBlock.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.Blocks.LogicBlock.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GameCraft.Blocks.ProjectileBlock">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\GameCraft.Blocks.ProjectileBlock.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\GameCraft.Blocks.ProjectileBlock.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.Blocks.TimerBlock">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.Blocks.TimerBlock.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.Blocks.TimerBlock.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.CharacterVulnerability">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.CharacterVulnerability.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.CharacterVulnerability.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.CharacterVulnerabilityGui">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.CharacterVulnerabilityGui.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.CharacterVulnerabilityGui.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.Effects">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.Effects.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.Effects.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.GUI.ConsoleBlock">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.GUI.ConsoleBlock.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.GUI.ConsoleBlock.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.GUI.GraphicsScreen">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.GUI.GraphicsScreen.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.GUI.GraphicsScreen.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.GUI.HUDFeedbackBlocks">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.GUI.HUDFeedbackBlocks.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.GUI.HUDFeedbackBlocks.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.GUI.Tweaks">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.GUI.Tweaks.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.GUI.Tweaks.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.GUI.Wires">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.GUI.Wires.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.GUI.Wires.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.GUI.Wires.Mockup">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.GUI.Wires.Mockup.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.GUI.Wires.Mockup.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.GUI.WorldSpaceGuis">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.GUI.WorldSpaceGuis.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.GUI.WorldSpaceGuis.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.Music">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.Music.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.Music.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.PerformanceWarnings">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.PerformanceWarnings.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.PerformanceWarnings.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.Tweaks">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.Tweaks.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.Tweaks.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.Tweaks.Mockup">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.Tweaks.Mockup.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.Tweaks.Mockup.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.VisualEffects">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.VisualEffects.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.VisualEffects.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.Wires">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.Wires.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.Wires.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.Wires.Input">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.Wires.Input.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.Wires.Input.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Gamecraft.Wires.Mockup">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Gamecraft.Wires.Mockup.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Gamecraft.Wires.Mockup.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GameState">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\GameState.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\GameState.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GPUInstancer">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\GPUInstancer.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\GPUInstancer.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Havok.Physics">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Havok.Physics.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Havok.Physics.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Havok.Physics.Hybrid">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Havok.Physics.Hybrid.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Havok.Physics.Hybrid.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="LZ4">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\LZ4.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\LZ4.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MultiplayerNetworking">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\MultiplayerNetworking.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\MultiplayerNetworking.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MultiplayerTest">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\MultiplayerTest.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\MultiplayerTest.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RCX.ScreenshotTaker">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RCX.ScreenshotTaker.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RCX.ScreenshotTaker.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftECS">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftECS.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftECS.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.AccountPreferences">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.AccountPreferences.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.AccountPreferences.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Blocks">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Blocks.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Blocks.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Blocks.Ghost">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Blocks.Ghost.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Blocks.Ghost.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Blocks.Triggers">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Blocks.Triggers.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Blocks.Triggers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Building.BoxSelect">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Building.BoxSelect.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Building.BoxSelect.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Building.Jobs">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Building.Jobs.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Building.Jobs.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Character">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Character.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Character.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.ClusterToWireConversion">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.ClusterToWireConversion.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.ClusterToWireConversion.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Common">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Common.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.ControlsScreen">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.ControlsScreen.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.ControlsScreen.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Crosshair">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Crosshair.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Crosshair.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.FrontEnd">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.FrontEnd.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.FrontEnd.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.GUI.BlockLabel">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.GUI.BlockLabel.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.GUI.BlockLabel.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.GUI.DebugDisplay">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.GUI.DebugDisplay.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.GUI.DebugDisplay.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.GUI">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.GUI.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.GUI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.GUI.RemoveBlock">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.GUI.RemoveBlock.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.GUI.RemoveBlock.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.GUI.ScaleGhost">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.GUI.ScaleGhost.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.GUI.ScaleGhost.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.GUIs.WorkshopPrefabs">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.GUIs.WorkshopPrefabs.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.GUIs.WorkshopPrefabs.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Input">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Input.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Input.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.MachineEditor">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.MachineEditor.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.MachineEditor.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.MainGame">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.MainGame.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.MainGame.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.MainSimulation">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.MainSimulation.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.MainSimulation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.MockCharacter">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.MockCharacter.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.MockCharacter.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Multiplayer">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Multiplayer.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Multiplayer.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Multiplayer.NetworkEntityStream">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Multiplayer.NetworkEntityStream.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Multiplayer.NetworkEntityStream.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.MultiplayerInput">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.MultiplayerInput.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.MultiplayerInput.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Robocraftx.ObjectIdBlocks">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Robocraftx.ObjectIdBlocks.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Robocraftx.ObjectIdBlocks.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Party">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Party.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Party.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.PartyGui">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.PartyGui.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.PartyGui.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Physics">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Physics.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Physics.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.PilotSeat">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.PilotSeat.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.PilotSeat.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Player">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Player.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Player.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Rendering">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Rendering.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Rendering.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Rendering.Mock">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Rendering.Mock.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Rendering.Mock.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.SaveAndLoad">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.SaveAndLoad.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.SaveAndLoad.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.SaveGameDialog">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.SaveGameDialog.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.SaveGameDialog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Serializers">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Serializers.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Serializers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.Services">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.Services.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.Services.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.SignalHandling">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.SignalHandling.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.SignalHandling.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX.StateSync">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX.StateSync.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX.StateSync.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX_SpawnPoints">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX_SpawnPoints.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX_SpawnPoints.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocraftX_TextBlock">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocraftX_TextBlock.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocraftX_TextBlock.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RobocratX.SimulationCompositionRoot">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\RobocratX.SimulationCompositionRoot.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\RobocratX.SimulationCompositionRoot.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="StringFormatter">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\StringFormatter.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\StringFormatter.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Svelto.Common_3">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Svelto.Common_3.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Svelto.Common_3.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Svelto.ECS">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Svelto.ECS.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Svelto.ECS.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Svelto.Services">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Svelto.Services.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Svelto.Services.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Svelto.Tasks">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Svelto.Tasks.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Svelto.Tasks.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Addressables">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Addressables.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Addressables.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Animation.Curves">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Animation.Curves.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Animation.Curves.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Animation.Curves.Hybrid">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Animation.Curves.Hybrid.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Animation.Curves.Hybrid.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Animation.DefaultGraphPipeline">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Animation.DefaultGraphPipeline.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Animation.DefaultGraphPipeline.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Animation.DefaultGraphPipeline.Hybrid">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Animation.DefaultGraphPipeline.Hybrid.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Animation.DefaultGraphPipeline.Hybrid.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Animation">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Animation.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Animation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Animation.Graph">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Animation.Graph.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Animation.Graph.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Animation.Hybrid">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Animation.Hybrid.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Animation.Hybrid.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Build.SlimPlayerRuntime">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Build.SlimPlayerRuntime.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Build.SlimPlayerRuntime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Burst">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Burst.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Burst.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Collections">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Collections.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Collections.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.DataFlowGraph">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.DataFlowGraph.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.DataFlowGraph.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Deformations">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Deformations.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Deformations.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Entities">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Entities.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Entities.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Entities.Hybrid">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Entities.Hybrid.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Entities.Hybrid.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Jobs">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Jobs.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Jobs.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Mathematics">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Mathematics.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Mathematics.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Mathematics.Extensions">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Mathematics.Extensions.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Mathematics.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Mathematics.Extensions.Hybrid">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Mathematics.Extensions.Hybrid.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Mathematics.Extensions.Hybrid.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.MemoryProfiler">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.MemoryProfiler.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.MemoryProfiler.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Physics">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Physics.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Physics.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Physics.Hybrid">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Physics.Hybrid.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Physics.Hybrid.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Platforms.Common">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Platforms.Common.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Platforms.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Postprocessing.Runtime">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Postprocessing.Runtime.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Postprocessing.Runtime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Properties">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Properties.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Properties.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Properties.Reflection">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Properties.Reflection.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Properties.Reflection.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Properties.UI">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Properties.UI.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Properties.UI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.RenderPipeline.Universal.ShaderLibrary">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.RenderPipeline.Universal.ShaderLibrary.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.RenderPipeline.Universal.ShaderLibrary.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.RenderPipelines.Core.Runtime">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.RenderPipelines.Core.Runtime.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.RenderPipelines.Core.Runtime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.RenderPipelines.Core.ShaderLibrary">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.RenderPipelines.Core.ShaderLibrary.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.RenderPipelines.Core.ShaderLibrary.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.RenderPipelines.Universal.Runtime">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.RenderPipelines.Universal.Runtime.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.RenderPipelines.Universal.Runtime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.RenderPipelines.Universal.Shaders">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.RenderPipelines.Universal.Shaders.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.RenderPipelines.Universal.Shaders.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.ResourceManager">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.ResourceManager.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.ResourceManager.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Scenes.Hybrid">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Scenes.Hybrid.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Scenes.Hybrid.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.ScriptableBuildPipeline">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.ScriptableBuildPipeline.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.ScriptableBuildPipeline.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Serialization">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Serialization.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Serialization.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.TextMeshPro">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.TextMeshPro.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.TextMeshPro.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Timeline">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Timeline.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Timeline.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Transforms">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Transforms.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Transforms.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Transforms.Hybrid">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Transforms.Hybrid.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Transforms.Hybrid.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.UI">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.UI.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.UI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="uREPL">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\uREPL.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\uREPL.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="VisualProfiler">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\VisualProfiler.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\VisualProfiler.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Accessibility">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Accessibility.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Accessibility.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Facepunch.Steamworks.Win64">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Facepunch.Steamworks.Win64.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Facepunch.Steamworks.Win64.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="JWT">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\JWT.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\JWT.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="mscorlib">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\mscorlib.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\mscorlib.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="netstandard">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\netstandard.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\netstandard.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Novell.Directory.Ldap">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Novell.Directory.Ldap.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Novell.Directory.Ldap.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Rewired_Core">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Rewired_Core.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Rewired_Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Rewired_Windows">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Rewired_Windows.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Rewired_Windows.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Burst.Unsafe">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\Unity.Burst.Unsafe.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\Unity.Burst.Unsafe.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.AccessibilityModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.AccessibilityModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.AccessibilityModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.AIModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.AIModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.AIModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.AndroidJNIModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.AndroidJNIModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.AndroidJNIModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.AnimationModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.AnimationModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.AnimationModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.ARModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.ARModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.ARModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.AssetBundleModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.AssetBundleModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.AssetBundleModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.AudioModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.AudioModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.AudioModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.ClothModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.ClothModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.ClothModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.ClusterInputModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.ClusterInputModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.ClusterInputModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.ClusterRendererModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.ClusterRendererModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.ClusterRendererModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.CoreModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.CrashReportingModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.CrashReportingModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.CrashReportingModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.DirectorModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.DirectorModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.DirectorModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.DSPGraphModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.DSPGraphModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.DSPGraphModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.GameCenterModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.GameCenterModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.GameCenterModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.GridModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.GridModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.GridModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.HotReloadModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.HotReloadModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.HotReloadModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.ImageConversionModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.ImageConversionModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.ImageConversionModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.IMGUIModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.IMGUIModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.IMGUIModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.InputLegacyModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.InputLegacyModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.InputLegacyModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.InputModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.InputModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.InputModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.JSONSerializeModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.JSONSerializeModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.JSONSerializeModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.LocalizationModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.LocalizationModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.LocalizationModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.ParticleSystemModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.ParticleSystemModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.ParticleSystemModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.PerformanceReportingModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.PerformanceReportingModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.PerformanceReportingModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.Physics2DModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.Physics2DModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.Physics2DModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.PhysicsModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.PhysicsModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.PhysicsModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.ProfilerModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.ProfilerModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.ProfilerModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.ScreenCaptureModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.ScreenCaptureModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.ScreenCaptureModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.SharedInternalsModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.SharedInternalsModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.SharedInternalsModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.SpriteMaskModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.SpriteMaskModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.SpriteMaskModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.SpriteShapeModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.SpriteShapeModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.SpriteShapeModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.StreamingModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.StreamingModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.StreamingModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.SubstanceModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.SubstanceModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.SubstanceModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.SubsystemsModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.SubsystemsModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.SubsystemsModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.TerrainModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.TerrainModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.TerrainModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.TerrainPhysicsModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.TerrainPhysicsModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.TerrainPhysicsModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.TextCoreModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.TextCoreModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.TextCoreModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.TextRenderingModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.TextRenderingModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.TextRenderingModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.TilemapModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.TilemapModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.TilemapModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.TLSModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.TLSModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.TLSModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.UIElementsModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.UIElementsModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.UIElementsModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.UIModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.UIModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.UIModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.UmbraModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.UmbraModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.UmbraModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.UNETModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.UNETModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.UNETModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.UnityAnalyticsModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.UnityAnalyticsModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.UnityAnalyticsModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.UnityConnectModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.UnityConnectModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.UnityConnectModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.UnityTestProtocolModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.UnityTestProtocolModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.UnityTestProtocolModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.UnityWebRequestAssetBundleModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.UnityWebRequestAssetBundleModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.UnityWebRequestAssetBundleModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.UnityWebRequestAudioModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.UnityWebRequestAudioModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.UnityWebRequestAudioModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.UnityWebRequestModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.UnityWebRequestModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.UnityWebRequestModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.UnityWebRequestTextureModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.UnityWebRequestTextureModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.UnityWebRequestTextureModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.UnityWebRequestWWWModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.UnityWebRequestWWWModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.UnityWebRequestWWWModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.VehiclesModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.VehiclesModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.VehiclesModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.VFXModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.VFXModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.VFXModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.VideoModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.VideoModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.VideoModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.VRModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.VRModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.VRModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.WindModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.WindModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.WindModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.XRModule">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\UnityEngine.XRModule.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\UnityEngine.XRModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="IllusionInjector">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\IllusionInjector.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\IllusionInjector.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="IllusionPlugin">
|
||||
<HintPath>..\ref\GamecraftPreview_Data\Managed\IllusionPlugin.dll</HintPath>
|
||||
<HintPath>..\..\ref\GamecraftPreview_Data\Managed\IllusionPlugin.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<!--End Dependencies-->
|
||||
</Project>
|
24
GamecraftModdingAPI/GamecraftModdingAPIException.cs
Normal file
24
GamecraftModdingAPI/GamecraftModdingAPIException.cs
Normal file
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace GamecraftModdingAPI
|
||||
{
|
||||
public class GamecraftModdingAPIException : Exception
|
||||
{
|
||||
public GamecraftModdingAPIException()
|
||||
{
|
||||
}
|
||||
|
||||
public GamecraftModdingAPIException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public GamecraftModdingAPIException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
protected GamecraftModdingAPIException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
146
GamecraftModdingAPI/Input/FakeInput.cs
Normal file
146
GamecraftModdingAPI/Input/FakeInput.cs
Normal file
|
@ -0,0 +1,146 @@
|
|||
using System;
|
||||
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.Common.Input;
|
||||
using Svelto.ECS;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Input
|
||||
{
|
||||
public static class FakeInput
|
||||
{
|
||||
private static readonly FakeInputEngine inputEngine = new FakeInputEngine();
|
||||
|
||||
/// <summary>
|
||||
/// Customize the player input.
|
||||
/// </summary>
|
||||
/// <param name="input">The custom input.</param>
|
||||
/// <param name="playerID">The player. Omit this to use the local player.</param>
|
||||
public static void CustomInput(LocalInputEntityStruct input, uint playerID = uint.MaxValue)
|
||||
{
|
||||
if (playerID == uint.MaxValue)
|
||||
{
|
||||
playerID = inputEngine.GetLocalPlayerID();
|
||||
}
|
||||
inputEngine.SendCustomInput(input, playerID);
|
||||
}
|
||||
|
||||
public static LocalInputEntityStruct GetInput(uint playerID = uint.MaxValue)
|
||||
{
|
||||
if (playerID == uint.MaxValue)
|
||||
{
|
||||
playerID = inputEngine.GetLocalPlayerID();
|
||||
}
|
||||
return inputEngine.GetInput(playerID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fake a GUI input.
|
||||
/// Omit any parameter you do not want to affect.
|
||||
/// Parameters that end with "?" don't do anything... yet.
|
||||
/// </summary>
|
||||
/// <param name="playerID">The player. Omit this to use the local player.</param>
|
||||
/// <param name="hotbar">Select the hotbar slot by number.</param>
|
||||
/// <param name="commandLine">Toggle the command line?</param>
|
||||
/// <param name="escape">Open escape menu?</param>
|
||||
/// <param name="enter">Page return?</param>
|
||||
/// <param name="debug">Toggle debug display?</param>
|
||||
/// <param name="next">Select next?</param>
|
||||
/// <param name="previous">Select previous?</param>
|
||||
/// <param name="tab">Tab?</param>
|
||||
/// <param name="colour">Toggle to hotbar colour mode?</param>
|
||||
/// <param name="hotbarPage">Select the hotbar page by number?</param>
|
||||
/// <param name="quickSave">Quicksave?</param>
|
||||
/// <param name="paste">Paste?</param>
|
||||
public static void GuiInput(uint playerID = uint.MaxValue, int hotbar = -1, bool commandLine = false, bool escape = false, bool enter = false, bool debug = false, bool next = false, bool previous = false, bool tab = false, bool colour = false, int hotbarPage = -1, bool quickSave = false, bool paste = false)
|
||||
{
|
||||
if (playerID == uint.MaxValue)
|
||||
{
|
||||
playerID = inputEngine.GetLocalPlayerID();
|
||||
}
|
||||
ref LocalInputEntityStruct currentInput = ref inputEngine.GetInputRef(playerID);
|
||||
//Utility.Logging.CommandLog($"Current sim frame {currentInput.frame}");
|
||||
// set inputs
|
||||
switch(hotbar)
|
||||
{
|
||||
case 0: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Hotbar_0; break;
|
||||
case 1: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Hotbar_1; break;
|
||||
case 2: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Hotbar_2; break;
|
||||
case 3: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Hotbar_3; break;
|
||||
case 4: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Hotbar_4; break;
|
||||
case 5: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Hotbar_5; break;
|
||||
case 6: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Hotbar_6; break;
|
||||
case 7: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Hotbar_7; break;
|
||||
case 8: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Hotbar_8; break;
|
||||
case 9: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Hotbar_9; break;
|
||||
default: break;
|
||||
}
|
||||
if (commandLine) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.ToggleCommandLine;
|
||||
if (escape) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Escape;
|
||||
if (enter) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Return;
|
||||
if (debug) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.ToggleDebugDisplay;
|
||||
if (next) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.SelectNext;
|
||||
if (previous) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.SelectPrev;
|
||||
if (tab) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Tab;
|
||||
switch (hotbarPage)
|
||||
{
|
||||
case 1: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.HotbarPage1; break;
|
||||
case 2: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.HotbarPage2; break;
|
||||
case 3: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.HotbarPage3; break;
|
||||
case 4: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.HotbarPage4; break;
|
||||
case 5: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.HotbarPage5; break;
|
||||
case 6: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.HotbarPage6; break;
|
||||
case 7: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.HotbarPage7; break;
|
||||
case 8: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.HotbarPage8; break;
|
||||
case 9: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.HotbarPage9; break;
|
||||
case 10: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.HotbarPage10; break;
|
||||
default: break;
|
||||
}
|
||||
if (quickSave) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.QuickSave;
|
||||
if (paste) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.PasteSelection;
|
||||
}
|
||||
|
||||
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 LocalInputEntityStruct currentInput = ref inputEngine.GetInputRef(playerID);
|
||||
//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;
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
GameEngineManager.AddGameEngine(inputEngine);
|
||||
MenuEngineManager.AddMenuEngine(inputEngine);
|
||||
}
|
||||
}
|
||||
}
|
65
GamecraftModdingAPI/Input/FakeInputEngine.cs
Normal file
65
GamecraftModdingAPI/Input/FakeInputEngine.cs
Normal file
|
@ -0,0 +1,65 @@
|
|||
using System;
|
||||
|
||||
using RobocraftX.Common.Input;
|
||||
using RobocraftX.Players;
|
||||
using Svelto.ECS;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
using GamecraftModdingAPI.Engines;
|
||||
|
||||
namespace GamecraftModdingAPI.Input
|
||||
{
|
||||
public class FakeInputEngine : IApiEngine
|
||||
{
|
||||
public string Name { get; } = "GamecraftModdingAPIFakeInputEngine";
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
public bool isRemovable => false;
|
||||
|
||||
public bool IsReady = false;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
IsReady = false;
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
IsReady = true;
|
||||
}
|
||||
|
||||
public bool SendCustomInput(LocalInputEntityStruct input, uint playerID, bool remote = false)
|
||||
{
|
||||
EGID egid = new EGID(playerID, remote ? InputExclusiveGroups.RemotePlayers : InputExclusiveGroups.LocalPlayers);
|
||||
if (entitiesDB.Exists<LocalInputEntityStruct>(egid))
|
||||
{
|
||||
ref LocalInputEntityStruct ies = ref entitiesDB.QueryEntity<LocalInputEntityStruct>(egid);
|
||||
ies = input;
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
public LocalInputEntityStruct GetInput(uint playerID, bool remote = false)
|
||||
{
|
||||
EGID egid = new EGID(playerID, remote ? InputExclusiveGroups.RemotePlayers : InputExclusiveGroups.LocalPlayers);
|
||||
if (entitiesDB.Exists<LocalInputEntityStruct>(egid))
|
||||
{
|
||||
return entitiesDB.QueryEntity<LocalInputEntityStruct>(egid);
|
||||
}
|
||||
else return default(LocalInputEntityStruct);
|
||||
}
|
||||
|
||||
public ref LocalInputEntityStruct GetInputRef(uint playerID, bool remote = false)
|
||||
{
|
||||
EGID egid = new EGID(playerID, remote ? InputExclusiveGroups.RemotePlayers : InputExclusiveGroups.LocalPlayers);
|
||||
return ref entitiesDB.QueryEntity<LocalInputEntityStruct>(egid);
|
||||
}
|
||||
|
||||
public uint GetLocalPlayerID()
|
||||
{
|
||||
return LocalPlayerIDUtility.GetLocalPlayerID(entitiesDB);
|
||||
}
|
||||
}
|
||||
}
|
47
GamecraftModdingAPI/Inventory/Hotbar.cs
Normal file
47
GamecraftModdingAPI/Inventory/Hotbar.cs
Normal file
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
|
||||
using RobocraftX.Common.Input;
|
||||
using RobocraftX.Multiplayer.Input;
|
||||
|
||||
using GamecraftModdingAPI.Blocks;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace GamecraftModdingAPI.Inventory
|
||||
{
|
||||
public static class Hotbar
|
||||
{
|
||||
private static readonly HotbarEngine hotbarEngine = new HotbarEngine();
|
||||
|
||||
/// <summary>
|
||||
/// Switch the block in the player's hand
|
||||
/// </summary>
|
||||
/// <param name="block">The block to switch to.</param>
|
||||
/// <param name="playerID">The player. Omit this to use the local player.</param>
|
||||
public static void EquipBlock(BlockIDs block, uint playerID = uint.MaxValue)
|
||||
{
|
||||
if (playerID == uint.MaxValue)
|
||||
{
|
||||
playerID = hotbarEngine.GetLocalPlayerID();
|
||||
}
|
||||
hotbarEngine.SelectBlock((int) block, playerID);
|
||||
// cubeSelectedByPick = true will crash the game
|
||||
// (this would be equivalent to mouse middle click pick block action)
|
||||
// reason: the game expects a Dictionary entry for the tweaked stats
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the block in the player's hand
|
||||
/// </summary>
|
||||
/// <returns>The equipped block.</returns>
|
||||
public static BlockIDs GetEquippedBlock()
|
||||
{
|
||||
return HotbarSlotSelectionHandlerEnginePatch.EquippedPartID;
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
GameEngineManager.AddGameEngine(hotbarEngine);
|
||||
}
|
||||
}
|
||||
}
|
58
GamecraftModdingAPI/Inventory/HotbarEngine.cs
Normal file
58
GamecraftModdingAPI/Inventory/HotbarEngine.cs
Normal file
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
|
||||
using RobocraftX.Character;
|
||||
using RobocraftX.GUI.Hotbar;
|
||||
using RobocraftX.Players;
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.Common.Input;
|
||||
using RobocraftX.Common.Players;
|
||||
using Svelto.ECS;
|
||||
|
||||
using GamecraftModdingAPI.Blocks;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
using GamecraftModdingAPI.Engines;
|
||||
|
||||
namespace GamecraftModdingAPI.Inventory
|
||||
{
|
||||
public class HotbarEngine : IApiEngine
|
||||
{
|
||||
public string Name { get; } = "GamecraftModdingAPIHotbarGameEngine";
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
public bool isRemovable => false;
|
||||
|
||||
public bool IsInGame = false;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
IsInGame = false;
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
IsInGame = true;
|
||||
}
|
||||
|
||||
public bool SelectBlock(int block, uint playerID, bool cubeSelectedByPick = false)
|
||||
{
|
||||
var inputs = entitiesDB.QueryEntities<LocalInputEntityStruct>(InputExclusiveGroups.LocalPlayers);
|
||||
if (inputs.count == 0) return false;
|
||||
for (int i = 0; i < inputs.count; i++)
|
||||
{
|
||||
if (inputs[i].ID.entityID == playerID) {
|
||||
inputs[i].cubeSelectedByPick = cubeSelectedByPick;
|
||||
inputs[i].selectedCube = block;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// TODO: expose the rest of the input functionality
|
||||
return false;
|
||||
}
|
||||
|
||||
public uint GetLocalPlayerID()
|
||||
{
|
||||
return LocalPlayerIDUtility.GetLocalPlayerID(entitiesDB);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using RobocraftX.GUI;
|
||||
using RobocraftX.GUI.Hotbar;
|
||||
using Svelto.ECS;
|
||||
|
||||
using HarmonyLib;
|
||||
using GamecraftModdingAPI.Blocks;
|
||||
|
||||
namespace GamecraftModdingAPI.Inventory
|
||||
{
|
||||
[HarmonyPatch]
|
||||
public class HotbarSlotSelectionHandlerEnginePatch
|
||||
{
|
||||
private static int selectedBlockInt = 0;
|
||||
|
||||
public static BlockIDs EquippedPartID { get => (BlockIDs)selectedBlockInt; }
|
||||
|
||||
private static MethodInfo PatchedMethod { get; } = AccessTools.Method(AccessTools.TypeByName("RobocraftX.GUI.Hotbar.HotbarSlotSelectionHandlerEngine"), "ActivateSlotForCube", parameters: new Type[] { typeof(uint), typeof(int), typeof(ExclusiveGroupStruct) });
|
||||
|
||||
public static void Prefix(uint playerID, int selectedDBPartID, ExclusiveGroupStruct groupID)
|
||||
{
|
||||
selectedBlockInt = selectedDBPartID;
|
||||
}
|
||||
|
||||
public static MethodBase TargetMethod(Harmony harmonyInstance)
|
||||
{
|
||||
return PatchedMethod;
|
||||
}
|
||||
}
|
||||
}
|
103
GamecraftModdingAPI/Main.cs
Normal file
103
GamecraftModdingAPI/Main.cs
Normal file
|
@ -0,0 +1,103 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Reflection;
|
||||
|
||||
using HarmonyLib;
|
||||
|
||||
using GamecraftModdingAPI.Utility;
|
||||
using GamecraftModdingAPI.Events;
|
||||
using GamecraftModdingAPI.Players;
|
||||
using GamecraftModdingAPI.Tasks;
|
||||
using uREPL;
|
||||
|
||||
namespace GamecraftModdingAPI
|
||||
{
|
||||
/// <summary>
|
||||
/// The main class of the GamecraftModdingAPI.
|
||||
/// Use this to initialize the API before calling it.
|
||||
/// </summary>
|
||||
public static class Main
|
||||
{
|
||||
private static Harmony harmony;
|
||||
|
||||
public static bool IsInitialized {
|
||||
get { return harmony != null; }
|
||||
}
|
||||
|
||||
private static int referenceCount = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the GamecraftModdingAPI.
|
||||
/// Call this as soon as possible after Gamecraft starts up.
|
||||
/// Ideally, this should be called from your main Plugin class's OnApplicationStart() method.
|
||||
/// </summary>
|
||||
public static void Init()
|
||||
{
|
||||
referenceCount++;
|
||||
if (referenceCount > 1) { return; }
|
||||
if (IsInitialized)
|
||||
{
|
||||
Logging.LogWarning("GamecraftModdingAPI.Main.Init() called but API is already initialized!");
|
||||
return;
|
||||
}
|
||||
Logging.MetaDebugLog($"Patching Gamecraft");
|
||||
var currentAssembly = Assembly.GetExecutingAssembly();
|
||||
harmony = new Harmony(currentAssembly.GetName().Name);
|
||||
harmony.PatchAll(currentAssembly);
|
||||
// init utility
|
||||
Logging.MetaDebugLog($"Initializing Utility");
|
||||
Utility.GameState.Init();
|
||||
Utility.VersionTracking.Init();
|
||||
// create default event emitters
|
||||
Logging.MetaDebugLog($"Initializing Events");
|
||||
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.ApplicationInitialized, "GamecraftModdingAPIApplicationInitializedEventEmitter", false));
|
||||
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.Menu, "GamecraftModdingAPIMenuActivatedEventEmitter", false));
|
||||
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.MenuSwitchedTo, "GamecraftModdingAPIMenuSwitchedToEventEmitter", false));
|
||||
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.Game, "GamecraftModdingAPIGameActivatedEventEmitter", false));
|
||||
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.GameReloaded, "GamecraftModdingAPIGameReloadedEventEmitter", false));
|
||||
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.GameSwitchedTo, "GamecraftModdingAPIGameSwitchedToEventEmitter", false));
|
||||
EventManager.AddEventEmitter(GameHostTransitionDeterministicGroupEnginePatch.buildEngine);
|
||||
EventManager.AddEventEmitter(GameHostTransitionDeterministicGroupEnginePatch.simEngine);
|
||||
// init block implementors
|
||||
Logging.MetaDebugLog($"Initializing Blocks");
|
||||
// init inventory
|
||||
Inventory.Hotbar.Init();
|
||||
// init input
|
||||
Input.FakeInput.Init();
|
||||
// init object-oriented classes
|
||||
Player.Init();
|
||||
Block.Init();
|
||||
GameClient.Init();
|
||||
AsyncUtils.Init();
|
||||
GamecraftModdingAPI.App.Client.Init();
|
||||
GamecraftModdingAPI.App.Game.Init();
|
||||
Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} initialized");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shuts down & cleans up the GamecraftModdingAPI.
|
||||
/// Call this as late as possible before Gamecraft quits.
|
||||
/// Ideally, this should be called from your main Plugin class's OnApplicationQuit() method.
|
||||
/// </summary>
|
||||
public static void Shutdown()
|
||||
{
|
||||
if (referenceCount > 0) { referenceCount--; }
|
||||
if (referenceCount == 0)
|
||||
{
|
||||
if (!IsInitialized)
|
||||
{
|
||||
Logging.LogWarning("GamecraftModdingAPI.Main.Shutdown() called but API is not initialized!");
|
||||
return;
|
||||
}
|
||||
Scheduler.Dispose();
|
||||
var currentAssembly = Assembly.GetExecutingAssembly();
|
||||
harmony.UnpatchAll(currentAssembly.GetName().Name);
|
||||
harmony = null;
|
||||
Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} shutdown");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,16 +8,16 @@ using Svelto.ECS;
|
|||
using Svelto.ECS.Serialization;
|
||||
|
||||
using HarmonyLib;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Persistence
|
||||
namespace GamecraftModdingAPI.Persistence
|
||||
{
|
||||
//[HarmonyPatch] - TODO
|
||||
[HarmonyPatch]
|
||||
class DeserializeFromDiskEntitiesEnginePatch
|
||||
{
|
||||
internal static EntitiesDB entitiesDB = null;
|
||||
|
||||
private static readonly byte[] frameStart = Encoding.UTF8.GetBytes("\0\0\0TechbloxModdingAPI\0\0\0");
|
||||
private static readonly byte[] frameStart = Encoding.UTF8.GetBytes("\0\0\0GamecraftModdingAPI\0\0\0");
|
||||
|
||||
public static void Prefix(ref ISerializationData ____serializationData, ref FasterList<byte> ____bytesStream, ref IEntitySerialization ____entitySerializer, bool ____spawnBlocksOnly)
|
||||
{
|
||||
|
@ -26,7 +26,7 @@ namespace TechbloxModdingAPI.Persistence
|
|||
SerializerManager.RegisterSerializers(SaveAndLoadCompositionRootPatch.currentEnginesRoot);
|
||||
uint originalPos = ____serializationData.dataPos;
|
||||
Logging.MetaDebugLog($"dataPos: {originalPos}");
|
||||
BinaryBufferReader bbr = new BinaryBufferReader(____bytesStream.ToArrayFast(out int count), ____serializationData.dataPos);
|
||||
BinaryBufferReader bbr = new BinaryBufferReader(____bytesStream.ToArrayFast(out uint count), ____serializationData.dataPos);
|
||||
byte[] frameBuffer = new byte[frameStart.Length];
|
||||
Logging.MetaDebugLog($"serial data count: {____serializationData.data.count} capacity: {____serializationData.data.capacity}");
|
||||
int i = 0;
|
|
@ -3,12 +3,12 @@
|
|||
using Svelto.ECS;
|
||||
using Svelto.ECS.Serialization;
|
||||
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Persistence
|
||||
namespace GamecraftModdingAPI.Persistence
|
||||
{
|
||||
/// <summary>
|
||||
/// Entity serializer and deserializer interface for storing and retrieving data in a Techblox save file (GameSave.GC).
|
||||
/// Entity serializer and deserializer interface for storing and retrieving data in a Gamecraft save file (GameSave.GC).
|
||||
/// </summary>
|
||||
public interface IEntitySerializer : IDeserializationFactory, IQueryingEntitiesEngine
|
||||
{
|
|
@ -5,7 +5,7 @@ using Svelto.ECS;
|
|||
|
||||
using HarmonyLib;
|
||||
|
||||
namespace TechbloxModdingAPI.Persistence
|
||||
namespace GamecraftModdingAPI.Persistence
|
||||
{
|
||||
[HarmonyPatch(typeof(SaveAndLoadCompositionRoot), "Compose")]
|
||||
class SaveAndLoadCompositionRootPatch
|
|
@ -7,15 +7,16 @@ using RobocraftX.SaveAndLoad;
|
|||
using Svelto.DataStructures;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.Serialization;
|
||||
using HarmonyLib;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Persistence
|
||||
using GamecraftModdingAPI.Utility;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace GamecraftModdingAPI.Persistence
|
||||
{
|
||||
//[HarmonyPatch] - TODO
|
||||
[HarmonyPatch]
|
||||
class SaveGameEnginePatch
|
||||
{
|
||||
private static readonly byte[] frameStart = Encoding.UTF8.GetBytes("\0\0\0TechbloxModdingAPI\0\0\0");
|
||||
private static readonly byte[] frameStart = Encoding.UTF8.GetBytes("\0\0\0GamecraftModdingAPI\0\0\0");
|
||||
|
||||
public static void Postfix(ref ISerializationData serializationData, EntitiesDB entitiesDB, IEntitySerialization entitySerializer)
|
||||
{
|
||||
|
@ -25,24 +26,24 @@ namespace TechbloxModdingAPI.Persistence
|
|||
Logging.MetaDebugLog("Skipping component serialization: no serializers registered!");
|
||||
return;
|
||||
}
|
||||
serializationData.data.IncreaseCapacityBy((uint)frameStart.Length);
|
||||
BinaryBufferWriter bbw = new BinaryBufferWriter(serializationData.data.ToArrayFast(out int buffLen), serializationData.dataPos);
|
||||
serializationData.data.ExpandBy((uint)frameStart.Length);
|
||||
BinaryBufferWriter bbw = new BinaryBufferWriter(serializationData.data.ToArrayFast(out uint buffLen), serializationData.dataPos);
|
||||
uint originalPos = serializationData.dataPos;
|
||||
Logging.MetaDebugLog($"dataPos: {originalPos}");
|
||||
// Add frame start so it's easier to find TechbloxModdingAPI-serialized components
|
||||
// Add frame start so it's easier to find GamecraftModdingAPI-serialized components
|
||||
for (int i = 0; i < frameStart.Length; i++)
|
||||
{
|
||||
bbw.Write(frameStart[i]);
|
||||
}
|
||||
Logging.MetaDebugLog($"dataPos (after frame start): {bbw.Position}");
|
||||
serializationData.data.IncreaseCapacityBy(4u);
|
||||
serializationData.data.ExpandBy(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.IncreaseCapacityBy(4u + (uint)serializerKeys[c].Length);
|
||||
serializationData.data.ExpandBy(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 +52,7 @@ namespace TechbloxModdingAPI.Persistence
|
|||
bbw.Write(nameBytes[i]);
|
||||
}
|
||||
Logging.MetaDebugLog($"dataPos (now): {bbw.Position}");
|
||||
serializationData.data.IncreaseCapacityBy(4u);
|
||||
serializationData.data.ExpandBy(4u);
|
||||
serializationData.dataPos = bbw.Position + 4u;
|
||||
Logging.MetaDebugLog($"dataPos (now): {bbw.Position}");
|
||||
Logging.MetaDebugLog($"dataPos (appears to be): {serializationData.dataPos}");
|
||||
|
@ -73,8 +74,8 @@ namespace TechbloxModdingAPI.Persistence
|
|||
}
|
||||
|
||||
public static MethodBase TargetMethod()
|
||||
{
|
||||
return AccessTools.TypeByName("RobocraftX.SaveAndLoad.SaveGameEngine").GetMethod("SerializeGameToBuffer");
|
||||
{
|
||||
return typeof(SaveGameEngine).GetMethod("SerializeGameToBuffer");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,14 +4,15 @@ using System.Linq;
|
|||
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.Serialization;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Persistence
|
||||
using GamecraftModdingAPI.Utility;
|
||||
|
||||
namespace GamecraftModdingAPI.Persistence
|
||||
{
|
||||
/// <summary>
|
||||
/// Keeps track of serializers.
|
||||
/// This is used to add and retrieve serializers.
|
||||
/// Added IEntitySerializations are used in serializing and deserializing Techblox save files (GameSave.GC).
|
||||
/// Added IEntitySerializations are used in serializing and deserializing Gamecraft save files (GameSave.GC).
|
||||
/// </summary>
|
||||
public static class SerializerManager
|
||||
{
|
||||
|
@ -58,7 +59,7 @@ namespace TechbloxModdingAPI.Persistence
|
|||
return _serializers.Count;
|
||||
}
|
||||
|
||||
internal static void RegisterSerializers(EnginesRoot enginesRoot)
|
||||
public static void RegisterSerializers(EnginesRoot enginesRoot)
|
||||
{
|
||||
_lastEnginesRoot = enginesRoot;
|
||||
IEntitySerialization ies = enginesRoot.GenerateEntitySerializer();
|
|
@ -5,7 +5,7 @@ using Svelto.ECS.Serialization;
|
|||
|
||||
using RobocraftX.Common;
|
||||
|
||||
namespace TechbloxModdingAPI.Persistence
|
||||
namespace GamecraftModdingAPI.Persistence
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple entity serializer sufficient for simple entity components.
|
||||
|
@ -23,16 +23,16 @@ namespace TechbloxModdingAPI.Persistence
|
|||
|
||||
public EntitiesDB entitiesDB { set; protected get; }
|
||||
|
||||
public EntityInitializer BuildDeserializedEntity(EGID egid, ISerializationData serializationData, ISerializableEntityDescriptor entityDescriptor, int serializationType, IEntitySerialization entitySerialization, IEntityFactory factory, bool enginesRootIsDeserializationOnly)
|
||||
public EntityComponentInitializer BuildDeserializedEntity(EGID egid, ISerializationData serializationData, ISerializableEntityDescriptor entityDescriptor, int serializationType, IEntitySerialization entitySerialization, IEntityFactory factory, bool enginesRootIsDeserializationOnly)
|
||||
{
|
||||
EntityInitializer esi = factory.BuildEntity<Descriptor>(egid);
|
||||
EntityComponentInitializer esi = factory.BuildEntity<Descriptor>(egid);
|
||||
entitySerialization.DeserializeEntityComponents(serializationData, entityDescriptor, ref esi, serializationType);
|
||||
return esi;
|
||||
}
|
||||
|
||||
public bool Deserialize(ref ISerializationData serializationData, IEntitySerialization entitySerializer)
|
||||
{
|
||||
BinaryBufferReader bbr = new BinaryBufferReader(serializationData.data.ToArrayFast(out int count), serializationData.dataPos);
|
||||
BinaryBufferReader bbr = new BinaryBufferReader(serializationData.data.ToArrayFast(out uint count), serializationData.dataPos);
|
||||
uint entityCount = bbr.ReadUint();
|
||||
serializationData.dataPos = bbr.Position;
|
||||
for (uint i = 0; i < entityCount; i++)
|
||||
|
@ -46,8 +46,8 @@ namespace TechbloxModdingAPI.Persistence
|
|||
|
||||
public bool Serialize(ref ISerializationData serializationData, EntitiesDB entitiesDB, IEntitySerialization entitySerializer)
|
||||
{
|
||||
serializationData.data.IncreaseCapacityBy(4u);
|
||||
BinaryBufferWriter bbw = new BinaryBufferWriter(serializationData.data.ToArrayFast(out int count), serializationData.dataPos);
|
||||
serializationData.data.ExpandBy(4u);
|
||||
BinaryBufferWriter bbw = new BinaryBufferWriter(serializationData.data.ToArrayFast(out uint count), serializationData.dataPos);
|
||||
EGID[] toSerialize = getEntitiesToSerialize(entitiesDB);
|
||||
bbw.Write((uint)toSerialize.Length);
|
||||
serializationData.dataPos = bbw.Position;
|
421
GamecraftModdingAPI/Player.cs
Normal file
421
GamecraftModdingAPI/Player.cs
Normal file
|
@ -0,0 +1,421 @@
|
|||
using System;
|
||||
|
||||
using Unity.Mathematics;
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.Common.Players;
|
||||
using Svelto.ECS;
|
||||
|
||||
using GamecraftModdingAPI.Players;
|
||||
using GamecraftModdingAPI.Blocks;
|
||||
|
||||
namespace GamecraftModdingAPI
|
||||
{
|
||||
/// <summary>
|
||||
/// An in-game player character. Any Leo you see is a player.
|
||||
/// </summary>
|
||||
public class Player : IEquatable<Player>, IEquatable<EGID>
|
||||
{
|
||||
// static functionality
|
||||
private static PlayerEngine playerEngine = new PlayerEngine();
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the specified player exists.
|
||||
/// </summary>
|
||||
/// <returns>Whether the player exists.</returns>
|
||||
/// <param name="player">Player type.</param>
|
||||
public static bool Exists(PlayerType player)
|
||||
{
|
||||
switch (player)
|
||||
{
|
||||
case PlayerType.Remote:
|
||||
return playerEngine.GetRemotePlayer() != uint.MaxValue;
|
||||
case PlayerType.Local:
|
||||
return playerEngine.GetLocalPlayer() != uint.MaxValue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the specified player exists.
|
||||
/// </summary>
|
||||
/// <returns>Whether the player exists.</returns>
|
||||
/// <param name="player">The player's unique identifier.</param>
|
||||
public static bool Exists(uint player)
|
||||
{
|
||||
return playerEngine.ExistsById(player);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The amount of Players in the current game.
|
||||
/// </summary>
|
||||
/// <returns>The count.</returns>
|
||||
public static uint Count()
|
||||
{
|
||||
return (uint) playerEngine.GetAllPlayerCount();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:GamecraftModdingAPI.Player"/> class.
|
||||
/// </summary>
|
||||
/// <param name="id">The player's unique identifier.</param>
|
||||
public Player(uint id)
|
||||
{
|
||||
this.Id = id;
|
||||
if (!Exists(id))
|
||||
{
|
||||
throw new PlayerNotFoundException($"No player with id {id} exists");
|
||||
}
|
||||
this.Type = playerEngine.GetLocalPlayer() == id ? PlayerType.Local : PlayerType.Remote;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:GamecraftModdingAPI.Player"/> class.
|
||||
/// </summary>
|
||||
/// <param name="player">The player type. Chooses the first available player matching the criteria.</param>
|
||||
public Player(PlayerType player)
|
||||
{
|
||||
switch (player)
|
||||
{
|
||||
case PlayerType.Local:
|
||||
this.Id = playerEngine.GetLocalPlayer();
|
||||
break;
|
||||
case PlayerType.Remote:
|
||||
this.Id = playerEngine.GetRemotePlayer();
|
||||
break;
|
||||
}
|
||||
if (this.Id == uint.MaxValue)
|
||||
{
|
||||
throw new PlayerNotFoundException($"No player of {player} type exists");
|
||||
}
|
||||
this.Type = player;
|
||||
}
|
||||
|
||||
// object fields & properties
|
||||
|
||||
/// <summary>
|
||||
/// The player's type.
|
||||
/// The player type is always relative to the current client, not the game host.
|
||||
/// </summary>
|
||||
/// <value>The enumerated player type.</value>
|
||||
public PlayerType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The player's unique identifier.
|
||||
/// </summary>
|
||||
/// <value>The identifier.</value>
|
||||
public uint Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The player's current position.
|
||||
/// </summary>
|
||||
/// <value>The position.</value>
|
||||
public float3 Position
|
||||
{
|
||||
get
|
||||
{
|
||||
return playerEngine.GetLocation(Id);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
playerEngine.SetLocation(Id, value, false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The player's current rotation.
|
||||
/// </summary>
|
||||
/// <value>The rotation.</value>
|
||||
public float3 Rotation
|
||||
{
|
||||
get
|
||||
{
|
||||
return playerEngine.GetRotation(Id);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
playerEngine.SetRotation(Id, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The player's current velocity.
|
||||
/// </summary>
|
||||
/// <value>The velocity.</value>
|
||||
public float3 Velocity
|
||||
{
|
||||
get
|
||||
{
|
||||
return playerEngine.GetLinearVelocity(Id);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
playerEngine.SetLinearVelocity(Id, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The player's current angular velocity.
|
||||
/// </summary>
|
||||
/// <value>The angular velocity.</value>
|
||||
public float3 AngularVelocity
|
||||
{
|
||||
get
|
||||
{
|
||||
return playerEngine.GetAngularVelocity(Id);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
playerEngine.SetAngularVelocity(Id, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The player's mass.
|
||||
/// </summary>
|
||||
/// <value>The mass.</value>
|
||||
public float Mass
|
||||
{
|
||||
get
|
||||
{
|
||||
return 1f / playerEngine.GetMass(Id).InverseMass;
|
||||
}
|
||||
|
||||
// FIXME: Setting mass doesn't do anything
|
||||
/*set
|
||||
{
|
||||
playerEngine.SetInverseMass(Id, 1f / value);
|
||||
}*/
|
||||
}
|
||||
|
||||
private float _ping = -1f;
|
||||
|
||||
/// <summary>
|
||||
/// The player's latest network ping time.
|
||||
/// </summary>
|
||||
/// <value>The ping (s).</value>
|
||||
public float Ping
|
||||
{
|
||||
get
|
||||
{
|
||||
float? temp = playerEngine.GetLastPingTime(Id, Type);
|
||||
if (temp.HasValue)
|
||||
{
|
||||
_ping = temp.Value;
|
||||
}
|
||||
return _ping;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The player's initial health when entering Simulation (aka Time Running) mode.
|
||||
/// </summary>
|
||||
/// <value>The initial health.</value>
|
||||
public float InitialHealth
|
||||
{
|
||||
get => playerEngine.GetInitialHealth(Id);
|
||||
|
||||
set
|
||||
{
|
||||
playerEngine.SetInitialHealth(Id, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The player's current health in Simulation (aka Time Running) mode.
|
||||
/// </summary>
|
||||
/// <value>The current health.</value>
|
||||
public float CurrentHealth
|
||||
{
|
||||
get => playerEngine.GetCurrentHealth(Id);
|
||||
|
||||
set
|
||||
{
|
||||
playerEngine.DamagePlayer(Id, CurrentHealth - value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether this <see cref="T:GamecraftModdingAPI.Player"/> is damageable.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if damageable; otherwise, <c>false</c>.</value>
|
||||
public bool Damageable
|
||||
{
|
||||
get => playerEngine.GetDamageable(Id);
|
||||
|
||||
set
|
||||
{
|
||||
playerEngine.SetDamageable(Id, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The player's lives when initially entering Simulation (aka Time Running) mode.
|
||||
/// </summary>
|
||||
/// <value>The initial lives.</value>
|
||||
public uint InitialLives
|
||||
{
|
||||
get => playerEngine.GetInitialLives(Id);
|
||||
|
||||
set => playerEngine.SetInitialLives(Id, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The player's current lives in Simulation (aka Time Running) mode.
|
||||
/// </summary>
|
||||
/// <value>The current lives.</value>
|
||||
public uint CurrentLives
|
||||
{
|
||||
get => playerEngine.GetCurrentLives(Id);
|
||||
|
||||
set => playerEngine.SetCurrentLives(Id, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the Game Over screen is displayed for the player.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if game over; otherwise, <c>false</c>.</value>
|
||||
public bool GameOver
|
||||
{
|
||||
get => playerEngine.GetGameOverScreen(Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the player is dead.
|
||||
/// If <c>true</c>, hopefully it was quick.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if dead; otherwise, <c>false</c>.</value>
|
||||
public bool Dead
|
||||
{
|
||||
get => playerEngine.IsDead(Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The player's selected block ID in their hand.
|
||||
/// </summary>
|
||||
/// <value>The selected block.</value>
|
||||
public BlockIDs SelectedBlock
|
||||
{
|
||||
get
|
||||
{
|
||||
return (BlockIDs)playerEngine.GetSelectedBlock(Id);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The player's selected block color in their hand.
|
||||
/// </summary>
|
||||
/// <value>The selected block's color.</value>
|
||||
public BlockColor SelectedColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return new BlockColor(playerEngine.GetSelectedColor(Id));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The player's selected block colour in their hand.
|
||||
/// </summary>
|
||||
/// <value>The selected block's colour.</value>
|
||||
public BlockColor SelectedColour
|
||||
{
|
||||
get
|
||||
{
|
||||
return new BlockColor(playerEngine.GetSelectedColor(Id));
|
||||
}
|
||||
}
|
||||
|
||||
// object methods
|
||||
|
||||
/// <summary>
|
||||
/// Teleport the player to the specified coordinates.
|
||||
/// </summary>
|
||||
/// <param name="x">The x coordinate.</param>
|
||||
/// <param name="y">The y coordinate.</param>
|
||||
/// <param name="z">The z coordinate.</param>
|
||||
/// <param name="relative">If set to <c>true</c> teleport relative to the player's current position.</param>
|
||||
/// <param name="exitSeat">If set to <c>true</c> exit any seat the player is in.</param>
|
||||
public void Teleport(float x, float y, float z, bool relative = true, bool exitSeat = true)
|
||||
{
|
||||
float3 location = new float3(x, y, z);
|
||||
if (relative)
|
||||
{
|
||||
location += playerEngine.GetLocation(Id);
|
||||
}
|
||||
playerEngine.SetLocation(Id, location, exitSeat: exitSeat);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the block the player is currently looking at in build mode.
|
||||
/// </summary>
|
||||
/// <param name="maxDistance">The maximum distance from the player (default is the player's building reach)</param>
|
||||
/// <returns>The block or null if not found</returns>
|
||||
public Block GetBlockLookedAt(float maxDistance = -1f)
|
||||
{
|
||||
var egid = playerEngine.GetThingLookedAt(Id, maxDistance);
|
||||
return egid.HasValue && egid.Value.groupID != CommonExclusiveGroups.SIMULATION_BODIES_GROUP
|
||||
? new Block(egid.Value)
|
||||
: null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the rigid body the player is currently looking at during simulation.
|
||||
/// </summary>
|
||||
/// <param name="maxDistance">The maximum distance from the player (default is the player's building reach)</param>
|
||||
/// <returns>The block or null if not found</returns>
|
||||
public SimBody GetSimBodyLookedAt(float maxDistance = -1f)
|
||||
{
|
||||
var egid = playerEngine.GetThingLookedAt(Id, maxDistance);
|
||||
return egid.HasValue && egid.Value.groupID == CommonExclusiveGroups.SIMULATION_BODIES_GROUP
|
||||
? new SimBody(egid.Value)
|
||||
: null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the blocks that are in the player's current selection.
|
||||
/// </summary>
|
||||
/// <returns>An array of blocks or an empty array</returns>
|
||||
public Block[] GetSelectedBlocks()
|
||||
{
|
||||
return playerEngine.GetSelectedBlocks(Id);
|
||||
}
|
||||
|
||||
public bool Equals(Player other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return Id == other.Id;
|
||||
}
|
||||
|
||||
public bool Equals(EGID other)
|
||||
{
|
||||
return Id == other.entityID && other.groupID == (Type == PlayerType.Local
|
||||
? PlayersExclusiveGroups.LocalPlayers
|
||||
: PlayersExclusiveGroups.RemotePlayers);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((Player) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (int) Id;
|
||||
}
|
||||
|
||||
// internal methods
|
||||
|
||||
internal static void Init()
|
||||
{
|
||||
Utility.GameEngineManager.AddGameEngine(playerEngine);
|
||||
}
|
||||
}
|
||||
}
|
485
GamecraftModdingAPI/Players/PlayerEngine.cs
Normal file
485
GamecraftModdingAPI/Players/PlayerEngine.cs
Normal file
|
@ -0,0 +1,485 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using RobocraftX.Character;
|
||||
using RobocraftX.Character.Movement;
|
||||
using RobocraftX.Common.Players;
|
||||
using RobocraftX.Common.Input;
|
||||
using RobocraftX.CR.MachineEditing.BoxSelect;
|
||||
using RobocraftX.Physics;
|
||||
using RobocraftX.Blocks.Ghost;
|
||||
using RobocraftX.Character.Camera;
|
||||
using RobocraftX.Character.Factories;
|
||||
using Gamecraft.CharacterVulnerability;
|
||||
using Gamecraft.CharacterVulnerability.Entities;
|
||||
using Svelto.ECS;
|
||||
using Unity.Mathematics;
|
||||
using Unity.Physics;
|
||||
using UnityEngine;
|
||||
|
||||
using GamecraftModdingAPI.Engines;
|
||||
|
||||
namespace GamecraftModdingAPI.Players
|
||||
{
|
||||
internal class PlayerEngine : IApiEngine, IFactoryEngine
|
||||
{
|
||||
public string Name { get; } = "GamecraftModdingAPIPlayerGameEngine";
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
public bool isRemovable => false;
|
||||
|
||||
public IEntityFactory Factory { set; private get; }
|
||||
|
||||
private bool isReady = false;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
isReady = false;
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
isReady = true;
|
||||
}
|
||||
|
||||
public uint GetLocalPlayer()
|
||||
{
|
||||
if (!isReady) return uint.MaxValue;
|
||||
var localPlayers = entitiesDB.QueryEntities<PlayerIDStruct>(PlayersExclusiveGroups.LocalPlayers);
|
||||
if (localPlayers.count > 0)
|
||||
{
|
||||
return localPlayers[0].ID.entityID;
|
||||
}
|
||||
return uint.MaxValue;
|
||||
}
|
||||
|
||||
public uint GetRemotePlayer()
|
||||
{
|
||||
if (!isReady) return uint.MaxValue;
|
||||
var localPlayers = entitiesDB.QueryEntities<PlayerIDStruct>(PlayersExclusiveGroups.RemotePlayers);
|
||||
if (localPlayers.count > 0)
|
||||
{
|
||||
return localPlayers[0].ID.entityID;
|
||||
}
|
||||
return uint.MaxValue;
|
||||
}
|
||||
|
||||
public long GetAllPlayerCount()
|
||||
{
|
||||
if (entitiesDB == null) return 0;
|
||||
long count = 0;
|
||||
foreach (ExclusiveGroupStruct eg in PlayersExclusiveGroups.AllPlayers)
|
||||
{
|
||||
count += entitiesDB.Count<PlayerIDStruct>(eg);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public long GetLocalPlayerCount()
|
||||
{
|
||||
if (entitiesDB == null) return 0;
|
||||
return entitiesDB.Count<PlayerIDStruct>(PlayersExclusiveGroups.LocalPlayers);
|
||||
}
|
||||
|
||||
public long GetRemotePlayerCount()
|
||||
{
|
||||
if (entitiesDB == null) return 0;
|
||||
return entitiesDB.Count<PlayerIDStruct>(PlayersExclusiveGroups.RemotePlayers);
|
||||
}
|
||||
|
||||
public bool ExistsById(uint playerId)
|
||||
{
|
||||
if (entitiesDB == null) return false;
|
||||
return entitiesDB.Exists<PlayerIDStruct>(playerId, PlayersExclusiveGroups.LocalPlayers)
|
||||
|| entitiesDB.Exists<PlayerIDStruct>(playerId, PlayersExclusiveGroups.RemotePlayers);
|
||||
}
|
||||
|
||||
public float3 GetLocation(uint playerId)
|
||||
{
|
||||
if (entitiesDB == null) return float3.zero;
|
||||
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
return rbes.position;
|
||||
}
|
||||
return float3.zero;
|
||||
}
|
||||
|
||||
public bool SetLocation(uint playerId, float3 location, bool exitSeat = true)
|
||||
{
|
||||
if (entitiesDB == null) return false;
|
||||
var characterGroups = CharacterExclusiveGroups.AllCharacters;
|
||||
for (int i = 0; i < characterGroups.count; i++)
|
||||
{
|
||||
EGID egid = new EGID(playerId, characterGroups[i]);
|
||||
if (entitiesDB.Exists<RigidBodyEntityStruct>(egid))
|
||||
{
|
||||
ref RigidBodyEntityStruct rbes = ref entitiesDB.QueryEntity<RigidBodyEntityStruct>(egid);
|
||||
if (characterGroups[i] == CharacterExclusiveGroups.InPilotSeatGroup && exitSeat)
|
||||
{
|
||||
entitiesDB.QueryEntity<CharacterPilotSeatEntityStruct>(egid).instantExit = true;
|
||||
entitiesDB.PublishEntityChange<CharacterPilotSeatEntityStruct>(egid);
|
||||
}
|
||||
rbes.position = location;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public float3 GetRotation(uint playerId)
|
||||
{
|
||||
if (entitiesDB == null) return float3.zero;
|
||||
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
return ((Quaternion) rbes.rotation).eulerAngles;
|
||||
}
|
||||
return default(float3);
|
||||
}
|
||||
|
||||
public bool SetRotation(uint playerId, float3 value)
|
||||
{
|
||||
if (entitiesDB == null) return false;
|
||||
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
Quaternion q = rbes.rotation;
|
||||
q.eulerAngles = value;
|
||||
rbes.rotation = q;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public float3 GetLinearVelocity(uint playerId)
|
||||
{
|
||||
if (entitiesDB == null) return float3.zero;
|
||||
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
return rbes.velocity;
|
||||
}
|
||||
return float3.zero;
|
||||
}
|
||||
|
||||
public bool SetLinearVelocity(uint playerId, float3 value)
|
||||
{
|
||||
if (entitiesDB == null) return false;
|
||||
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
rbes.velocity = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public float3 GetAngularVelocity(uint playerId)
|
||||
{
|
||||
if (entitiesDB == null) return float3.zero;
|
||||
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
return rbes.angularVelocity;
|
||||
}
|
||||
return float3.zero;
|
||||
}
|
||||
|
||||
public bool SetAngularVelocity(uint playerId, float3 value)
|
||||
{
|
||||
if (entitiesDB == null) return false;
|
||||
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
rbes.angularVelocity = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public PhysicsMass GetMass(uint playerId)
|
||||
{
|
||||
if (entitiesDB == null) return default(PhysicsMass);
|
||||
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
return rbes.physicsMass;
|
||||
}
|
||||
return default(PhysicsMass);
|
||||
}
|
||||
|
||||
public bool SetInverseMass(uint playerId, float inverseMass)
|
||||
{
|
||||
if (entitiesDB == null) return false;
|
||||
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
rbes.physicsMass.InverseInertia = inverseMass;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public float? GetLastPingTime(uint playerId, PlayerType type)
|
||||
{
|
||||
if (entitiesDB == null) return null;
|
||||
EGID egid = new EGID(playerId, PlayerGroupFromEnum(type));
|
||||
if (entitiesDB.Exists<PlayerNetworkStatsEntityStruct>(egid))
|
||||
{
|
||||
return entitiesDB.QueryEntity<PlayerNetworkStatsEntityStruct>(egid).lastPingTimeSinceLevelLoad;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public float GetInitialHealth(uint playerId)
|
||||
{
|
||||
if (entitiesDB == null) return 0;
|
||||
ref var c = ref GetCharacterStruct<CharacterHealthEntityStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
return c.initialHealth;
|
||||
}
|
||||
return -1f;
|
||||
}
|
||||
|
||||
public bool SetInitialHealth(uint playerId, float val)
|
||||
{
|
||||
if (entitiesDB == null) return false;
|
||||
ref var c = ref GetCharacterStruct<CharacterHealthEntityStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
c.initialHealth = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public float GetCurrentHealth(uint playerId)
|
||||
{
|
||||
if (entitiesDB == null) return 0;
|
||||
ref var c = ref GetCharacterStruct<CharacterHealthEntityStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
return c.currentHealth;
|
||||
}
|
||||
return -1f;
|
||||
}
|
||||
|
||||
public bool SetCurrentHealth(uint playerId, float val)
|
||||
{
|
||||
if (entitiesDB == null) return false;
|
||||
ref var c = ref GetCharacterStruct<CharacterHealthEntityStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
c.currentHealth = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool DamagePlayer(uint playerId, float amount)
|
||||
{
|
||||
if (entitiesDB == null) return false;
|
||||
Factory.BuildEntity<DamageEntityDescriptor>(
|
||||
new EGID(CharacterVulnerabilityExclusiveGroups.NextDamageEntityId, CharacterVulnerabilityExclusiveGroups.CharacterDamageExclusiveGroup)
|
||||
).Init(new DamageEntityStruct
|
||||
{
|
||||
damage = amount,
|
||||
targetPlayerEntityId = playerId,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool GetDamageable(uint playerId)
|
||||
{
|
||||
if (entitiesDB == null) return false;
|
||||
ref var c = ref GetCharacterStruct<CharacterHealthEntityStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
return c.canTakeDamageStat;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool SetDamageable(uint playerId, bool val)
|
||||
{
|
||||
if (entitiesDB == null) return false;
|
||||
ref var ches = ref GetCharacterStruct<CharacterHealthEntityStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
ches.canTakeDamage = val;
|
||||
ches.canTakeDamage = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public uint GetInitialLives(uint playerId)
|
||||
{
|
||||
if (entitiesDB == null) return 0;
|
||||
ref var c = ref GetCharacterStruct<CharacterLivesEntityComponent>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
return c.initialLives;
|
||||
}
|
||||
return uint.MaxValue;
|
||||
}
|
||||
|
||||
public bool SetInitialLives(uint playerId, uint val)
|
||||
{
|
||||
if (entitiesDB == null) return false;
|
||||
ref var c = ref GetCharacterStruct<CharacterLivesEntityComponent>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
c.initialLives = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public uint GetCurrentLives(uint playerId)
|
||||
{
|
||||
if (entitiesDB == null) return 0;
|
||||
ref var c = ref GetCharacterStruct<CharacterLivesEntityComponent>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
return c.currentLives;
|
||||
}
|
||||
return uint.MaxValue;
|
||||
}
|
||||
|
||||
public bool SetCurrentLives(uint playerId, uint val)
|
||||
{
|
||||
if (entitiesDB == null) return false;
|
||||
ref var c = ref GetCharacterStruct<CharacterLivesEntityComponent>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
c.currentLives = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool GetGameOverScreen(uint playerId)
|
||||
{
|
||||
if (entitiesDB == null) return false;
|
||||
ref var c = ref GetCharacterStruct<CharacterLivesEntityComponent>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
return c.gameOverScreen;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsDead(uint playerId)
|
||||
{
|
||||
if (entitiesDB == null) return true;
|
||||
return entitiesDB.Exists<RigidBodyEntityStruct>(playerId, CharacterExclusiveGroups.DeadCharacters);
|
||||
}
|
||||
|
||||
public int GetSelectedBlock(uint playerId)
|
||||
{
|
||||
if (entitiesDB == null) return 0;
|
||||
ref var c = ref GetCharacterStruct<EquippedPartStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
return c.SelectedDBPartID;
|
||||
}
|
||||
return ushort.MaxValue;
|
||||
}
|
||||
|
||||
public byte GetSelectedColor(uint playerId)
|
||||
{
|
||||
if (entitiesDB == null) return 0;
|
||||
ref var c = ref GetCharacterStruct<EquippedColourStruct>(playerId, out bool exists);
|
||||
if (exists)
|
||||
{
|
||||
return c.indexInPalette;
|
||||
}
|
||||
return 255;
|
||||
}
|
||||
|
||||
// reusable methods
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private ExclusiveGroup PlayerGroupFromEnum(PlayerType type)
|
||||
{
|
||||
return type == PlayerType.Local ? PlayersExclusiveGroups.LocalPlayers : PlayersExclusiveGroups.RemotePlayers;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref T GetCharacterStruct<T>(uint playerId, out bool exists) where T : unmanaged, IEntityComponent
|
||||
{
|
||||
var characterGroups = CharacterExclusiveGroups.AllCharacters;
|
||||
for (int i = 0; i < characterGroups.count; i++)
|
||||
{
|
||||
EGID egid = new EGID(playerId, characterGroups[i]);
|
||||
if (entitiesDB.Exists<T>(egid))
|
||||
{
|
||||
exists = true;
|
||||
return ref entitiesDB.QueryEntity<T>(egid);
|
||||
}
|
||||
}
|
||||
|
||||
exists = false;
|
||||
T[] arr = new T[1];
|
||||
return ref arr[0]; //Return default value
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool GetPlayerStruct<T>(uint playerId, out T s) where T : unmanaged, IEntityComponent
|
||||
{
|
||||
var playerGroups = PlayersExclusiveGroups.AllPlayers;
|
||||
for (int i = 0; i < playerGroups.count; i++)
|
||||
{
|
||||
EGID egid = new EGID(playerId, playerGroups[i]);
|
||||
if (entitiesDB.Exists<T>(egid))
|
||||
{
|
||||
s = entitiesDB.QueryEntity<T>(egid);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
s = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
public EGID? GetThingLookedAt(uint playerId, float maxDistance = -1f)
|
||||
{
|
||||
if (!entitiesDB.TryQueryMappedEntities<CharacterCameraRayCastEntityStruct>(
|
||||
CameraExclusiveGroups.CameraGroup, out var mapper))
|
||||
return null;
|
||||
mapper.TryGetEntity(playerId, out CharacterCameraRayCastEntityStruct rayCast);
|
||||
float distance = maxDistance < 0
|
||||
? GhostBlockUtils.GetBuildInteractionDistance(entitiesDB, rayCast,
|
||||
GhostBlockUtils.GhostCastMethod.GhostCastProportionalToBlockSize)
|
||||
: maxDistance;
|
||||
if (rayCast.hit && rayCast.distance <= distance)
|
||||
return rayCast.hitEgid;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public unsafe Block[] GetSelectedBlocks(uint playerid)
|
||||
{
|
||||
if (!entitiesDB.Exists<BoxSelectStateEntityStruct>(playerid,
|
||||
BoxSelectExclusiveGroups.BoxSelectVolumeExclusiveGroup))
|
||||
return new Block[0];
|
||||
var state = entitiesDB.QueryEntity<BoxSelectStateEntityStruct>(playerid,
|
||||
BoxSelectExclusiveGroups.BoxSelectVolumeExclusiveGroup);
|
||||
var blocks = entitiesDB.QueryEntity<SelectedBlocksStruct>(playerid,
|
||||
BoxSelectExclusiveGroups.BoxSelectVolumeExclusiveGroup);
|
||||
if (!state.active) return new Block[0];
|
||||
var pointer = (EGID*) blocks.selectedBlocks.ToPointer();
|
||||
var ret = new Block[blocks.count];
|
||||
for (int j = 0; j < blocks.count; j++)
|
||||
{
|
||||
var egid = pointer[j];
|
||||
ret[j] = new Block(egid);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
using System;
|
||||
namespace TechbloxModdingAPI.Players
|
||||
namespace GamecraftModdingAPI.Players
|
||||
{
|
||||
public class PlayerException : TechbloxModdingAPIException
|
||||
public class PlayerException : GamecraftModdingAPIException
|
||||
{
|
||||
public PlayerException()
|
||||
{
|
42
GamecraftModdingAPI/Players/PlayerTests.cs
Normal file
42
GamecraftModdingAPI/Players/PlayerTests.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
|
||||
using Unity.Mathematics;
|
||||
|
||||
using GamecraftModdingAPI;
|
||||
using GamecraftModdingAPI.Tests;
|
||||
|
||||
namespace GamecraftModdingAPI.Players
|
||||
{
|
||||
#if TEST
|
||||
/// <summary>
|
||||
/// Player test cases. Not accessible in release versions.
|
||||
/// </summary>
|
||||
[APITestClass]
|
||||
public static class PlayerTests
|
||||
{
|
||||
[APITestCase(TestType.EditMode)]
|
||||
public static void ExistsTest()
|
||||
{
|
||||
if (!Assert.Equal(Player.Exists(PlayerType.Local), true, "Local player does not exist.", "Local player detected.")) return;
|
||||
Assert.Equal(Player.Count(), 1u, "Player.Count() is not one, possibly because it failed silently.", "Player count is one for single player game.");
|
||||
}
|
||||
|
||||
[APITestCase(TestType.EditMode)]
|
||||
public static void PositionTest()
|
||||
{
|
||||
Player p = new Player(PlayerType.Local);
|
||||
if (!Assert.Errorless(() => { p.Teleport(0, 0, 0, relative: false); }, "Player.Teleport(origin) errored: ", "Player teleported to origin successfully.")) return;
|
||||
if (!Assert.CloseTo(p.Position, float3.zero, "Player is not close to origin despite being teleported there.", "Player.Position is at origin.")) return;
|
||||
if (!Assert.Errorless(() => { p.Position = float3.zero + 1; }, "Player.Position = origin+1 errored: ", "Player moved to origin+1.")) return;
|
||||
Assert.CloseTo(p.Position, float3.zero + 1, "Player is not close to origin+1 despite being teleported there.", "Player.Position is at origin+1.");
|
||||
}
|
||||
|
||||
[APITestCase(TestType.Menu)]
|
||||
public static void InvalidStateTest()
|
||||
{
|
||||
if (!Assert.Errorless(() => { Player.Count(); }, "Player.Count() errored in menu.", "Player.Count() succeeded in menu.")) return;
|
||||
Assert.Equal(Player.Count(), 0u, "Player.Count() is not zero in menu.", "Player count is zero in menu as expected.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
using System;
|
||||
namespace TechbloxModdingAPI.Players
|
||||
namespace GamecraftModdingAPI.Players
|
||||
{
|
||||
public enum PlayerType
|
||||
{
|
|
@ -3,42 +3,27 @@ using Svelto.ECS;
|
|||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
using Gamecraft.Damage;
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.Physics;
|
||||
|
||||
namespace TechbloxModdingAPI
|
||||
namespace GamecraftModdingAPI
|
||||
{
|
||||
/// <summary>
|
||||
/// A rigid body (like a chunk of connected blocks) during simulation.
|
||||
/// A rigid body (like a cluster of connected blocks) during simulation.
|
||||
/// </summary>
|
||||
public class SimBody : EcsObjectBase, IEquatable<SimBody>, IEquatable<EGID>
|
||||
public class SimBody : IEquatable<SimBody>, IEquatable<EGID>
|
||||
{
|
||||
/// <summary>
|
||||
/// The cluster this chunk belongs to, or null if no cluster destruction manager present or the chunk doesn't exist.
|
||||
/// Get the SimBody from a Block if possible for good performance here.
|
||||
/// </summary>
|
||||
public Cluster Cluster => cluster ??= clusterId == uint.MaxValue // Return cluster or if it's null then set it
|
||||
? Block.BlockEngine.GetCluster(Id.entityID) // If we don't have a clusterId set then get it from the game
|
||||
: GetInstance(new EGID(clusterId, CommonExclusiveGroups.SIMULATION_CLUSTERS_GROUP),
|
||||
egid => new Cluster(egid)); // Otherwise get the cluster from the ID
|
||||
public EGID Id { get; }
|
||||
|
||||
private Cluster cluster;
|
||||
private readonly uint clusterId = uint.MaxValue;
|
||||
|
||||
public SimBody(EGID id) : base(id)
|
||||
public SimBody(EGID id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public SimBody(uint id) : this(new EGID(id, CommonExclusiveGroups.SIMULATION_BODIES_GROUP))
|
||||
{
|
||||
}
|
||||
|
||||
internal SimBody(uint id, uint clusterID) : this(id)
|
||||
{
|
||||
clusterId = clusterID;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The position of this body. When setting the position, update the position of the connected bodies as well,
|
||||
/// otherwise unexpected forces may arise.
|
||||
|
@ -85,33 +70,10 @@ namespace TechbloxModdingAPI
|
|||
//set => GetStruct().physicsMass.CenterOfMass = value;
|
||||
}
|
||||
|
||||
public float Volume
|
||||
{
|
||||
get => GetStruct().volume;
|
||||
}
|
||||
|
||||
public float InitialHealth
|
||||
{
|
||||
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).initialHealth;
|
||||
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).initialHealth = value;
|
||||
}
|
||||
|
||||
public float CurrentHealth
|
||||
{
|
||||
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).currentHealth;
|
||||
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).currentHealth = value;
|
||||
}
|
||||
|
||||
public float HealthMultiplier
|
||||
{
|
||||
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).healthMultiplier;
|
||||
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(this).healthMultiplier = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the body can be moved or static.
|
||||
/// </summary>
|
||||
public bool Static => Block.BlockEngine.GetBlockInfo<MassEntityStruct>(this).isStatic; //Setting it doesn't have any effect
|
||||
public bool Static => Block.BlockEngine.GetBlockInfo<MassEntityStruct>(Id).isStatic; //Setting it doesn't have any effect
|
||||
|
||||
/// <summary>
|
||||
/// The rigid bodies connected to this one via functional joints (broken ones don't count).
|
||||
|
@ -121,18 +83,9 @@ namespace TechbloxModdingAPI
|
|||
return Block.BlockEngine.GetConnectedSimBodies(Id.entityID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The blocks that form this rigid body.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Block[] GetBlocks()
|
||||
{
|
||||
return Block.BlockEngine.GetBodyBlocks(Id.entityID);
|
||||
}
|
||||
|
||||
private ref RigidBodyEntityStruct GetStruct()
|
||||
{
|
||||
return ref Block.BlockEngine.GetBlockInfo<RigidBodyEntityStruct>(this);
|
||||
return ref Block.BlockEngine.GetBlockInfo<RigidBodyEntityStruct>(Id);
|
||||
}
|
||||
|
||||
public override string ToString()
|
|
@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
|||
|
||||
using Svelto.Tasks;
|
||||
|
||||
namespace TechbloxModdingAPI.Tasks
|
||||
namespace GamecraftModdingAPI.Tasks
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for asynchronous tasks
|
|
@ -7,7 +7,7 @@ using System.Threading.Tasks;
|
|||
using Svelto.Tasks;
|
||||
using Svelto.Tasks.Enumerators;
|
||||
|
||||
namespace TechbloxModdingAPI.Tasks
|
||||
namespace GamecraftModdingAPI.Tasks
|
||||
{
|
||||
/// <summary>
|
||||
/// An asynchronous task to be performed once.
|
|
@ -7,7 +7,7 @@ using System.Threading.Tasks;
|
|||
using Svelto.Tasks;
|
||||
using Svelto.Tasks.Enumerators;
|
||||
|
||||
namespace TechbloxModdingAPI.Tasks
|
||||
namespace GamecraftModdingAPI.Tasks
|
||||
{
|
||||
/// <summary>
|
||||
/// An asynchronous repeating task.
|
|
@ -7,7 +7,7 @@ using System.Threading.Tasks;
|
|||
using Svelto.Tasks.Lean;
|
||||
using Svelto.Tasks.ExtraLean;
|
||||
|
||||
namespace TechbloxModdingAPI.Tasks
|
||||
namespace GamecraftModdingAPI.Tasks
|
||||
{
|
||||
/// <summary>
|
||||
/// Asynchronous task scheduling for ISchedulables.
|
||||
|
@ -20,7 +20,7 @@ namespace TechbloxModdingAPI.Tasks
|
|||
{
|
||||
get
|
||||
{
|
||||
return RobocraftX.Schedulers.ClientLean.UIScheduler;
|
||||
return RobocraftX.Schedulers.Lean.UIScheduler;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,13 +28,13 @@ namespace TechbloxModdingAPI.Tasks
|
|||
{
|
||||
get
|
||||
{
|
||||
return RobocraftX.Schedulers.ClientExtraLean.UIScheduler;
|
||||
return RobocraftX.Schedulers.ExtraLean.UIScheduler;
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly Svelto.Tasks.ExtraLean.Unity.UpdateMonoRunner extraLeanRunner = new Svelto.Tasks.ExtraLean.Unity.UpdateMonoRunner("TechbloxModdingAPIExtraLean");
|
||||
public static readonly Svelto.Tasks.ExtraLean.Unity.UpdateMonoRunner extraLeanRunner = new Svelto.Tasks.ExtraLean.Unity.UpdateMonoRunner("GamecraftModdingAPIExtraLean");
|
||||
|
||||
public static readonly Svelto.Tasks.Lean.Unity.UpdateMonoRunner leanRunner = new Svelto.Tasks.Lean.Unity.UpdateMonoRunner("TechbloxModdingAPILean");
|
||||
public static readonly Svelto.Tasks.Lean.Unity.UpdateMonoRunner leanRunner = new Svelto.Tasks.Lean.Unity.UpdateMonoRunner("GamecraftModdingAPILean");
|
||||
|
||||
/// <summary>
|
||||
/// Schedule a task to run asynchronously.
|
||||
|
@ -42,7 +42,7 @@ namespace TechbloxModdingAPI.Tasks
|
|||
/// </summary>
|
||||
/// <param name="toRun">The task to run</param>
|
||||
/// <param name="extraLean">Schedule toRun on an extra lean runner?</param>
|
||||
/// <param name="ui">Schedule toRun on Techblox's built-in UI task runner?</param>
|
||||
/// <param name="ui">Schedule toRun on Gamecraft's built-in UI task runner?</param>
|
||||
public static void Schedule(ISchedulable toRun, bool extraLean = false, bool ui = false)
|
||||
{
|
||||
if (extraLean)
|
|
@ -1,5 +1,5 @@
|
|||
using System;
|
||||
namespace TechbloxModdingAPI.Tests
|
||||
namespace GamecraftModdingAPI.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Test type.
|
|
@ -5,7 +5,7 @@ using System.Runtime.CompilerServices;
|
|||
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace TechbloxModdingAPI.Tests
|
||||
namespace GamecraftModdingAPI.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// API test system assertion utilities.
|
||||
|
@ -83,12 +83,32 @@ namespace TechbloxModdingAPI.Tests
|
|||
{
|
||||
if (err == null) err = $"{nameof(T)} '{obj1}' is not equal to '{obj2}'.";
|
||||
if (success == null) success = $"{nameof(T)} '{obj1}' is equal to '{obj2}'.";
|
||||
if ((obj1 == null && obj2 == null)
|
||||
|| (obj1 != null && obj2 != null && obj1.Equals(obj2) && obj2.Equals(obj1)))
|
||||
if (obj1 == null && obj2 == null)
|
||||
{
|
||||
// pass
|
||||
Log(PASS + success);
|
||||
TestRoot.TestsPassed = true;
|
||||
return true;
|
||||
}
|
||||
else if (!(obj1 == null && obj2 == null) && obj1.Equals(obj2) && obj2.Equals(obj1))
|
||||
{
|
||||
// pass
|
||||
Log(PASS + success);
|
||||
TestRoot.TestsPassed = true;
|
||||
return true;
|
||||
}
|
||||
else if (obj1 != null && (obj1 != null && !obj1.Equals(obj2)))
|
||||
{
|
||||
// pass
|
||||
Log(PASS + success);
|
||||
TestRoot.TestsPassed = true;
|
||||
return true;
|
||||
}
|
||||
else if (obj2 != null && !obj2.Equals(obj1))
|
||||
{
|
||||
// pass
|
||||
Log(PASS + success);
|
||||
TestRoot.TestsPassed = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -119,25 +139,6 @@ namespace TechbloxModdingAPI.Tests
|
|||
return true;
|
||||
}
|
||||
|
||||
public static bool Errorful<T>(Action tryThis, string err = null, string success = null) where T : Exception
|
||||
{
|
||||
if (err == null) err = $"{tryThis} was expected to error but completed without errors.";
|
||||
if (success == null) success = $"{tryThis} completed with an expected error.";
|
||||
try
|
||||
{
|
||||
tryThis();
|
||||
}
|
||||
catch (T e)
|
||||
{
|
||||
TestRoot.TestsPassed = true;
|
||||
Log(PASS + success + " " + e.GetType().Name + ": " + e.Message);
|
||||
return true;
|
||||
}
|
||||
Log(FAIL + err);
|
||||
TestRoot.TestsPassed = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool CloseTo(float a, float b, string err = null, string success = null, float delta = float.Epsilon)
|
||||
{
|
||||
if (err == null) err = $"{a} is not within {delta} of {b}.";
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue