@@ -14,9 +14,6 @@ namespace CLre.API.App | |||
if (gameEngineReady != null) gameEngineReady(this, new GameReady { }); | |||
} | |||
public override IEntitiesDB entitiesDB { get; set; } | |||
public override IEntityFactory entityFactory { get; set; } | |||
public void OnFrameworkInitialized() | |||
{ | |||
// TODO framework init event | |||
@@ -33,9 +30,6 @@ namespace CLre.API.App | |||
{ | |||
} | |||
public override IEntitiesDB entitiesDB { get; set; } | |||
public override IEntityFactory entityFactory { get; set; } | |||
public void OnFrameworkInitialized() | |||
{ | |||
if (gameFrameworkReady != null) gameFrameworkReady(this, new GameReady { }); | |||
@@ -55,8 +49,5 @@ namespace CLre.API.App | |||
{ | |||
if (menuEngineReady != null) menuEngineReady(this, new MenuReady { }); | |||
} | |||
public override IEntitiesDB entitiesDB { get; set; } | |||
public override IEntityFactory entityFactory { get; set; } | |||
} | |||
} |
@@ -54,9 +54,6 @@ namespace CLre.API.Characters | |||
{ | |||
} | |||
public override IEntitiesDB entitiesDB { get; set; } | |||
public override IEntityFactory entityFactory { get; set; } | |||
public bool GetGodModeRequested() | |||
{ | |||
if (entitiesDB == null) return false; | |||
@@ -21,8 +21,8 @@ namespace CLre.API.Engines | |||
} | |||
public abstract void Ready(); | |||
public abstract IEntitiesDB entitiesDB { get; set; } | |||
public abstract IEntityFactory entityFactory { get; set; } | |||
public IEntitiesDB entitiesDB { get; set; } | |||
public IEntityFactory entityFactory { get; set; } | |||
} | |||
/// <summary> | |||
@@ -41,8 +41,8 @@ namespace CLre.API.Engines | |||
} | |||
public abstract void Ready(); | |||
public abstract IEntitiesDB entitiesDB { get; set; } | |||
public abstract IEntityFactory entityFactory { get; set; } | |||
public IEntitiesDB entitiesDB { get; set; } | |||
public IEntityFactory entityFactory { get; set; } | |||
} | |||
/// <summary> | |||
@@ -60,8 +60,8 @@ namespace CLre.API.Engines | |||
} | |||
public abstract void Ready(); | |||
public abstract IEntitiesDB entitiesDB { get; set; } | |||
public abstract IEntityFactory entityFactory { get; set; } | |||
public IEntitiesDB entitiesDB { get; set; } | |||
public IEntityFactory entityFactory { get; set; } | |||
} | |||
/// <summary> | |||
@@ -79,8 +79,8 @@ namespace CLre.API.Engines | |||
} | |||
public abstract void Ready(); | |||
public abstract IEntitiesDB entitiesDB { get; set; } | |||
public abstract IEntityFactory entityFactory { get; set; } | |||
public IEntitiesDB entitiesDB { get; set; } | |||
public IEntityFactory entityFactory { get; set; } | |||
} | |||
[HarmonyPatch(typeof(FrontEnd.MainFrontEnd), "BuildEngines")] | |||
@@ -12,8 +12,8 @@ namespace CLre.API.Engines | |||
} | |||
public abstract void Ready(); | |||
public abstract IEntitiesDB entitiesDB { get; set; } | |||
public abstract IEntityFactory entityFactory { get; set; } | |||
public IEntitiesDB entitiesDB { get; set; } | |||
public IEntityFactory entityFactory { get; set; } | |||
} | |||
public abstract class GameObsoleteEnginePostBuild : ICLreEngine | |||
@@ -24,8 +24,8 @@ namespace CLre.API.Engines | |||
} | |||
public abstract void Ready(); | |||
public abstract IEntitiesDB entitiesDB { get; set; } | |||
public abstract IEntityFactory entityFactory { get; set; } | |||
public IEntitiesDB entitiesDB { get; set; } | |||
public IEntityFactory entityFactory { get; set; } | |||
} | |||
[HarmonyPatch(typeof(GameFramework.MainLevel), "BuildDeprecatedEngines")] | |||
@@ -3,6 +3,7 @@ using CLre.API.Engines; | |||
using GameNetworkLayer.Shared; | |||
using HarmonyLib; | |||
using Svelto.ECS; | |||
using VoxelFarm.GameServer; | |||
namespace CLre.API.Synergy | |||
{ | |||
@@ -40,9 +41,6 @@ namespace CLre.API.Synergy | |||
Utility.Logging.MetaLog($"Received CLre handshake! {p}"); | |||
} | |||
public override IEntitiesDB entitiesDB { get; set; } | |||
public override IEntityFactory entityFactory { get; set; } | |||
public IEnumerator Sender(SerializedCLreHandshake payload) | |||
{ | |||
yield return null; | |||
@@ -72,12 +70,15 @@ namespace CLre.API.Synergy | |||
internal static object netMessageListener; | |||
internal static object netMessageSender; | |||
internal static TerrainModelClientServer tmcs; | |||
[HarmonyPostfix] | |||
public static void AfterMethodCall(object ____netMessageListener, object ____netMessageSender) | |||
public static void AfterMethodCall(object ____netMessageListener, object ____netMessageSender, TerrainModelClientServer ____terrainModelServerPrediction) | |||
{ | |||
netMessageListener = ____netMessageListener; | |||
netMessageSender = ____netMessageSender; | |||
tmcs = ____terrainModelServerPrediction; | |||
} | |||
} | |||
} |
@@ -54,9 +54,6 @@ namespace CLre.API.Synergy | |||
}); | |||
} | |||
public override IEntitiesDB entitiesDB { get; set; } | |||
public override IEntityFactory entityFactory { get; set; } | |||
public ClientMessagingEngine(): base() | |||
{ | |||
App.Client.GameJoin += (_, __) => { MessageSender().Run(); }; | |||
@@ -0,0 +1,75 @@ | |||
using System; | |||
using System.IO; | |||
using System.Runtime.CompilerServices; | |||
using Game.Handhelds; | |||
using NetworkFramework.Shared; | |||
using UnityEngine; | |||
namespace CLre.API.Synergy.Tweaks | |||
{ | |||
public struct SerializedCLreTerrainModifyRejection: ISerializedNetData | |||
{ | |||
public RejectionFlag Flags; | |||
public uint resourceId; | |||
public Vector3 hit; | |||
public string toolKey; | |||
public ToolModeType toolMode; | |||
public byte[] Serialize() | |||
{ | |||
using (MemoryStream stream = new MemoryStream()) | |||
{ | |||
using (BinaryWriter writer = new BinaryWriter(stream)) | |||
{ | |||
writer.Write((byte)Flags); | |||
writer.Write(resourceId); | |||
writer.Write(hit.x); | |||
writer.Write(hit.y); | |||
writer.Write(hit.z); | |||
writer.Write(toolKey); | |||
writer.Write((byte)toolMode); | |||
return stream.ToArray(); | |||
} | |||
} | |||
} | |||
public void Deserialize(byte[] data) | |||
{ | |||
using (MemoryStream stream = new MemoryStream(data)) | |||
{ | |||
using (BinaryReader reader = new BinaryReader(stream)) | |||
{ | |||
Flags = (RejectionFlag)reader.ReadByte(); | |||
resourceId = reader.ReadUInt32(); | |||
float x = reader.ReadSingle(); | |||
float y = reader.ReadSingle(); | |||
float z = reader.ReadSingle(); | |||
hit = new Vector3(x, y, z); | |||
toolKey = reader.ReadString(); | |||
toolMode = (ToolModeType)reader.ReadByte(); | |||
} | |||
} | |||
} | |||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
public bool Ok() | |||
{ | |||
return (Flags & RejectionFlag.Rejection) == RejectionFlag.None; | |||
} | |||
} | |||
[Flags] | |||
public enum RejectionFlag : byte | |||
{ | |||
None = 0, | |||
Rejection = 1, | |||
Proximity = 1 << 1, | |||
Permission = 1 << 2, | |||
AccountNotFound = 1 << 3, | |||
InitError = 1 << 4, | |||
} | |||
} |
@@ -1,9 +1,12 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Reflection; | |||
using Game.DataLoader; | |||
using GameNetworkLayer.Client; | |||
using GameNetworkLayer.Shared; | |||
using HarmonyLib; | |||
using NetworkFramework.Shared; | |||
using OpenCVForUnity; | |||
using Svelto.DataStructures; | |||
using Svelto.ECS; | |||
@@ -34,6 +37,10 @@ namespace CLre.API.Utility | |||
public delegate void INetMsgClientListener_RegisterListener<T>(NetworkDispatcherCode code, NetCBClient<T> proc) where T: struct, ISerializedNetData; | |||
public delegate void DeprecatedDispatcher_Dispatch<T>(ref T value); | |||
public delegate Dictionary<string, BaseData> IDataDB_GetValues(); | |||
// useful reflection functions | |||
public static TFuncProto BuildDelegate<TFuncProto>(MethodInfo method) where TFuncProto : Delegate | |||
{ | |||
@@ -51,6 +51,7 @@ namespace CLre | |||
Fixes.InitLogSooner.Init(); | |||
Fixes.MiniScreenHelper.Init(); | |||
Fixes.UnderStructureCollider.Init(); | |||
Fixes.TerrainModifyReset.Init(); | |||
// API init | |||
API.Synergy.ClientHandshakeEngine.Init(); | |||
@@ -106,7 +107,11 @@ namespace CLre | |||
API.App.Client.MenuReady += (_, __) => { API.Utility.Logging.MetaLog("Menu engine ready event fired!"); }; | |||
API.App.Client.GameReady += (_, __) => { API.Utility.Logging.MetaLog("Game engine ready event fired!"); }; | |||
API.App.Client.GameFrameworkReady += (_, __) => { API.Utility.Logging.MetaLog("Game framework ready event fired!"); }; | |||
API.App.Client.GameFrameworkReady += (_, __) => | |||
{ | |||
API.Utility.Logging.MetaLog("Game framework ready event fired!"); | |||
API.Utility.Logging.MetaLog($"PhotonChat Connection Protocol: {PhotonChatUI.Chat.Instance.ConnectionProtocol}"); | |||
}; | |||
API.App.Client.GameFrameworkExit += (_, __) => { API.Utility.Logging.MetaLog("Game framework exit event fired!"); }; | |||
Character c = Character.Local(); | |||
@@ -0,0 +1,244 @@ | |||
using System; | |||
using System.Reflection; | |||
using System.Runtime.CompilerServices; | |||
using CLre.API.Synergy; | |||
using CLre.API.Utility; | |||
using Game.DataLoader; | |||
using Game.Handhelds; | |||
using GameNetworkLayer.Shared; | |||
using HarmonyLib; | |||
using NetworkFramework.Shared; | |||
using Svelto.ECS; | |||
using UnityEngine; | |||
using VoxelFarm.GameServer; | |||
namespace CLre.Fixes | |||
{ | |||
[Bugfix(name = "TerrainModificationFailedHandler", | |||
description = "Actually handle TerrainModificationFailed network messages", | |||
more = "https://trello.com/c/Pq5lcB1p/23-moderation-tools", | |||
component = BugfixType.Initialiser, id = 8)] | |||
public class TerrainModifyReset | |||
{ | |||
private static TerrainModifyResetEngine _tmrEngine = null; | |||
public static void Init() | |||
{ | |||
_tmrEngine = new TerrainModifyResetEngine(); | |||
} | |||
} | |||
[Bugfix(name = "TerrainModificationFailedHandler", | |||
description = "Actually handle TerrainModificationFailed network messages", | |||
more = "https://trello.com/c/Pq5lcB1p/23-moderation-tools", | |||
component = BugfixType.Workaround, id = 8)] | |||
public class TerrainModifyResetEngine : API.Engines.GameObsoleteEnginePostBuild, IDataAccess | |||
{ | |||
private Reflection.INetMsgClientListener_RegisterListener<API.Synergy.Tweaks.SerializedCLreTerrainModifyRejection> _registerListener; | |||
public override void Ready() | |||
{ | |||
_registerListener = | |||
Reflection.MethodAsDelegate<Reflection.INetMsgClientListener_RegisterListener<API.Synergy.Tweaks.SerializedCLreTerrainModifyRejection>>( | |||
"GameNetworkLayer.Client.NetMessageClientListener:RegisterListener", | |||
generics: new [] {typeof(API.Synergy.Tweaks.SerializedCLreTerrainModifyRejection)}, | |||
instance: MainLevel_BuildClasses_Patch.netMessageListener); | |||
_registerListener(NetworkDispatcherCode.TerrainModificationFailed, OnMessageReceived); | |||
} | |||
private void OnMessageReceived(ref API.Synergy.Tweaks.SerializedCLreTerrainModifyRejection data) | |||
{ | |||
if (!data.Ok()) | |||
{ | |||
// reset terrain visuals | |||
// TODO optimise | |||
#if DEBUG | |||
API.Utility.Logging.MetaLog($"data.resourceId: {data.resourceId}"); | |||
#endif | |||
AddTerrain(ref data); | |||
} | |||
} | |||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
private static void GetTerrainRelativePosition(ref Vector3 pos) | |||
{ | |||
// This uses decompiled code from VoxelFarm.Shared.VoxelFarmGameUtils:GetTerrainRelativePosition | |||
// there's no point in calling that simple function when I have to jump through hoops with reflection | |||
// | |||
// there's also nothing particularly unique (ie copyrightable) about this code, | |||
// so the lawyers can suck it (also suing a benevolent project is a shitty move) | |||
pos.x /= 0.083333336f; | |||
pos.y /= 0.041666668f; | |||
pos.z /= 0.083333336f; | |||
} | |||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
private static void AddTerrain(ref API.Synergy.Tweaks.SerializedCLreTerrainModifyRejection data) | |||
{ | |||
// This uses decompiled code from VoxelFarm.GameServer.TerrainModelClientServer:AddTerrain | |||
// there's no point in calling that simple function when I have to jump through hoops with reflection | |||
// to supply the parameters to it | |||
// | |||
// Also this is not unique functionality, and comes from the logic of how the placement modes work | |||
switch (data.toolMode) | |||
{ | |||
case ToolModeType.Block: | |||
MainLevel_BuildClasses_Patch.tmcs.AddDisc(0, data.hit, (int)data.resourceId, 5, 5); | |||
break; | |||
case ToolModeType.Disc: | |||
MainLevel_BuildClasses_Patch.tmcs.AddDisc(0, data.hit, (int)data.resourceId, 1, 5); | |||
break; | |||
case ToolModeType.Voxel: | |||
MainLevel_BuildClasses_Patch.tmcs.AddSingleVoxel(0, data.hit, (int)data.resourceId); | |||
break; | |||
} | |||
} | |||
public IDataDB dataDB { get; set; } | |||
} | |||
[Bugfix(name = "TerrainModificationFailedHandler", | |||
description = "Actually handle TerrainModificationFailed network messages", | |||
more = "https://trello.com/c/Pq5lcB1p/23-moderation-tools", | |||
component = BugfixType.HarmonyPatch, id = 8)] | |||
[HarmonyPatch] | |||
class TerrainPendingModificationEngineClient_Add_Patch | |||
{ | |||
internal static object _terrainModifyInputNode = null; | |||
[HarmonyPrefix] | |||
public static void BeforeMethodCall(object node) | |||
{ | |||
#if DEBUG | |||
API.Utility.Logging.MetaLog("Intercepting VoxelFarm.Client.TerrainPendingModificationEngineClient:Add()"); | |||
#endif | |||
_terrainModifyInputNode = node; | |||
} | |||
[HarmonyTargetMethod] | |||
public static MethodBase Target() | |||
{ | |||
return AccessTools.Method("VoxelFarm.Client.TerrainPendingModificationEngineClient:Add", new []{ AccessTools.TypeByName("VoxelFarm.Shared.TerrainModifyInputNode")}); | |||
} | |||
} | |||
/*[Bugfix(name = "TerrainModificationFailedHandler", | |||
description = "Actually handle TerrainModificationFailed network messages", | |||
more = "https://trello.com/c/Pq5lcB1p/23-moderation-tools", | |||
component = BugfixType.HarmonyPatch, id = 8)] | |||
[HarmonyPatch] | |||
class TerrainPendingModificationEngineClient_OnBlockRemoved_Patch | |||
{ | |||
[HarmonyPrefix] | |||
public static bool BeforeMethodCall(int sender, ref ISerializedNetData terrainModifyInputData) | |||
{ | |||
#if DEBUG | |||
API.Utility.Logging.MetaLog($"Intercepting VoxelFarm.Client.TerrainPendingModificationEngineClient:OnBlockRemoved({sender}, {terrainModifyInputData})"); | |||
#endif | |||
return false; | |||
} | |||
[HarmonyTargetMethod] | |||
public static MethodBase Target() | |||
{ | |||
return AccessTools.Method("VoxelFarm.Client.TerrainPendingModificationEngineClient:OnBlockRemoved"); | |||
} | |||
}*/ | |||
[Bugfix(name = "TerrainModificationFailedHandler", | |||
description = "Actually handle TerrainModificationFailed network messages", | |||
more = "https://trello.com/c/Pq5lcB1p/23-moderation-tools", | |||
component = BugfixType.Debug, id = 8)] | |||
[HarmonyPatch] | |||
class SpadeEngine_FinishDigging_Patch | |||
{ | |||
internal static int CurrentMaterialId = 0; | |||
[HarmonyPrefix] | |||
public static void BeforeMethodCall(object toolNode, int ____currentMaterialId) | |||
{ | |||
#if DEBUG | |||
API.Utility.Logging.MetaLog($"Intercepting Game.Handhelds.SpadeEngine:FinishDigging:GetTerrainMaterial(...) material:{____currentMaterialId}"); | |||
#endif | |||
CurrentMaterialId = ____currentMaterialId; | |||
} | |||
[HarmonyTargetMethod] | |||
public static MethodBase Target() | |||
{ | |||
return AccessTools.Method("Game.Handhelds.SpadeEngine:FinishDigging"); | |||
} | |||
} | |||
[Bugfix(name = "TerrainModificationFailedHandler", | |||
description = "Actually handle TerrainModificationFailed network messages", | |||
more = "https://trello.com/c/Pq5lcB1p/23-moderation-tools", | |||
component = BugfixType.Debug, id = 8)] | |||
[HarmonyPatch] | |||
class TerrainModifyInputData_InjectValues_Patch | |||
{ | |||
[HarmonyPrefix] | |||
public static void BeforeMethodCall(ref uint resourceId) | |||
{ | |||
#if DEBUG | |||
API.Utility.Logging.MetaLog($"VoxelFarm.Shared.TerrainModifyInputData:InjectValues({resourceId}, ...)"); | |||
#endif | |||
if (resourceId == 0) resourceId = (uint) SpadeEngine_FinishDigging_Patch.CurrentMaterialId; | |||
} | |||
[HarmonyTargetMethod] | |||
public static MethodBase Target() | |||
{ | |||
return AccessTools.Method("VoxelFarm.Shared.TerrainModifyInputData:InjectValues"); | |||
} | |||
} | |||
[Bugfix(name = "TerrainModificationFailedHandler", | |||
description = "Actually handle TerrainModificationFailed network messages", | |||
more = "https://trello.com/c/Pq5lcB1p/23-moderation-tools", | |||
component = BugfixType.HarmonyPatch, id = 8)] | |||
[HarmonyPatch] | |||
class NetMessageClientListener_RegisterListener_Patch | |||
{ | |||
[HarmonyPrefix] | |||
public static bool BeforeMethodCall(NetworkDispatcherCode code) | |||
{ | |||
#if DEBUG | |||
API.Utility.Logging.MetaLog($"Intercepting GameNetworkLayer.Client.NetMessageClientListener:RegisterListener({code}, ...)"); | |||
#endif | |||
// don't allow for standard TerrainModificationFailed listener to be registered | |||
// because it's a different type and that's illegal | |||
return code != NetworkDispatcherCode.TerrainModificationFailed; | |||
} | |||
[HarmonyTargetMethod] | |||
public static MethodBase Target() | |||
{ | |||
return AccessTools.Method("GameNetworkLayer.Client.NetMessageClientListener:RegisterListener", generics: new []{ typeof(SerializedEmptyNetData)}); | |||
} | |||
} | |||
// this disables terrain destruction | |||
/*[Bugfix(name = "TerrainModificationFailedHandler", | |||
description = "Actually handle TerrainModificationFailed network messages", | |||
more = "https://trello.com/c/Pq5lcB1p/23-moderation-tools", | |||
component = BugfixType.Debug, id = 8)] | |||
[HarmonyPatch] | |||
class TerrainModificationEngineServer_RemoveTerrainInput_Patch | |||
{ | |||
[HarmonyPrefix] | |||
public static bool BeforeMethodCall(int senderPlayerId, ref ISerializedNetData data) | |||
{ | |||
#if DEBUG | |||
API.Utility.Logging.MetaLog($"Intercepting client-side GameServer.VoxelFarm.Server.TerrainModificationEngineServer:RemoveTerrainInput({senderPlayerId}, {data})"); | |||
#endif | |||
return false; | |||
} | |||
[HarmonyTargetMethod] | |||
public static MethodBase Target() | |||
{ | |||
return AccessTools.Method("GameServer.VoxelFarm.Server.TerrainModificationEngineServer:RemoveTerrainInput"); | |||
} | |||
}*/ | |||
} |
@@ -1,7 +1,9 @@ | |||
using System; | |||
using System.IO; | |||
using System.Runtime.CompilerServices; | |||
using Game.Handhelds; | |||
using NetworkFramework.Shared; | |||
using UnityEngine; | |||
namespace CLre_server.API.Synergy.Tweaks | |||
{ | |||
@@ -9,8 +11,14 @@ namespace CLre_server.API.Synergy.Tweaks | |||
{ | |||
public RejectionFlag Flags; | |||
public uint Cell; | |||
public uint resourceId; | |||
public Vector3 hit; | |||
public string toolKey; | |||
public ToolModeType toolMode; | |||
public byte[] Serialize() | |||
{ | |||
using (MemoryStream stream = new MemoryStream()) | |||
@@ -18,7 +26,12 @@ namespace CLre_server.API.Synergy.Tweaks | |||
using (BinaryWriter writer = new BinaryWriter(stream)) | |||
{ | |||
writer.Write((byte)Flags); | |||
writer.Write(Cell); | |||
writer.Write(resourceId); | |||
writer.Write(hit.x); | |||
writer.Write(hit.y); | |||
writer.Write(hit.z); | |||
writer.Write(toolKey); | |||
writer.Write((byte)toolMode); | |||
return stream.ToArray(); | |||
} | |||
} | |||
@@ -31,7 +44,13 @@ namespace CLre_server.API.Synergy.Tweaks | |||
using (BinaryReader reader = new BinaryReader(stream)) | |||
{ | |||
Flags = (RejectionFlag)reader.ReadByte(); | |||
Cell = reader.ReadUInt32(); | |||
resourceId = reader.ReadUInt32(); | |||
float x = reader.ReadSingle(); | |||
float y = reader.ReadSingle(); | |||
float z = reader.ReadSingle(); | |||
hit = new Vector3(x, y, z); | |||
toolKey = reader.ReadString(); | |||
toolMode = (ToolModeType)reader.ReadByte(); | |||
} | |||
} | |||
} | |||
@@ -51,5 +51,21 @@ namespace CLre_server.API.Tools | |||
} | |||
} | |||
} | |||
[HarmonyPatch(typeof(AccessTools), "Method", | |||
new Type[] {typeof(Type), typeof(string), typeof(Type[]), typeof(Type[])})] | |||
class AccessTools_Method2_Patch | |||
{ | |||
[HarmonyPostfix] | |||
public static void AfterMethodCall(MethodInfo __result, Type type, string name) | |||
{ | |||
if (!AccessToolsWarnings.isEnabled) return; | |||
if (__result == null) | |||
{ | |||
var method = (new StackTrace()).GetFrame(2).GetMethod(); | |||
Utility.Logging.LogWarning($"[{method.DeclaringType.FullName}.{method.Name}] AccessTools.Method(\"{type}\", \"{name}\") returned null result"); | |||
} | |||
} | |||
} | |||
} | |||
#endif |
@@ -1,5 +1,7 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Reflection; | |||
using Game.DataLoader; | |||
using GameNetworkLayer.Shared; | |||
using HarmonyLib; | |||
using NetworkFramework.Shared; | |||
@@ -33,7 +35,8 @@ namespace CLre_server.API.Utility | |||
public delegate void INetMsgServerListener_RegisterListener<T>(NetworkDispatcherCode code, NetCBServer<T> proc) where T: struct, ISerializedNetData; | |||
public delegate Dictionary<string, BaseData> IDataDB_GetValues(); | |||
// useful reflection functions | |||
public static TFuncProto BuildDelegate<TFuncProto>(MethodInfo method) where TFuncProto : Delegate | |||
{ | |||
@@ -4,6 +4,7 @@ using System.Collections.Generic; | |||
using System.Reflection; | |||
using System.Runtime.CompilerServices; | |||
using CLre_server.API.Synergy.Tweaks; | |||
using CLre_server.API.Utility; | |||
using Game.DataLoader; | |||
using GameNetworkLayer.Shared; | |||
using HarmonyLib; | |||
@@ -12,6 +13,7 @@ using Svelto.DataStructures; | |||
using Svelto.ECS; | |||
using UnityEngine; | |||
using User.Server; | |||
using voxelfarm; | |||
namespace CLre_server.Tweaks | |||
{ | |||
@@ -104,8 +106,6 @@ namespace CLre_server.Tweaks | |||
#endif | |||
if (isPointInAABB) | |||
{ | |||
result.Cell = item; | |||
if (!isOwner) | |||
{ | |||
result.Flags = RejectionFlag.Proximity | |||
@@ -154,19 +154,24 @@ namespace CLre_server.Tweaks | |||
[HarmonyPatch] | |||
class TerrainModificationEngineServer_RemoveTerrainInput_Patch | |||
{ | |||
private static API.Utility.Reflection.INetMsgServerSender_SendMessage<SerializedCLreTerrainModifyRejection> | |||
_netMessageSend = null; | |||
private static object _netMsgServerSender; | |||
// reflection caching | |||
private static API.Utility.Reflection.INetMsgServerSender_SendMessage<SerializedCLreTerrainModifyRejection> | |||
_netMessageSend_CLre = null; | |||
[HarmonyPrefix] | |||
public static bool BeforeMethodCall(int senderPlayerId, ref ISerializedNetData data, object ____netMsgServerSender) | |||
{ | |||
if (!CLre.Config.terrain_exclusion_zone) return true; | |||
if (_netMessageSend == null) | |||
_netMsgServerSender = ____netMsgServerSender; | |||
if (_netMessageSend_CLre == null) | |||
{ | |||
// cache reflection operations on first run | |||
#if DEBUG | |||
API.Utility.Logging.MetaLog("Building SendMessage delegate optimisation"); | |||
#endif | |||
_netMessageSend = API.Utility.Reflection | |||
_netMessageSend_CLre = API.Utility.Reflection | |||
.MethodAsDelegate< | |||
API.Utility.Reflection.INetMsgServerSender_SendMessage<SerializedCLreTerrainModifyRejection> | |||
>( | |||
@@ -185,12 +190,34 @@ namespace CLre_server.Tweaks | |||
#if DEBUG | |||
API.Utility.Logging.MetaLog("Rejecting terrain modification"); | |||
#endif | |||
// TODO optimize | |||
Traverse tmid = Traverse.Create(data); | |||
modifyPayload.resourceId = tmid.Property<uint>("resourceId").Value; | |||
modifyPayload.hit = location; | |||
//modifyPayload.materialIndex = tmid.Property<int>("materialIndex").Value; | |||
modifyPayload.toolKey = tmid.Property<string>("toolKey").Value; | |||
modifyPayload.toolMode = tmid.Property<Game.Handhelds.ToolModeType>("toolMode").Value; | |||
switch (modifyPayload.toolMode) | |||
{ | |||
case Game.Handhelds.ToolModeType.Block: | |||
modifyPayload.hit.y -= 0.125f * 2; // each layer is 0.125 thick, block is 3 layers | |||
break; | |||
case Game.Handhelds.ToolModeType.Disc: | |||
break; | |||
case Game.Handhelds.ToolModeType.Voxel: | |||
modifyPayload.toolMode = Game.Handhelds.ToolModeType.Disc; // voxels aren't replaced properly | |||
break; | |||
} | |||
// signal client that stuff failed | |||
_netMessageSend(NetworkDispatcherCode.TerrainModificationFailed, ref modifyPayload, senderPlayerId); | |||
_netMessageSend_CLre(NetworkDispatcherCode.TerrainModificationFailed, ref modifyPayload, senderPlayerId); | |||
// build terrain data for terrain replacement | |||
#if DEBUG | |||
API.Utility.Logging.MetaLog("Filling hole left by terrain modification"); | |||
#endif | |||
} | |||
return modifyPayload.Ok(); | |||
} | |||
[HarmonyTargetMethod] | |||
public static MethodBase Target() | |||
{ | |||