Unofficial CardLife revival project, pronounced like "celery"
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

244 lines
9.8KB

  1. using System;
  2. using System.Reflection;
  3. using System.Runtime.CompilerServices;
  4. using CLre.API.Synergy;
  5. using CLre.API.Utility;
  6. using Game.DataLoader;
  7. using Game.Handhelds;
  8. using GameNetworkLayer.Shared;
  9. using HarmonyLib;
  10. using NetworkFramework.Shared;
  11. using Svelto.ECS;
  12. using UnityEngine;
  13. using VoxelFarm.GameServer;
  14. namespace CLre.Fixes
  15. {
  16. [Bugfix(name = "TerrainModificationFailedHandler",
  17. description = "Actually handle TerrainModificationFailed network messages",
  18. more = "https://trello.com/c/Pq5lcB1p/23-moderation-tools",
  19. component = BugfixType.Initialiser, id = 8)]
  20. public class TerrainModifyReset
  21. {
  22. private static TerrainModifyResetEngine _tmrEngine = null;
  23. public static void Init()
  24. {
  25. _tmrEngine = new TerrainModifyResetEngine();
  26. }
  27. }
  28. [Bugfix(name = "TerrainModificationFailedHandler",
  29. description = "Actually handle TerrainModificationFailed network messages",
  30. more = "https://trello.com/c/Pq5lcB1p/23-moderation-tools",
  31. component = BugfixType.Workaround, id = 8)]
  32. public class TerrainModifyResetEngine : API.Engines.GameObsoleteEnginePostBuild, IDataAccess
  33. {
  34. private Reflection.INetMsgClientListener_RegisterListener<API.Synergy.Tweaks.SerializedCLreTerrainModifyRejection> _registerListener;
  35. public override void Ready()
  36. {
  37. _registerListener =
  38. Reflection.MethodAsDelegate<Reflection.INetMsgClientListener_RegisterListener<API.Synergy.Tweaks.SerializedCLreTerrainModifyRejection>>(
  39. "GameNetworkLayer.Client.NetMessageClientListener:RegisterListener",
  40. generics: new [] {typeof(API.Synergy.Tweaks.SerializedCLreTerrainModifyRejection)},
  41. instance: MainLevel_BuildClasses_Patch.netMessageListener);
  42. _registerListener(NetworkDispatcherCode.TerrainModificationFailed, OnMessageReceived);
  43. }
  44. private void OnMessageReceived(ref API.Synergy.Tweaks.SerializedCLreTerrainModifyRejection data)
  45. {
  46. if (!data.Ok())
  47. {
  48. // reset terrain visuals
  49. // TODO optimise
  50. #if DEBUG
  51. API.Utility.Logging.MetaLog($"data.resourceId: {data.resourceId}");
  52. #endif
  53. AddTerrain(ref data);
  54. }
  55. }
  56. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  57. private static void GetTerrainRelativePosition(ref Vector3 pos)
  58. {
  59. // This uses decompiled code from VoxelFarm.Shared.VoxelFarmGameUtils:GetTerrainRelativePosition
  60. // there's no point in calling that simple function when I have to jump through hoops with reflection
  61. //
  62. // there's also nothing particularly unique (ie copyrightable) about this code,
  63. // so the lawyers can suck it (also suing a benevolent project is a shitty move)
  64. pos.x /= 0.083333336f;
  65. pos.y /= 0.041666668f;
  66. pos.z /= 0.083333336f;
  67. }
  68. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  69. private static void AddTerrain(ref API.Synergy.Tweaks.SerializedCLreTerrainModifyRejection data)
  70. {
  71. // This uses decompiled code from VoxelFarm.GameServer.TerrainModelClientServer:AddTerrain
  72. // there's no point in calling that simple function when I have to jump through hoops with reflection
  73. // to supply the parameters to it
  74. //
  75. // Also this is not unique functionality, and comes from the logic of how the placement modes work
  76. switch (data.toolMode)
  77. {
  78. case ToolModeType.Block:
  79. MainLevel_BuildClasses_Patch.tmcs.AddDisc(0, data.hit, (int)data.resourceId, 5, 5);
  80. break;
  81. case ToolModeType.Disc:
  82. MainLevel_BuildClasses_Patch.tmcs.AddDisc(0, data.hit, (int)data.resourceId, 1, 5);
  83. break;
  84. case ToolModeType.Voxel:
  85. MainLevel_BuildClasses_Patch.tmcs.AddSingleVoxel(0, data.hit, (int)data.resourceId);
  86. break;
  87. }
  88. }
  89. public IDataDB dataDB { get; set; }
  90. }
  91. [Bugfix(name = "TerrainModificationFailedHandler",
  92. description = "Actually handle TerrainModificationFailed network messages",
  93. more = "https://trello.com/c/Pq5lcB1p/23-moderation-tools",
  94. component = BugfixType.HarmonyPatch, id = 8)]
  95. [HarmonyPatch]
  96. class TerrainPendingModificationEngineClient_Add_Patch
  97. {
  98. internal static object _terrainModifyInputNode = null;
  99. [HarmonyPrefix]
  100. public static void BeforeMethodCall(object node)
  101. {
  102. #if DEBUG
  103. API.Utility.Logging.MetaLog("Intercepting VoxelFarm.Client.TerrainPendingModificationEngineClient:Add()");
  104. #endif
  105. _terrainModifyInputNode = node;
  106. }
  107. [HarmonyTargetMethod]
  108. public static MethodBase Target()
  109. {
  110. return AccessTools.Method("VoxelFarm.Client.TerrainPendingModificationEngineClient:Add", new []{ AccessTools.TypeByName("VoxelFarm.Shared.TerrainModifyInputNode")});
  111. }
  112. }
  113. /*[Bugfix(name = "TerrainModificationFailedHandler",
  114. description = "Actually handle TerrainModificationFailed network messages",
  115. more = "https://trello.com/c/Pq5lcB1p/23-moderation-tools",
  116. component = BugfixType.HarmonyPatch, id = 8)]
  117. [HarmonyPatch]
  118. class TerrainPendingModificationEngineClient_OnBlockRemoved_Patch
  119. {
  120. [HarmonyPrefix]
  121. public static bool BeforeMethodCall(int sender, ref ISerializedNetData terrainModifyInputData)
  122. {
  123. #if DEBUG
  124. API.Utility.Logging.MetaLog($"Intercepting VoxelFarm.Client.TerrainPendingModificationEngineClient:OnBlockRemoved({sender}, {terrainModifyInputData})");
  125. #endif
  126. return false;
  127. }
  128. [HarmonyTargetMethod]
  129. public static MethodBase Target()
  130. {
  131. return AccessTools.Method("VoxelFarm.Client.TerrainPendingModificationEngineClient:OnBlockRemoved");
  132. }
  133. }*/
  134. [Bugfix(name = "TerrainModificationFailedHandler",
  135. description = "Actually handle TerrainModificationFailed network messages",
  136. more = "https://trello.com/c/Pq5lcB1p/23-moderation-tools",
  137. component = BugfixType.Debug, id = 8)]
  138. [HarmonyPatch]
  139. class SpadeEngine_FinishDigging_Patch
  140. {
  141. internal static int CurrentMaterialId = 0;
  142. [HarmonyPrefix]
  143. public static void BeforeMethodCall(object toolNode, int ____currentMaterialId)
  144. {
  145. #if DEBUG
  146. API.Utility.Logging.MetaLog($"Intercepting Game.Handhelds.SpadeEngine:FinishDigging:GetTerrainMaterial(...) material:{____currentMaterialId}");
  147. #endif
  148. CurrentMaterialId = ____currentMaterialId;
  149. }
  150. [HarmonyTargetMethod]
  151. public static MethodBase Target()
  152. {
  153. return AccessTools.Method("Game.Handhelds.SpadeEngine:FinishDigging");
  154. }
  155. }
  156. [Bugfix(name = "TerrainModificationFailedHandler",
  157. description = "Actually handle TerrainModificationFailed network messages",
  158. more = "https://trello.com/c/Pq5lcB1p/23-moderation-tools",
  159. component = BugfixType.Debug, id = 8)]
  160. [HarmonyPatch]
  161. class TerrainModifyInputData_InjectValues_Patch
  162. {
  163. [HarmonyPrefix]
  164. public static void BeforeMethodCall(ref uint resourceId)
  165. {
  166. #if DEBUG
  167. API.Utility.Logging.MetaLog($"VoxelFarm.Shared.TerrainModifyInputData:InjectValues({resourceId}, ...)");
  168. #endif
  169. if (resourceId == 0) resourceId = (uint) SpadeEngine_FinishDigging_Patch.CurrentMaterialId;
  170. }
  171. [HarmonyTargetMethod]
  172. public static MethodBase Target()
  173. {
  174. return AccessTools.Method("VoxelFarm.Shared.TerrainModifyInputData:InjectValues");
  175. }
  176. }
  177. [Bugfix(name = "TerrainModificationFailedHandler",
  178. description = "Actually handle TerrainModificationFailed network messages",
  179. more = "https://trello.com/c/Pq5lcB1p/23-moderation-tools",
  180. component = BugfixType.HarmonyPatch, id = 8)]
  181. [HarmonyPatch]
  182. class NetMessageClientListener_RegisterListener_Patch
  183. {
  184. [HarmonyPrefix]
  185. public static bool BeforeMethodCall(NetworkDispatcherCode code)
  186. {
  187. #if DEBUG
  188. API.Utility.Logging.MetaLog($"Intercepting GameNetworkLayer.Client.NetMessageClientListener:RegisterListener({code}, ...)");
  189. #endif
  190. // don't allow for standard TerrainModificationFailed listener to be registered
  191. // because it's a different type and that's illegal
  192. return code != NetworkDispatcherCode.TerrainModificationFailed;
  193. }
  194. [HarmonyTargetMethod]
  195. public static MethodBase Target()
  196. {
  197. return AccessTools.Method("GameNetworkLayer.Client.NetMessageClientListener:RegisterListener", generics: new []{ typeof(SerializedEmptyNetData)});
  198. }
  199. }
  200. // this disables terrain destruction
  201. /*[Bugfix(name = "TerrainModificationFailedHandler",
  202. description = "Actually handle TerrainModificationFailed network messages",
  203. more = "https://trello.com/c/Pq5lcB1p/23-moderation-tools",
  204. component = BugfixType.Debug, id = 8)]
  205. [HarmonyPatch]
  206. class TerrainModificationEngineServer_RemoveTerrainInput_Patch
  207. {
  208. [HarmonyPrefix]
  209. public static bool BeforeMethodCall(int senderPlayerId, ref ISerializedNetData data)
  210. {
  211. #if DEBUG
  212. API.Utility.Logging.MetaLog($"Intercepting client-side GameServer.VoxelFarm.Server.TerrainModificationEngineServer:RemoveTerrainInput({senderPlayerId}, {data})");
  213. #endif
  214. return false;
  215. }
  216. [HarmonyTargetMethod]
  217. public static MethodBase Target()
  218. {
  219. return AccessTools.Method("GameServer.VoxelFarm.Server.TerrainModificationEngineServer:RemoveTerrainInput");
  220. }
  221. }*/
  222. }