public ProcessMemoryTests() { _processId = Process.GetCurrentProcess().Id; _remoteFunctionDelegate = new RemoteFunction(TestRemoteThread); _remoteFunctionPointer = Marshal.GetFunctionPointerForDelegate(_remoteFunctionDelegate); }
// Bind the RPC functions we'll be calling void BindMethods() { materialListCall = new RemoteFunction <dfproto.EmptyMessage, RemoteFortressReader.MaterialList>(); materialListCall.bind(networkClient, "GetMaterialList", "RemoteFortressReader"); itemListCall = new RemoteFunction <dfproto.EmptyMessage, RemoteFortressReader.MaterialList>(); itemListCall.bind(networkClient, "GetItemList", "RemoteFortressReader"); tiletypeListCall = new RemoteFunction <dfproto.EmptyMessage, RemoteFortressReader.TiletypeList>(); tiletypeListCall.bind(networkClient, "GetTiletypeList", "RemoteFortressReader"); blockListCall = new RemoteFunction <RemoteFortressReader.BlockRequest, RemoteFortressReader.BlockList>(); blockListCall.bind(networkClient, "GetBlockList", "RemoteFortressReader"); hashCheckCall = new RemoteFunction <dfproto.EmptyMessage>(); hashCheckCall.bind(networkClient, "CheckHashes", "RemoteFortressReader"); unitListCall = new RemoteFunction <dfproto.EmptyMessage, RemoteFortressReader.UnitList>(); unitListCall.bind(networkClient, "GetUnitList", "RemoteFortressReader"); viewInfoCall = new RemoteFunction <dfproto.EmptyMessage, RemoteFortressReader.ViewInfo>(); viewInfoCall.bind(networkClient, "GetViewInfo", "RemoteFortressReader"); mapInfoCall = new RemoteFunction <dfproto.EmptyMessage, RemoteFortressReader.MapInfo>(); mapInfoCall.bind(networkClient, "GetMapInfo", "RemoteFortressReader"); mapResetCall = new RemoteFunction <dfproto.EmptyMessage>(); mapResetCall.bind(networkClient, "ResetMapHashes", "RemoteFortressReader"); buildingListCall = new RemoteFunction <dfproto.EmptyMessage, RemoteFortressReader.BuildingList>(); buildingListCall.bind(networkClient, "GetBuildingDefList", "RemoteFortressReader"); worldMapCall = new RemoteFunction <dfproto.EmptyMessage, RemoteFortressReader.WorldMap>(); worldMapCall.bind(networkClient, "GetWorldMap", "RemoteFortressReader"); regionMapCall = new RemoteFunction <dfproto.EmptyMessage, RemoteFortressReader.RegionMaps>(); regionMapCall.bind(networkClient, "GetRegionMaps", "RemoteFortressReader"); creatureRawListCall = new RemoteFunction <dfproto.EmptyMessage, RemoteFortressReader.CreatureRawList>(); creatureRawListCall.bind(networkClient, "GetCreatureRaws", "RemoteFortressReader"); }
/// <summary> /// Bind the RPC functions we'll be calling /// </summary> void BindMethods() { materialListCall = new RemoteFunction <EmptyMessage, MaterialList>(networkClient, "GetMaterialList", "RemoteFortressReader"); itemListCall = new RemoteFunction <EmptyMessage, MaterialList>(networkClient, "GetItemList", "RemoteFortressReader"); tiletypeListCall = new RemoteFunction <EmptyMessage, TiletypeList>(networkClient, "GetTiletypeList", "RemoteFortressReader"); blockListCall = CreateAndBindTimed <BlockRequest, BlockList>(GameSettings.Instance.updateTimers.blockUpdate, networkClient, "GetBlockList", "RemoteFortressReader"); unitListCall = new RemoteFunction <BlockRequest, UnitList>(networkClient, "GetUnitListInside", "RemoteFortressReader"); unitListCallLegacy = new RemoteFunction <EmptyMessage, UnitList>(networkClient, "GetUnitList", "RemoteFortressReader"); viewInfoCall = new RemoteFunction <EmptyMessage, ViewInfo>(networkClient, "GetViewInfo", "RemoteFortressReader"); mapInfoCall = new RemoteFunction <EmptyMessage, MapInfo>(networkClient, "GetMapInfo", "RemoteFortressReader"); mapResetCall = new RemoteFunction <EmptyMessage>(networkClient, "ResetMapHashes", "RemoteFortressReader"); buildingListCall = new RemoteFunction <EmptyMessage, BuildingList>(networkClient, "GetBuildingDefList", "RemoteFortressReader"); worldMapCall = new RemoteFunction <EmptyMessage, WorldMap>(networkClient, "GetWorldMapNew", "RemoteFortressReader"); worldMapCenterCall = new RemoteFunction <EmptyMessage, WorldMap>(networkClient, "GetWorldMapCenter", "RemoteFortressReader"); regionMapCall = new RemoteFunction <EmptyMessage, RegionMaps>(networkClient, "GetRegionMapsNew", "RemoteFortressReader"); creatureRawListCall = new RemoteFunction <EmptyMessage, CreatureRawList>(networkClient, "GetCreatureRaws", "RemoteFortressReader"); partialCreatureRawListCall = new RemoteFunction <ListRequest, CreatureRawList>(networkClient, "GetPartialCreatureRaws", "RemoteFortressReader"); plantRawListCall = new RemoteFunction <EmptyMessage, PlantRawList>(networkClient, "GetPlantRaws", "RemoteFortressReader"); keyboardEventCall = new RemoteFunction <KeyboardEvent>(networkClient, "PassKeyboardEvent", "RemoteFortressReader"); copyScreenCall = new RemoteFunction <EmptyMessage, RemoteFortressReader.ScreenCapture>(networkClient, "CopyScreen", "RemoteFortressReader"); digCommandCall = new RemoteFunction <DigCommand>(networkClient, "SendDigCommand", "RemoteFortressReader"); pauseCommandCall = new RemoteFunction <SingleBool>(networkClient, "SetPauseState", "RemoteFortressReader"); pauseStatusCall = new RemoteFunction <EmptyMessage, SingleBool>(networkClient, "GetPauseState", "RemoteFortressReader"); versionInfoCall = new RemoteFunction <EmptyMessage, VersionInfo>(networkClient, "GetVersionInfo", "RemoteFortressReader"); reportsCall = new RemoteFunction <EmptyMessage, Status>(networkClient, "GetReports", "RemoteFortressReader"); moveCommandCall = new RemoteFunction <MoveCommandParams>(networkClient, "MoveCommand", "RemoteFortressReader"); jumpCommandCall = new RemoteFunction <MoveCommandParams>(networkClient, "JumpCommand", "RemoteFortressReader"); menuQueryCall = new RemoteFunction <EmptyMessage, MenuContents>(networkClient, "MenuQuery", "RemoteFortressReader"); movementSelectCommandCall = new RemoteFunction <IntMessage>(networkClient, "MovementSelectCommand", "RemoteFortressReader"); miscMoveCall = new RemoteFunction <MiscMoveParams>(networkClient, "MiscMoveCommand", "RemoteFortressReader"); languageCall = new RemoteFunction <EmptyMessage, Language>(networkClient, "GetLanguage", "RemoteFortressReader"); getSideMenuCall = new RemoteFunction <EmptyMessage, SidebarState>(networkClient, "GetSideMenu", "RemoteFortressReader"); setSideMenuCall = new RemoteFunction <SidebarCommand>(networkClient, "SetSideMenu", "RemoteFortressReader"); }
public ConnectionState() { network_client = new DFHack.RemoteClient(df_network_out); is_connected = network_client.connect(); if (!is_connected) { return; } net_block_request = new RemoteFortressReader.BlockRequest(); MaterialListCall = new RemoteFunction <dfproto.EmptyMessage, RemoteFortressReader.MaterialList>(); MaterialListCall.bind(network_client, "GetMaterialList", "RemoteFortressReader"); TiletypeListCall = new RemoteFunction <dfproto.EmptyMessage, RemoteFortressReader.TiletypeList>(); TiletypeListCall.bind(network_client, "GetTiletypeList", "RemoteFortressReader"); BlockListCall = new RemoteFunction <RemoteFortressReader.BlockRequest, RemoteFortressReader.BlockList>(); BlockListCall.bind(network_client, "GetBlockList", "RemoteFortressReader"); HashCheckCall = new RemoteFunction <dfproto.EmptyMessage>(); HashCheckCall.bind(network_client, "CheckHashes", "RemoteFortressReader"); UnitListCall = new RemoteFunction <dfproto.EmptyMessage, RemoteFortressReader.UnitList>(); UnitListCall.bind(network_client, "GetUnitList", "RemoteFortressReader"); ViewInfoCall = new RemoteFunction <dfproto.EmptyMessage, RemoteFortressReader.ViewInfo>(); ViewInfoCall.bind(network_client, "GetViewInfo", "RemoteFortressReader"); MapInfoCall = new RemoteFunction <dfproto.EmptyMessage, RemoteFortressReader.MapInfo>(); MapInfoCall.bind(network_client, "GetMapInfo", "RemoteFortressReader"); MapResetCall = new RemoteFunction <dfproto.EmptyMessage>(); MapResetCall.bind(network_client, "ResetMapHashes", "RemoteFortressReader"); }
private void CallFunction() { String funcname = request.Params["phprpc_func"].ToLower(CultureInfo.InvariantCulture); RemoteFunction rf = null; if (functions.ContainsKey(funcname)) { rf = (RemoteFunction)functions[funcname]; } else if (globalFunctions.ContainsKey(funcname)) { rf = (RemoteFunction)globalFunctions[funcname]; } else { throw new Exception("Can't find this function " + request.Params["phprpc_func"] + "()."); } InitKey(); ArrayList arguments = GetArguments(); String result = null; for (Int32 i = 0, n = rf.functions.Length; i < n; i++) { try { result = EncodeString(EncryptString(Call(rf.functions[i], rf.obj, arguments), 2)); break; } catch (Exception e) { if (i == n - 1) { errstr = String.Empty; throw e; } else { errno = 2; if (debug) { errstr += e.ToString() + "\r\n"; } else { errstr += e.Message + "\r\n"; } } } } buffer.Append("phprpc_result=\""); buffer.Append(result); buffer.Append("\";\r\n"); if (byref) { buffer.Append("phprpc_args=\""); buffer.Append(EncodeString(EncryptString(Serialize(arguments), 1))); buffer.Append("\";\r\n"); } SendError(); }
public RemoteFunctionListViewItem(RemoteFunction function) : base(function.Hash) { Function = function; SubItems.Add(function.FullName); SubItems.Add(function.File); SubItems.Add(function.ExecuteAction.ToString()); SubItems.Add(function.ExecuteCount.ToString()); function.ListViewItem = this; }
/// <summary> /// Adds a remote function. /// </summary> /// <param name="funcName">The name of the function.</param> /// <param name="function">The RemoteFunction delegate to add.</param> public void AddRemoteFunction(string funcName, RemoteFunction function) { if (Events.ContainsKey(funcName)) { throw new InvalidOperationException(String.Format("Function \"{0}\" already exists!", funcName)); } Functions.TryAdd(funcName, function); }
public void InjectAndWait() { this.MemorySharp = new MemorySharp(targetProcess); MemorySharp.Modules.Inject(domainPath + "\\" + domainName, true); RemoteFunction remoteFunction = this.MemorySharp[domainName]["LoadDomainHostSettings"]; object[] arrayObjects = new[] { payloadPath, payloadName, payloadArgs }; remoteFunction.Execute(CallingConventions.Cdecl, arrayObjects); this.MemorySharp[domainName]["HostDomain"].Execute(CallingConventions.Cdecl, new object[] { }); }
static void AttachToMainThread(RemoteFunction mono_get_root_domain, RemoteFunction mono_thread_attach) { Console.ForegroundColor = ConsoleColor.Cyan; Console.Write("Attaching to/Entering the primary/main mono thread/context... "); IntPtr mono_get_root_domain_result = mono_get_root_domain.Execute(CallingConventions.Cdecl); // Returns MonoDomain. IntPtr mono_thread_attach_result = mono_thread_attach.Execute(CallingConventions.Cdecl, mono_get_root_domain_result); // Returns MonoThread. Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("success."); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("{0} returned {1} (0x{2})", mono_get_root_domain.Name, mono_get_root_domain_result, mono_get_root_domain_result.ToString("X2")); Console.WriteLine("{0} returned {1} (0x{2})", mono_thread_attach.Name, mono_thread_attach_result, mono_thread_attach_result.ToString("X2")); }
/// <summary> /// Tries to bind an RPC function, leaving returning null if it fails. /// </summary> /// <typeparam name="Input">Protobuf class used as an input</typeparam> /// <param name="client">Connection to Dwarf Fortress</param> /// <param name="name">Name of the RPC function to bind to</param> /// <param name="proto">Name of the protobuf file to use</param> /// <returns>Bound remote function on success, otherwise null.</returns> RemoteFunction <Input> CreateAndBind <Input>(RemoteClient client, string name, string proto = "") where Input : class, ProtoBuf.IExtensible, new() { RemoteFunction <Input> output = new RemoteFunction <Input>(); if (output.bind(client, name, proto)) { return(output); } else { return(null); } }
TimedRemoteFunction <Input, Output> CreateAndBindTimed <Input, Output>(float interval, RemoteClient client, string name, string proto = "") where Input : class, ProtoBuf.IExtensible, new() where Output : class, ProtoBuf.IExtensible, new() { RemoteFunction <Input, Output> output = new RemoteFunction <Input, Output>(); if (output.Bind(client, name, proto)) { return(new TimedRemoteFunction <Input, Output>(interval, output)); } else { return(null); } }
public bool ConnectToDF() { ColorConsoleStream stream = new ColorConsoleStream(); client = new RemoteClient(stream); if (!client.Connect()) { return(false); } mapInfoCall = new RemoteFunction <EmptyMessage, MapInfo>(client, "GetMapInfo", "RemoteFortressReader"); tileTypeListCall = new RemoteFunction <EmptyMessage, TiletypeList>(client, "GetTiletypeList", "RemoteFortressReader"); mapReadCall = new RemoteFunction <BlockRequest, BlockList>(client, "GetBlockList", "RemoteFortressReader"); mapResetCall = new RemoteFunction <EmptyMessage>(client, "ResetMapHashes", "RemoteFortressReader"); materialListCall = new RemoteFunction <EmptyMessage, MaterialList>(client, "GetMaterialList", "RemoteFortressReader"); return(true); }
/// <summary> /// Bind the RPC functions we'll be calling /// </summary> void BindMethods() { materialListCall = CreateAndBind <dfproto.EmptyMessage, RemoteFortressReader.MaterialList>(networkClient, "GetMaterialList", "RemoteFortressReader"); itemListCall = CreateAndBind <dfproto.EmptyMessage, RemoteFortressReader.MaterialList>(networkClient, "GetItemList", "RemoteFortressReader"); tiletypeListCall = CreateAndBind <dfproto.EmptyMessage, RemoteFortressReader.TiletypeList>(networkClient, "GetTiletypeList", "RemoteFortressReader"); blockListCall = CreateAndBind <RemoteFortressReader.BlockRequest, RemoteFortressReader.BlockList>(networkClient, "GetBlockList", "RemoteFortressReader"); unitListCall = CreateAndBind <dfproto.EmptyMessage, RemoteFortressReader.UnitList>(networkClient, "GetUnitList", "RemoteFortressReader"); viewInfoCall = CreateAndBind <dfproto.EmptyMessage, RemoteFortressReader.ViewInfo>(networkClient, "GetViewInfo", "RemoteFortressReader"); mapInfoCall = CreateAndBind <dfproto.EmptyMessage, RemoteFortressReader.MapInfo>(networkClient, "GetMapInfo", "RemoteFortressReader"); mapResetCall = CreateAndBind <dfproto.EmptyMessage>(networkClient, "ResetMapHashes", "RemoteFortressReader"); buildingListCall = CreateAndBind <dfproto.EmptyMessage, RemoteFortressReader.BuildingList>(networkClient, "GetBuildingDefList", "RemoteFortressReader"); worldMapCall = CreateAndBind <dfproto.EmptyMessage, RemoteFortressReader.WorldMap>(networkClient, "GetWorldMapNew", "RemoteFortressReader"); worldMapCenterCall = CreateAndBind <dfproto.EmptyMessage, RemoteFortressReader.WorldMap>(networkClient, "GetWorldMapCenter", "RemoteFortressReader"); regionMapCall = CreateAndBind <dfproto.EmptyMessage, RemoteFortressReader.RegionMaps>(networkClient, "GetRegionMapsNew", "RemoteFortressReader"); creatureRawListCall = CreateAndBind <dfproto.EmptyMessage, RemoteFortressReader.CreatureRawList>(networkClient, "GetCreatureRaws", "RemoteFortressReader"); plantRawListCall = CreateAndBind <dfproto.EmptyMessage, RemoteFortressReader.PlantRawList>(networkClient, "GetPlantRaws", "RemoteFortressReader"); keyboardEventCall = CreateAndBind <RemoteFortressReader.KeyboardEvent>(networkClient, "PassKeyboardEvent", "RemoteFortressReader"); copyScreenCall = CreateAndBind <dfproto.EmptyMessage, RemoteFortressReader.ScreenCapture>(networkClient, "CopyScreen", "RemoteFortressReader"); }
//const string WebMonoDll = "mono-1-vc.dll"; static void GetMonoRemoteFunctions(MemorySharp memorySharp, out RemoteFunction mono_get_root_domain, out RemoteFunction mono_thread_attach, out RemoteFunction mono_security_set_mode, out RemoteFunction mono_domain_get, out RemoteFunction mono_domain_assembly_open, out RemoteFunction mono_assembly_get_image, out RemoteFunction mono_class_from_name, out RemoteFunction mono_class_get_method_from_name, out RemoteFunction mono_runtime_invoke) { Console.ForegroundColor = ConsoleColor.White; mono_get_root_domain = memorySharp[DesktopMonoDll].FindFunction("mono_get_root_domain"); // Returns MonoDomain. Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Function \"{0}\" found at 0x{1} address", mono_get_root_domain.Name, mono_get_root_domain.BaseAddress.ToString("X2")); Console.ForegroundColor = ConsoleColor.White; mono_thread_attach = memorySharp[DesktopMonoDll].FindFunction("mono_thread_attach"); // Returns MonoThread. Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Function \"{0}\" found at 0x{1} address", mono_thread_attach.Name, mono_thread_attach.BaseAddress.ToString("X2")); Console.ForegroundColor = ConsoleColor.White; mono_security_set_mode = memorySharp[DesktopMonoDll].FindFunction("mono_security_set_mode"); // Returns void. Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Function \"{0}\" found at 0x{1} address", mono_security_set_mode.Name, mono_security_set_mode.BaseAddress.ToString("X2")); Console.ForegroundColor = ConsoleColor.White; mono_domain_get = memorySharp[DesktopMonoDll].FindFunction("mono_domain_get"); // Returns MonoDomain. Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Function \"{0}\" found at 0x{1} address", mono_domain_get.Name, mono_domain_get.BaseAddress.ToString("X2")); Console.ForegroundColor = ConsoleColor.White; mono_domain_assembly_open = memorySharp[DesktopMonoDll].FindFunction("mono_domain_assembly_open"); // Returns MonoAssembly. Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Function \"{0}\" found at 0x{1} address", mono_domain_assembly_open.Name, mono_domain_assembly_open.BaseAddress.ToString("X2")); Console.ForegroundColor = ConsoleColor.White; mono_assembly_get_image = memorySharp[DesktopMonoDll].FindFunction("mono_assembly_get_image"); // Returns MonoImage. Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Function \"{0}\" found at 0x{1} address", mono_assembly_get_image.Name, mono_assembly_get_image.BaseAddress.ToString("X2")); Console.ForegroundColor = ConsoleColor.White; mono_class_from_name = memorySharp[DesktopMonoDll].FindFunction("mono_class_from_name"); // Returns MonoClass. Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Function \"{0}\" found at 0x{1} address", mono_class_from_name.Name, mono_class_from_name.BaseAddress.ToString("X2")); Console.ForegroundColor = ConsoleColor.White; mono_class_get_method_from_name = memorySharp[DesktopMonoDll].FindFunction("mono_class_get_method_from_name"); // Returns MonoMethod. Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Function \"{0}\" found at 0x{1} address", mono_class_get_method_from_name.Name, mono_class_get_method_from_name.BaseAddress.ToString("X2")); Console.ForegroundColor = ConsoleColor.White; mono_runtime_invoke = memorySharp[DesktopMonoDll].FindFunction("mono_runtime_invoke"); // Returns MonoObject. Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Function \"{0}\" found at 0x{1} address", mono_runtime_invoke.Name, mono_runtime_invoke.BaseAddress.ToString("X2")); Console.ForegroundColor = ConsoleColor.White; }
private void LoadModules() { DirectoryInfo di = new DirectoryInfo("Modules"); if (!di.Exists) { di.Create(); } foreach (FileInfo fi in di.GetFiles("*.ncm")) { try { Assembly asm = Assembly.LoadFile(fi.FullName); foreach (Type t in asm.GetTypes()) { foreach (MethodInfo mi in t.GetMethods()) { if (!Attribute.IsDefined(mi, typeof(RemoteCallAttribute))) { continue; } RemoteFunction function = new RemoteFunction(asm, t, mi, lvFunctions); if (LoadedFunctions.ContainsKey(function.Hash)) { function.Dispose(); } else { LoadedFunctions.Add(function.Hash, function); lvFunctions.Items.Add(new RemoteFunctionListViewItem(function)); } } } } catch (Exception ex) { LogError(ex); } } }
private void _server_OnDataRetrieved(eSock.Server sender, eSock.Server.eSockClient client, object[] data) { try { NetworkHeaders header = (NetworkHeaders)data[0]; if (header == NetworkHeaders.Handshake) { string key = Guid.NewGuid().ToString(); client.Send((byte)NetworkHeaders.AcceptHandshake, key); client.Encryption.EncryptionKey = key; client.Encryption.Enabled = true; return; } if (header == NetworkHeaders.RemoteCall) { string functionHash = (string)data[1]; if (!LoadedFunctions.ContainsKey(functionHash)) { Console.WriteLine("Invalid call ({0})", functionHash); client.Send(null); return; } object[] args = (object[])data[2]; RemoteFunction function = LoadedFunctions[functionHash]; client.Send(function.Execute(args)); Console.WriteLine("Function Call ({0}) Value={1}", function, functionHash); } } catch (Exception ex) { client.Send(null); LogError(ex); } }
private void ReceiveMessage(object obj) { while (IsUdpcRecvStart) { try { byte[] bytRecv = udpcRecv.Receive(ref localIpep); string reData = Encoding.GetEncoding("gb2312").GetString(bytRecv, 0, bytRecv.Length); RemoteFunction ur = JsonConvert.DeserializeObject <RemoteFunction>(reData); switch (ur.function) { case "minerStatus": MinerStatusLoad.remoteMinerStatus(JsonConvert.DeserializeObject <RemoteMinerStatus>(reData)); break; } } catch (Exception ex) { } } }
public ConnectionState() { network_client = new DFHack.RemoteClient(df_network_out); is_connected = network_client.connect(); if (!is_connected) return; net_block_request = new RemoteFortressReader.BlockRequest(); MaterialListCall = new RemoteFunction<dfproto.EmptyMessage, RemoteFortressReader.MaterialList>(); MaterialListCall.bind(network_client, "GetMaterialList", "RemoteFortressReader"); TiletypeListCall = new RemoteFunction<dfproto.EmptyMessage, RemoteFortressReader.TiletypeList>(); TiletypeListCall.bind(network_client, "GetTiletypeList", "RemoteFortressReader"); BlockListCall = new RemoteFunction<RemoteFortressReader.BlockRequest, RemoteFortressReader.BlockList>(); BlockListCall.bind(network_client, "GetBlockList", "RemoteFortressReader"); HashCheckCall = new RemoteFunction<dfproto.EmptyMessage>(); HashCheckCall.bind(network_client, "CheckHashes", "RemoteFortressReader"); UnitListCall = new RemoteFunction<dfproto.EmptyMessage, RemoteFortressReader.UnitList>(); UnitListCall.bind(network_client, "GetUnitList", "RemoteFortressReader"); ViewInfoCall = new RemoteFunction<dfproto.EmptyMessage, RemoteFortressReader.ViewInfo>(); ViewInfoCall.bind(network_client, "GetViewInfo", "RemoteFortressReader"); MapInfoCall = new RemoteFunction<dfproto.EmptyMessage, RemoteFortressReader.MapInfo>(); MapInfoCall.bind(network_client, "GetMapInfo", "RemoteFortressReader"); MapResetCall = new RemoteFunction<dfproto.EmptyMessage>(); MapResetCall.bind(network_client, "ResetMapHashes", "RemoteFortressReader"); }
/// <summary> /// Bind the RPC functions we'll be calling /// </summary> void BindMethods() { materialListCall = CreateAndBind <dfproto.EmptyMessage, MaterialList>(networkClient, "GetMaterialList", "RemoteFortressReader"); itemListCall = CreateAndBind <dfproto.EmptyMessage, MaterialList>(networkClient, "GetItemList", "RemoteFortressReader"); tiletypeListCall = CreateAndBind <dfproto.EmptyMessage, TiletypeList>(networkClient, "GetTiletypeList", "RemoteFortressReader"); blockListCall = CreateAndBind <BlockRequest, BlockList>(networkClient, "GetBlockList", "RemoteFortressReader"); unitListCall = CreateAndBind <dfproto.EmptyMessage, UnitList>(networkClient, "GetUnitList", "RemoteFortressReader"); viewInfoCall = CreateAndBind <dfproto.EmptyMessage, ViewInfo>(networkClient, "GetViewInfo", "RemoteFortressReader"); mapInfoCall = CreateAndBind <dfproto.EmptyMessage, MapInfo>(networkClient, "GetMapInfo", "RemoteFortressReader"); mapResetCall = CreateAndBind <dfproto.EmptyMessage>(networkClient, "ResetMapHashes", "RemoteFortressReader"); buildingListCall = CreateAndBind <dfproto.EmptyMessage, BuildingList>(networkClient, "GetBuildingDefList", "RemoteFortressReader"); worldMapCall = CreateAndBind <dfproto.EmptyMessage, WorldMap>(networkClient, "GetWorldMapNew", "RemoteFortressReader"); worldMapCenterCall = CreateAndBind <dfproto.EmptyMessage, WorldMap>(networkClient, "GetWorldMapCenter", "RemoteFortressReader"); regionMapCall = CreateAndBind <dfproto.EmptyMessage, RegionMaps>(networkClient, "GetRegionMapsNew", "RemoteFortressReader"); creatureRawListCall = CreateAndBind <dfproto.EmptyMessage, CreatureRawList>(networkClient, "GetCreatureRaws", "RemoteFortressReader"); partialCreatureRawListCall = CreateAndBind <ListRequest, CreatureRawList>(networkClient, "GetPartialCreatureRaws", "RemoteFortressReader"); plantRawListCall = CreateAndBind <dfproto.EmptyMessage, PlantRawList>(networkClient, "GetPlantRaws", "RemoteFortressReader"); keyboardEventCall = CreateAndBind <KeyboardEvent>(networkClient, "PassKeyboardEvent", "RemoteFortressReader"); copyScreenCall = CreateAndBind <dfproto.EmptyMessage, ScreenCapture>(networkClient, "CopyScreen", "RemoteFortressReader"); digCommandCall = CreateAndBind <DigCommand>(networkClient, "SendDigCommand", "RemoteFortressReader"); pauseCommandCall = CreateAndBind <SingleBool>(networkClient, "SetPauseState", "RemoteFortressReader"); pauseStatusCall = CreateAndBind <dfproto.EmptyMessage, SingleBool>(networkClient, "GetPauseState", "RemoteFortressReader"); versionInfoCall = CreateAndBind <dfproto.EmptyMessage, VersionInfo>(networkClient, "GetVersionInfo", "RemoteFortressReader"); }
// Bind the RPC functions we'll be calling void BindMethods() { materialListCall = new RemoteFunction<dfproto.EmptyMessage, RemoteFortressReader.MaterialList>(); materialListCall.bind(networkClient, "GetMaterialList", "RemoteFortressReader"); itemListCall = new RemoteFunction<dfproto.EmptyMessage, RemoteFortressReader.MaterialList>(); itemListCall.bind(networkClient, "GetItemList", "RemoteFortressReader"); tiletypeListCall = new RemoteFunction<dfproto.EmptyMessage, RemoteFortressReader.TiletypeList>(); tiletypeListCall.bind(networkClient, "GetTiletypeList", "RemoteFortressReader"); blockListCall = new RemoteFunction<RemoteFortressReader.BlockRequest, RemoteFortressReader.BlockList>(); blockListCall.bind(networkClient, "GetBlockList", "RemoteFortressReader"); hashCheckCall = new RemoteFunction<dfproto.EmptyMessage>(); hashCheckCall.bind(networkClient, "CheckHashes", "RemoteFortressReader"); unitListCall = new RemoteFunction<dfproto.EmptyMessage, RemoteFortressReader.UnitList>(); unitListCall.bind(networkClient, "GetUnitList", "RemoteFortressReader"); viewInfoCall = new RemoteFunction<dfproto.EmptyMessage, RemoteFortressReader.ViewInfo>(); viewInfoCall.bind(networkClient, "GetViewInfo", "RemoteFortressReader"); mapInfoCall = new RemoteFunction<dfproto.EmptyMessage, RemoteFortressReader.MapInfo>(); mapInfoCall.bind(networkClient, "GetMapInfo", "RemoteFortressReader"); mapResetCall = new RemoteFunction<dfproto.EmptyMessage>(); mapResetCall.bind(networkClient, "ResetMapHashes", "RemoteFortressReader"); buildingListCall = new RemoteFunction<dfproto.EmptyMessage, RemoteFortressReader.BuildingList>(); buildingListCall.bind(networkClient, "GetBuildingDefList", "RemoteFortressReader"); worldMapCall = new RemoteFunction<dfproto.EmptyMessage, RemoteFortressReader.WorldMap>(); worldMapCall.bind(networkClient, "GetWorldMap", "RemoteFortressReader"); regionMapCall = new RemoteFunction<dfproto.EmptyMessage, RemoteFortressReader.RegionMaps>(); regionMapCall.bind(networkClient, "GetRegionMaps", "RemoteFortressReader"); creatureRawListCall = new RemoteFunction<dfproto.EmptyMessage, RemoteFortressReader.CreatureRawList>(); creatureRawListCall.bind(networkClient, "GetCreatureRaws", "RemoteFortressReader"); }
/// <summary> /// Bind methods that aren't dependent on the RFR plugin. /// </summary> void BindStaticMethods() { dfhackVersionCall = new RemoteFunction <EmptyMessage, StringMessage>(networkClient, "GetVersion"); dfVersionCall = new RemoteFunction <EmptyMessage, StringMessage>(networkClient, "GetDFVersion"); dfWorldInfoCall = new RemoteFunction <EmptyMessage, GetWorldInfoOut>(networkClient, "GetWorldInfo"); }
/// <summary> /// Bind methods that aren't dependent on the RFR plugin. /// </summary> void BindStaticMethods() { dfhackVersionCall = CreateAndBind <dfproto.EmptyMessage, dfproto.StringMessage>(networkClient, "GetVersion"); dfVersionCall = CreateAndBind <dfproto.EmptyMessage, dfproto.StringMessage>(networkClient, "GetDFVersion"); dfWorldInfoCall = CreateAndBind <dfproto.EmptyMessage, dfproto.GetWorldInfoOut>(networkClient, "GetWorldInfo"); }
public static void Main(string[] args) { string jsonContent = ""; if (args.Length == 1) { jsonContent = args[0]; } else { var cmdPath = @"D:\Develop\APILast\sources\Hosting\APILast.Host.Net\cmd.json"; using (var fs = new FileStream(cmdPath, FileMode.Open, FileAccess.Read)) jsonContent = new StreamReader(fs).ReadToEnd(); } var configuration = JsonConvert.DeserializeObject <NetHostConfig>(jsonContent); var libaryLoader = new LibraryLoader(configuration.Native); var me = Process.GetCurrentProcess(); var handlesInOwnProcess = libaryLoader.LoadNativeLibariesIntoProcess(me.Id); var remote = RemoteFunction.Locate(handlesInOwnProcess.ProcessHandle, handlesInOwnProcess.AssemblyResolveHandleLibHandle, "_RegisterHandler@4"); var invoker = RemoteFunction.Locate(handlesInOwnProcess.ProcessHandle, handlesInOwnProcess.CtoSharpLibHandle, "_InitAssembly@4"); var offsetforResolve = IntPtr.Subtract(remote.FunctionPointer, handlesInOwnProcess.AssemblyResolveHandleLibHandle.ToInt32()); var offsetforInvoker = IntPtr.Subtract(invoker.FunctionPointer, handlesInOwnProcess.CtoSharpLibHandle.ToInt32()); List <NativeLibaryHandles> handles = new List <NativeLibaryHandles>(); foreach (var item in configuration.Services) { var handleInRemoteProcess = libaryLoader.LoadNativeLibariesIntoProcess(item.Value); handles.Add(handleInRemoteProcess); } var remoteHandle = handles[0]; var functionPosInRemoteProcess = IntPtr.Add(remoteHandle.AssemblyResolveHandleLibHandle, offsetforResolve.ToInt32()); var moreRemote = new RemoteFunction(remoteHandle.ProcessHandle, functionPosInRemoteProcess, Encoding.ASCII); moreRemote.Execute(configuration.Native.NativeLibDirectory); var functionPosInRemoteProcess2 = IntPtr.Add(remoteHandle.CtoSharpLibHandle, offsetforInvoker.ToInt32()); var moreRemote2 = new RemoteFunction(remoteHandle.ProcessHandle, functionPosInRemoteProcess2, Encoding.ASCII); moreRemote2.Execute("SampleService;APILast.Adapter.Sample"); libaryLoader.CalculateFunctionOffsets(); // what next ? // find methods // calculate offsets // free libaries in own process // foobazen var r = configuration; }
/// <summary> /// Bind the RPC functions we'll be calling /// </summary> void BindMethods() { unitListCall = CreateAndBind <EmptyMessage, UnitList>(networkClient, "GetUnitList", "RemoteFortressReader"); creatureRawListCall = CreateAndBind <EmptyMessage, CreatureRawList>(networkClient, "GetCreatureRaws", "RemoteFortressReader"); materialListCall = CreateAndBind <EmptyMessage, MaterialList>(networkClient, "GetMaterialList", "RemoteFortressReader"); }
private void OnGUI() { if (GUILayout.Button("Read Raws")) { var client = new RemoteClient(); if (!client.Connect()) { return; } client.SuspendGame(); var getCreatureRaws = new RemoteFunction <EmptyMessage, CreatureRawList>(client, "GetCreatureRaws", "RemoteFortressReader"); var materialListCall = new RemoteFunction <EmptyMessage, MaterialList>(client, "GetMaterialList", "RemoteFortressReader"); var itemListCall = new RemoteFunction <EmptyMessage, MaterialList>(client, "GetItemList", "RemoteFortressReader"); var unitListCall = new RemoteFunction <EmptyMessage, UnitList>(client, "GetUnitList", "RemoteFortressReader"); client.ResumeGame(); creatureRaws = getCreatureRaws.Execute().creature_raws; var ExistingMatList = AssetDatabase.LoadAssetAtPath <MaterialRaws>("Assets/Resources/MaterialRaws.asset"); var ExistingItemList = AssetDatabase.LoadAssetAtPath <ItemRaws>("Assets/Resources/ItemRaws.asset"); MaterialRaws.Instance.MaterialList = materialListCall.Execute().material_list; ItemRaws.Instance.ItemList = itemListCall.Execute().material_list; units = unitListCall.Execute().creature_list; if (ExistingMatList == null) { AssetDatabase.CreateAsset(MaterialRaws.Instance, "Assets/Resources/MaterialRaws.asset"); } if (ExistingItemList == null) { AssetDatabase.CreateAsset(ItemRaws.Instance, "Assets/Resources/ItemRaws.asset"); } AssetDatabase.SaveAssets(); Debug.Log(string.Format("Pulled {0} creature raws from DF.", creatureRaws.Count)); if (MaterialCollection.Instance == null) { MaterialCollector.BuildMaterialCollection(); } MaterialCollection.Instance.PopulateMatTextures(); client.Disconnect(); //foreach (var raw in creatureRaws) //{ // raw.creature_id = BodyDefinition.GetCorrectedCreatureID(raw); //} RefilterList(); } if (creatureRaws != null) { EditorGUI.BeginChangeCheck(); filter = EditorGUILayout.TextField(filter); filterToken = EditorGUILayout.Toggle("Token", filterToken); filterName = EditorGUILayout.Toggle("Name", filterName); filterDescription = EditorGUILayout.Toggle("Description", filterDescription); filterParts = EditorGUILayout.Toggle("Parts", filterParts); bodyCategoryFilter = (CreatureBody.BodyCategory)EditorGUILayout.EnumPopup(bodyCategoryFilter); if (EditorGUI.EndChangeCheck()) { RefilterList(); } EditorGUILayout.Space(); GUILayout.BeginHorizontal(); if (GUILayout.Button("Sort by name")) { creatureRaws.Sort((x, y) => x.creature_id.CompareTo(y.creature_id)); RefilterList(); } if (GUILayout.Button("Sort by size")) { creatureRaws.Sort((x, y) => x.adultsize.CompareTo(y.adultsize)); RefilterList(); } if (GUILayout.Button("Sort by index")) { creatureRaws.Sort((x, y) => x.index.CompareTo(y.index)); RefilterList(); } GUILayout.EndHorizontal(); showRaces = EditorGUILayout.Foldout(showRaces, "Races"); if (showRaces) { raceScroll = EditorGUILayout.BeginScrollView(raceScroll); foreach (var creature in filteredRaws) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel(string.Format("{0} ({1})", creature.creature_id, creature.name[0])); EditorGUILayout.BeginVertical(); foreach (var caste in creature.caste) { if (GUILayout.Button(string.Format("{0} ({1})", caste.caste_id, caste.caste_name[0]))) { var creatureBase = new GameObject().AddComponent <CreatureBody>(); creatureBase.name = caste.caste_name[0]; creatureBase.race = creature; creatureBase.caste = caste; creatureBase.MakeBody(); Selection.SetActiveObjectWithContext(creatureBase, null); } } EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndScrollView(); if (GUILayout.Button("Dump Part Categories")) { var path = EditorUtility.SaveFilePanel("Save bodypart list", "", "Bodyparts.csv", "csv"); if (!string.IsNullOrEmpty(path)) { Dictionary <string, Dictionary <string, ChildCount> > parts = new Dictionary <string, Dictionary <string, ChildCount> >(); foreach (var creature in filteredRaws) { foreach (var caste in creature.caste) { if (bodyCategoryFilter != CreatureBody.BodyCategory.None && bodyCategoryFilter != CreatureBody.FindBodyCategory(caste)) { continue; } for (int i = 0; i < caste.body_parts.Count; i++) { var part = caste.body_parts[i]; //this is an internal part, and doesn't need modeling. if (part.flags[(int)BodyPartFlags.BodyPartRawFlags.INTERNAL]) { continue; } if (!parts.ContainsKey(part.category)) { parts[part.category] = new Dictionary <string, ChildCount>(); } Dictionary <string, int> childCounts = new Dictionary <string, int>(); foreach (var sub in caste.body_parts) { if (sub.parent != i) { continue; } if (sub.flags[(int)BodyPartFlags.BodyPartRawFlags.INTERNAL]) { continue; } if (!childCounts.ContainsKey(sub.category)) { childCounts[sub.category] = 1; } else { childCounts[sub.category]++; } } foreach (var item in childCounts) { if (!parts[part.category].ContainsKey(item.Key)) { parts[part.category][item.Key] = new ChildCount(); } if (parts[part.category][item.Key].min > item.Value) { parts[part.category][item.Key].min = item.Value; } if (parts[part.category][item.Key].max < item.Value) { parts[part.category][item.Key].max = item.Value; } } } } } using (var writer = new StreamWriter(path)) { foreach (var parent in parts) { writer.Write("\"" + parent.Key + "\","); foreach (var child in parent.Value) { writer.Write(string.Format("\"{0}\",{1},{2},", child.Key, child.Value.min, child.Value.max)); } writer.WriteLine(); } } } } if (GUILayout.Button("Place all races")) { var watch = System.Diagnostics.Stopwatch.StartNew(); CreatureBody prevCreature = null; foreach (var creature in filteredRaws) { var creatureBase = new GameObject().AddComponent <CreatureBody>(); creatureBase.name = creature.caste[0].caste_name[0]; creatureBase.race = creature; creatureBase.caste = creature.caste[0]; creatureBase.MakeBody(); if (prevCreature != null) { creatureBase.transform.position = new Vector3(prevCreature.transform.position.x + prevCreature.bounds.max.x - creatureBase.bounds.min.x, 0, 0); } prevCreature = creatureBase; } watch.Stop(); Debug.Log(string.Format("Took {0}ms to create {1} creatures, averaging {2}ms per creature.", watch.ElapsedMilliseconds, filteredRaws.Count, (float)watch.ElapsedMilliseconds / filteredRaws.Count)); } } showUnits = EditorGUILayout.Foldout(showUnits, "Units"); if (showUnits) { unitScroll = EditorGUILayout.BeginScrollView(unitScroll); foreach (var unit in units) { string name = unit.name; if (string.IsNullOrEmpty(name)) { name = creatureRaws[unit.race.mat_type].caste[unit.race.mat_index].caste_name[0]; } if (!string.IsNullOrEmpty(filter) && (filterParts || filterName)) { bool matched = false; if (filterName) { matched = name.ToUpper().Contains(filter.ToUpper()); } if (filterParts) { foreach (var item in unit.inventory) { if (!ItemRaws.Instance.ContainsKey(item.item.type)) { continue; } matched = ItemRaws.Instance[item.item.type].id.ToUpper().Contains(filter.ToUpper()); if (matched) { break; } } } if (!matched) { continue; } } if (GUILayout.Button(name)) { var creatureBase = new GameObject().AddComponent <CreatureBody>(); creatureBase.name = name; creatureBase.race = creatureRaws[unit.race.mat_type]; creatureBase.caste = creatureRaws[unit.race.mat_type].caste[unit.race.mat_index]; creatureBase.unit = unit; creatureBase.MakeBody(); creatureBase.UpdateUnit(unit); Selection.SetActiveObjectWithContext(creatureBase, null); } } EditorGUILayout.EndScrollView(); if (GUILayout.Button("Place all units")) { var watch = System.Diagnostics.Stopwatch.StartNew(); CreatureBody prevCreature = null; foreach (var unit in units) { string name = unit.name; if (string.IsNullOrEmpty(name)) { name = creatureRaws[unit.race.mat_type].caste[unit.race.mat_index].caste_name[0]; } if (!string.IsNullOrEmpty(filter) && (filterParts || filterName)) { bool matched = false; if (filterToken) { matched = creatureRaws[unit.race.mat_type].creature_id.ToUpper().Contains(filter.ToUpper()); } if (filterName) { matched = name.ToUpper().Contains(filter.ToUpper()); } if (filterParts) { foreach (var item in unit.inventory) { if (!ItemRaws.Instance.ContainsKey(item.item.type)) { continue; } matched = ItemRaws.Instance[item.item.type].id.ToUpper().Contains(filter.ToUpper()); if (matched) { break; } } } if (!matched) { continue; } } var creatureBase = new GameObject().AddComponent <CreatureBody>(); creatureBase.name = name; creatureBase.race = creatureRaws[unit.race.mat_type]; creatureBase.caste = creatureRaws[unit.race.mat_type].caste[unit.race.mat_index]; creatureBase.unit = unit; creatureBase.MakeBody(); creatureBase.UpdateUnit(unit); creatureBase.transform.localRotation = Quaternion.identity; if (prevCreature != null) { creatureBase.transform.position = new Vector3(prevCreature.transform.position.x + prevCreature.bounds.max.x - creatureBase.bounds.min.x, 0, 0); } prevCreature = creatureBase; } watch.Stop(); Debug.Log(string.Format("Took {0}ms to create {1} creatures, averaging {2}ms per creature.", watch.ElapsedMilliseconds, filteredRaws.Count, (float)watch.ElapsedMilliseconds / filteredRaws.Count)); } } } }
private void OnGUI() { if (GUILayout.Button("Read Raws")) { var client = new RemoteClient(); if (!client.Connect()) { return; } var getCreatureRaws = new RemoteFunction <EmptyMessage, CreatureRawList>(client, "GetCreatureRaws", "RemoteFortressReader"); creatureRaws = getCreatureRaws.Execute().creature_raws; Debug.Log(string.Format("Pulled {0} creature raws from DF.", creatureRaws.Count)); client.Disconnect(); creatureRaws.Sort((x, y) => x.creature_id.CompareTo(y.creature_id)); RefilterList(); } if (creatureRaws != null) { EditorGUI.BeginChangeCheck(); filter = EditorGUILayout.TextField(filter); bodyCategoryFilter = (CreatureBody.BodyCategory)EditorGUILayout.EnumPopup(bodyCategoryFilter); if (EditorGUI.EndChangeCheck()) { RefilterList(); } if (GUILayout.Button("Dump Part Categories")) { var path = EditorUtility.SaveFilePanel("Save bodypart list", "", "Bodyparts.csv", "csv"); Dictionary <string, Dictionary <string, ChildCount> > parts = new Dictionary <string, Dictionary <string, ChildCount> >(); foreach (var creature in filteredRaws) { foreach (var caste in creature.caste) { if (bodyCategoryFilter != CreatureBody.BodyCategory.None && bodyCategoryFilter != CreatureBody.FindBodyCategory(caste)) { continue; } for (int i = 0; i < caste.body_parts.Count; i++) { var part = caste.body_parts[i]; //this is an internal part, and doesn't need modeling. if (part.flags[(int)BodyPartFlags.BodyPartRawFlags.INTERNAL]) { continue; } if (!parts.ContainsKey(part.category)) { parts[part.category] = new Dictionary <string, ChildCount>(); } Dictionary <string, int> childCounts = new Dictionary <string, int>(); foreach (var sub in caste.body_parts) { if (sub.parent != i) { continue; } if (sub.flags[(int)BodyPartFlags.BodyPartRawFlags.INTERNAL]) { continue; } if (!childCounts.ContainsKey(sub.category)) { childCounts[sub.category] = 1; } else { childCounts[sub.category]++; } } foreach (var item in childCounts) { if (!parts[part.category].ContainsKey(item.Key)) { parts[part.category][item.Key] = new ChildCount(); } if (parts[part.category][item.Key].min > item.Value) { parts[part.category][item.Key].min = item.Value; } if (parts[part.category][item.Key].max < item.Value) { parts[part.category][item.Key].max = item.Value; } } } } } using (var writer = new StreamWriter(path)) { foreach (var parent in parts) { writer.Write("\"" + parent.Key + "\","); foreach (var child in parent.Value) { writer.Write(string.Format("\"{0}\",{1},{2},", child.Key, child.Value.min, child.Value.max)); } writer.WriteLine(); } } } GUILayout.BeginHorizontal(); if (GUILayout.Button("Sort by name")) { creatureRaws.Sort((x, y) => x.creature_id.CompareTo(y.creature_id)); RefilterList(); } if (GUILayout.Button("Sort by size")) { creatureRaws.Sort((x, y) => x.adultsize.CompareTo(y.adultsize)); RefilterList(); } GUILayout.EndHorizontal(); scrollPosition = GUILayout.BeginScrollView(scrollPosition); foreach (var creature in filteredRaws) { GUILayout.BeginHorizontal(); GUILayout.Label(creature.creature_id); foreach (var caste in creature.caste) { if (GUILayout.Button(caste.caste_id)) { var creatureBase = new GameObject().AddComponent <CreatureBody>(); creatureBase.name = creature.creature_id + "_" + caste.caste_id; creatureBase.race = creature; creatureBase.caste = caste; creatureBase.MakeBody(); Selection.SetActiveObjectWithContext(creatureBase, null); } } GUILayout.EndHorizontal(); } GUILayout.EndScrollView(); if (GUILayout.Button("Place all creatures")) { var watch = System.Diagnostics.Stopwatch.StartNew(); CreatureBody prevCreature = null; foreach (var creature in filteredRaws) { var creatureBase = new GameObject().AddComponent <CreatureBody>(); creatureBase.name = creature.creature_id + "_" + creature.caste[0].caste_id; creatureBase.race = creature; creatureBase.caste = creature.caste[0]; creatureBase.MakeBody(); creatureBase.transform.rotation = Quaternion.LookRotation(Vector3.back); if (prevCreature != null) { creatureBase.transform.position = new Vector3(prevCreature.transform.position.x + prevCreature.bounds.max.x - creatureBase.bounds.min.x, 0, 0); } prevCreature = creatureBase; } watch.Stop(); Debug.Log(string.Format("Took {0}ms to create {1} creatures, averaging {2}ms per creature.", watch.ElapsedMilliseconds, filteredRaws.Count, (float)watch.ElapsedMilliseconds / filteredRaws.Count)); } } }
public SecureFunction(RemoteFunction <T> _func) { func = _func; func.ReturnCallback += (f, r, i) => ReturnCallback?.Invoke(this, r, i); }