private static void objLoaded(GameObject[] loaded) { try { //Sanity check if (objToEntity[0].model != loaded[0].name) { throw new Exception("Mod loading failed. Model doesn't map to entity. " + objToEntity[0].model + " != " + loaded[0].name); } TDLPlugin.DebugOutput(objToEntity[0].entity + " Loaded"); //Assign the loaded components Entity.GetEntityByName(objToEntity[0].entity).prefab.AddComponent <MeshFilter>().mesh = loaded[0].GetComponent <MeshFilter>().mesh; Entity.GetEntityByName(objToEntity[0].entity).prefab.AddComponent <MeshRenderer>().material = loaded[0].GetComponent <MeshRenderer>().material; //Destroy the created GameObject, and remove the head of the list UnityEngine.Object.Destroy(loaded[0]); objToEntity.RemoveAt(0); //If we have more than 1 object to load, start loading again if (loadList.Count > 0) { loadTimer.Enabled = true; } else { AllModelsLoadedHandler(); } } catch (Exception ex) { System.IO.File.AppendAllText(TDLPlugin.path + "/error_log.log", ex.ToString() + "\n\n"); } }
public LoadEntityTable() { //Last mod will overwrite the first, as per normal foreach (Mod loadingMod in TDLPlugin.mods) { TDLPlugin.DebugOutput("Loading mod: " + loadingMod.Name); //Determine the path to load the mod from string workingPath = TDLPlugin.path + "/" + loadingMod.Path + "/"; //Load all of the components //Load the script dll file, if it exists Assembly workingAssembly = null; try { //Security check if (loadingMod.CanRunScripts) { workingAssembly = Assembly.LoadFile(workingPath + loadingMod.Name + ".dll"); } } catch { } //Load the entities loadModEntities(workingPath, loadingMod.Name, workingAssembly); //Load other text assets - such as spawn categories, or recipies if (Directory.Exists(workingPath + "textassets")) { loadCategories(workingPath + "textassets"); loadRecipes(workingPath + "textassets"); } } //Create the timer to load the next object //Some bug in the lib means that I can't call repeatedly loadTimer = new Timer(10); loadTimer.Elapsed += OnLoadTimerEvent; //Don't enable, the callback will do that for us if (loadList.Count > 0) { loadNextObjFile(); } }
//The game will call this function public static System.Object HookTDL(System.Object[] args) { try { //Set the startup path, so we can find the modding directory if (pl == null) { path = System.Reflection.Assembly.GetExecutingAssembly().CodeBase.Substring(8); path = path.Substring(0, path.Substring(0, path.LastIndexOf("/")).LastIndexOf("/")) + "/Mods"; if (!Directory.Exists(path) || !File.Exists(path + "/modloader.xml")) { CreateModDirectory(); } settingsDoc.LoadXml(System.IO.File.ReadAllText(path + "/modloader.xml")); //Load the mods XmlDocument modDoc = new XmlDocument(); XmlNodeList eleList = settingsDoc.SelectNodes("/modloader/loadorder/*"); List <Mod> modsTemp = new List <Mod>(); for (int i = 0; i < eleList.Count; i++) { if (!bool.Parse(eleList[i].SelectSingleNode("@enabled").Value)) { continue; } //Is this mod allowed to use code? bool canRunScripts = false; try { canRunScripts = bool.Parse(eleList[i].SelectSingleNode("@scripts").Value); } catch { } string modPath = eleList[i].SelectSingleNode("text()").Value; modDoc.Load(path + "\\" + modPath + "\\info.xml"); string modName = modDoc.SelectSingleNode("mod/name/text()").Value; string modVersion = modDoc.SelectSingleNode("mod/version/text()").Value; string modAuthor = modDoc.SelectSingleNode("mod/author/text()").Value; modsTemp.Add(new Mod(modName, modVersion, modAuthor, modPath, canRunScripts)); } mods = modsTemp.ToArray(); //Load the settings eleList = settingsDoc.SelectNodes("/modloader/settings/setting"); for (int i = 0; i < eleList.Count; i++) { settings.Add(eleList[i].SelectSingleNode("@id").Value, eleList[i].SelectSingleNode("text()").Value); } //Create the reference pl = new TDLPlugin(); //Add the ModsMenu menu //TDLMenuCommon.Singleton.gameObject.AddComponent<ModsMenu>(); //Check settings, such as TextAsset dumps if (!debugging) { pl.WriteOutTextAssets(); } } //We are passing in the entrypoint as a string here, so a cast should be fine string command = ""; try { command = (string)args[0]; } catch (Exception ex) { //If it fails, give some feedback as to why if (args != null) { DebugOutput("Invalid parameter (0): " + args[0]); } else { DebugOutput("Invalid parameter (0): null"); } System.IO.File.WriteAllText(path + "/error_log.log", "Hook Argument Exception\r\n" + ex.ToString()); } //Switch for all of the known hooks switch (command) { case "loadEntityTable": let = new LoadEntityTable(); //TEMP pl.probingCode(); return(""); case "ShowModMenu": if (!BodyMenuMods.singleton) { Component.FindObjectOfType <StartMenu>().gameObject.AddComponent <BodyMenuMods>(); } return(BodyMenuMods.singleton); case "LoadPrefab": DebugOutput("Prefab: '" + (string)args[1] + "'"); return(LoadEntityTable.getPrefabObject((string)args[1])); default: DebugOutput("No hook found for '" + command + "'"); break; } } catch (Exception ex) { System.IO.File.AppendAllText(path + "/error_log.log", ex.ToString() + "\n\n"); } return(null); }
public void loadModEntities(string workingPath, string modName, Assembly workingAssembly) { //If we have entities to load, do so workingPath += "entities"; if (Directory.Exists(workingPath)) { //Load all entity files XmlDocument entityDoc = new XmlDocument(); foreach (string fileName in Directory.GetFiles(workingPath, "*.xml", SearchOption.TopDirectoryOnly)) { //Load the file entityDoc.LoadXml(System.IO.File.ReadAllText(fileName)); //Store the name string entityName = entityDoc.SelectSingleNode("/entity/@name").Value; Entity newEnt = Entity.GetEntityByName(entityName); GameObject newPrefab; //If the object doesn't exist yet, make it if (newEnt.entityName == "prop_unknown") { TDLPlugin.DebugOutput("Unknown entity, creating: " + entityName); //Create the entity XmlDocument xmlDocument = new XmlDocument(); //Load the Xml xmlDocument.LoadXml("<entity class='" + entityDoc.SelectSingleNode("/entity/properties/class/text()").Value + "' name='" + entityName + "' near='yes' cache='3' ambient='yes' />"); newEnt = new Entity(xmlDocument.DocumentElement); //Create the entity prefab newPrefab = new GameObject(entityName + "_prefab"); } else { newPrefab = newEnt._prefab; } //Entity properties try { newEnt.carry = bool.Parse(entityDoc.SelectSingleNode("/entity/properties/canCarry/text()").Value); } catch {} try { newEnt.drag = bool.Parse(entityDoc.SelectSingleNode("/entity/properties/canDrag/text()").Value); } catch { } //Still not sure what this does try { //newEnt.farOverride = bool.Parse(entityDoc.SelectSingleNode("/entity/properties/near/text()").Value); } catch { } try { newEnt.lootEntry = new LootEntry(entityDoc.SelectSingleNode("/entity/properties/lootEntry/text()").Value.Split(',')); } catch { } //Mesh try { string replacementMesh = entityDoc.SelectSingleNode("/entity/mesh/text()").Value; if (replacementMesh != null) { //Disable the current model try { newPrefab.GetComponent <LODGroup>().enabled = false; } catch { } //Load our model loadList.Add(workingPath + "/" + entityDoc.SelectSingleNode("/entity/mesh/text()").Value); string meshFileName = entityDoc.SelectSingleNode("/entity/mesh/text()").Value; objToEntity.Add(new ModelEntityMapping(meshFileName.Substring(0, meshFileName.LastIndexOf('.')), entityName)); //Set the texture randomiser up try { XmlNodeList texturesList = entityDoc.SelectNodes("/entity/randomTextures/*"); //Add all of the possible textures Texture2D[] possibleTextures = new Texture2D[texturesList.Count]; for (int i = 0; i < texturesList.Count; i++) { possibleTextures[i] = new Texture2D(int.Parse(texturesList[i].SelectSingleNode("@width").Value), int.Parse(texturesList[i].SelectSingleNode("@height").Value)); possibleTextures[i].LoadImage(System.IO.File.ReadAllBytes(workingPath + "/" + texturesList[i].SelectSingleNode("text()").Value)); } newPrefab.AddComponent <TextureRandomiser>().textures = possibleTextures; } catch {} } } catch { //Nope, no mesh } //Physics try { //Are we removing the orginal? try { if (Boolean.Parse(entityDoc.SelectSingleNode("/entity/physics/@replace").Value)) { foreach (Collider col in newPrefab.GetComponents <Collider>()) { UnityEngine.Object.Destroy(col); } } } catch (System.Xml.XPath.XPathException) { //Not specified, so no } XmlNodeList eleList = entityDoc.SelectNodes("/entity/physics/*"); //Add all child physics elements for (int i = 0; i < eleList.Count; i++) { string type = eleList[i].Name; //TODO: Add all col types to this Collider newCol = null; switch (type) { case "rigidBody": Rigidbody rb = newPrefab.GetComponent <Rigidbody>(); if (rb == null) { rb = newPrefab.AddComponent <Rigidbody>(); } rb.mass = float.Parse(eleList[i].SelectSingleNode("mass/text()").Value); //rb.drag = 0f; //rb.mass = 1f; break; case "boxCollider": string[] center = eleList[i].SelectSingleNode("center/text()").Value.Split('|'); string[] size = eleList[i].SelectSingleNode("size/text()").Value.Split('|'); newCol = newPrefab.AddComponent <BoxCollider>(); ((BoxCollider)newCol).center = new Vector3(float.Parse(center[0]), float.Parse(center[1]), float.Parse(center[2])); ((BoxCollider)newCol).size = new Vector3(float.Parse(size[0]), float.Parse(size[1]), float.Parse(size[2])); //Temp, this should be loaded elsewhere, somehow //newCol.material = (PhysicMaterial)Resources.Load("PhysicMaterials/Ice"); break; case "sphereCollider": break; //Should only be used for statics case "meshCollider": Mesh colMesh = ObjImporter.ImportFile(workingPath + "/" + eleList[i].SelectSingleNode("mesh/text()").Value); newCol = newPrefab.AddComponent <MeshCollider>(); ((MeshCollider)newCol).sharedMesh = colMesh; ((MeshCollider)newCol).convex = bool.Parse(eleList[i].SelectSingleNode("convex/text()").Value); //newCol.material = (PhysicMaterial)Resources.Load("PhysicMaterials/Ice"); break; default: TDLPlugin.DebugOutput("Unknown physics type: " + type); break; } //If it has a enabled comp, check it try { if (!bool.Parse(eleList[i].SelectSingleNode("enabled/text()").Value)) { newCol.isTrigger = true; } } catch { } try { newCol.name = eleList[i].Attributes["id"].Value; DebugConsole.Log("Setting name " + newCol.name + " on " + newPrefab.name); } catch {} } } catch { //Nope, no physics } //Script Components try { XmlNodeList componentListXML = entityDoc.SelectNodes("/entity/scripts/*"); //Add all scripts to the entity for (int i = 0; i < componentListXML.Count; i++) { Type loadedType = workingAssembly.GetType("Mod." + modName + "." + componentListXML[i].SelectSingleNode("text()").Value); //Init a setup member loadedType.InvokeMember("ModLoaderInit", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, new object[] { newEnt.entityName, workingPath }); //Add the component newPrefab.AddComponent(loadedType); } } catch { //No scripts to load } //Reassign the prefab newEnt._prefab = newPrefab; prefabs.Add(newPrefab.name, newPrefab); DebugConsole.Log("Has no prefab:" + newEnt.hasNoPrefab); DebugConsole.Log("Test prefab:" + newEnt._prefab.name); newEnt.hasNoPrefab = false; newEnt.prefabName = newEnt._prefab.name; DebugConsole.Log("Mod prefab:" + newEnt.prefab.name); } } //Assembly assemble = Assembly.LoadFile(@"D:\SteamLibrary\SteamApps\common\The Dead Linger\TDL_Data\Mods\RotateLock\RotateLock.dll"); //TDLMenuCommon.Singleton.gameObject.AddComponent(assemble.GetType("Mod.RotateLock.RotateLockComponent", true)); }