diff --git a/NebulaModel/Packets/Factory/Foundation/VeinPosUpdatePacket.cs b/NebulaModel/Packets/Factory/Foundation/VeinPosUpdatePacket.cs new file mode 100644 index 000000000..2e96dfc37 --- /dev/null +++ b/NebulaModel/Packets/Factory/Foundation/VeinPosUpdatePacket.cs @@ -0,0 +1,20 @@ +using NebulaAPI.DataStructures; +using UnityEngine; + +namespace NebulaModel.Packets.Factory.Foundation; + +public class VeinPosUpdatePacket +{ + public VeinPosUpdatePacket() { } + + public VeinPosUpdatePacket(int planetId, int veinId, Vector3 pos) + { + PlanetId = planetId; + VeinId = veinId; + Pos = new Float3(pos); + } + + public int PlanetId { get; set; } + public int VeinId { get; set; } + public Float3 Pos { get; set; } +} diff --git a/NebulaNetwork/PacketProcessors/Factory/Foundation/VeinPosUpdateProcessor.cs b/NebulaNetwork/PacketProcessors/Factory/Foundation/VeinPosUpdateProcessor.cs new file mode 100644 index 000000000..2a80a1470 --- /dev/null +++ b/NebulaNetwork/PacketProcessors/Factory/Foundation/VeinPosUpdateProcessor.cs @@ -0,0 +1,61 @@ +#region + +using NebulaAPI.DataStructures; +using NebulaAPI.Packets; +using NebulaModel.Networking; +using NebulaModel.Packets; +using NebulaModel.Packets.Factory.Foundation; +using NebulaWorld; +using UnityEngine; + +#endregion + +namespace NebulaNetwork.PacketProcessors.Factory.Foundation; + +[RegisterPacketProcessor] +internal class VeinPosUpdateProcessor : PacketProcessor +{ + protected override void ProcessPacket(VeinPosUpdatePacket packet, NebulaConnection conn) + { + var planet = GameMain.galaxy.PlanetById(packet.PlanetId); + if (planet?.factory == null) + { + return; + } + + var pos = packet.Pos.ToVector3(); + ref var veinData = ref planet.factory.veinPool[packet.VeinId]; + veinData.pos = pos; + if (planet != GameMain.localPlanet) + { + return; + } + + // Update GPU models on the local planet + var rot = Maths.SphericalRotation(pos, Random.value * 360f); + GameMain.gpuiManager.AlterModel(veinData.modelIndex, veinData.modelId, packet.VeinId, pos, rot, false); + var veinProto = LDB.veins.Select((int)veinData.type); + if (veinProto != null) + { + var magnitude = pos.magnitude; + var normalVector = pos / magnitude; + if (veinData.minerId0 > 0) + { + GameMain.gpuiManager.AlterModel(veinProto.MinerBaseModelIndex, veinData.minerBaseModelId, veinData.minerId0, normalVector * (magnitude + 0.1f), false); + GameMain.gpuiManager.AlterModel(veinProto.MinerCircleModelIndex, veinData.minerCircleModelId0, veinData.minerId0, normalVector * (magnitude + 0.4f), false); + } + if (veinData.minerId1 > 0) + { + GameMain.gpuiManager.AlterModel(veinProto.MinerCircleModelIndex, veinData.minerCircleModelId1, veinData.minerId1, normalVector * (magnitude + 0.6f), false); + } + if (veinData.minerId2 > 0) + { + GameMain.gpuiManager.AlterModel(veinProto.MinerCircleModelIndex, veinData.minerCircleModelId2, veinData.minerId2, normalVector * (magnitude + 0.8f), false); + } + if (veinData.minerId3 > 0) + { + GameMain.gpuiManager.AlterModel(veinProto.MinerCircleModelIndex, veinData.minerCircleModelId3, veinData.minerId3, normalVector * (magnitude + 1f), false); + } + } + } +} diff --git a/NebulaPatcher/Patches/Transpilers/PlanetFactory_Transpiler.cs b/NebulaPatcher/Patches/Transpilers/PlanetFactory_Transpiler.cs index edfb6f8c5..4f04bbd09 100644 --- a/NebulaPatcher/Patches/Transpilers/PlanetFactory_Transpiler.cs +++ b/NebulaPatcher/Patches/Transpilers/PlanetFactory_Transpiler.cs @@ -8,6 +8,7 @@ using HarmonyLib; using NebulaModel.Logger; using NebulaModel.Packets.Factory.Belt; +using NebulaModel.Packets.Factory.Foundation; using NebulaModel.Packets.Factory.Inserter; using NebulaWorld; using UnityEngine; @@ -257,4 +258,55 @@ public static IEnumerable AddPrebuildDataWithComponents_Transpi return instructions; } } + + [HarmonyTranspiler] + [HarmonyPatch(nameof(PlanetFactory.FlattenTerrainReform))] + public static IEnumerable FlattenTerrainReform_Transpiler(IEnumerable instructions) + { + try + { + /* Broadcast the change of vein pos to other players, because nearColliderLogic is just dummy placeholder on remote planets (PlanetTimer) + + Replace: this.veinPool[num18].pos = vector.normalized * num21; + To: SetVeinPos(this, num18, vector.normalized * num21); + */ + var matcher = new CodeMatcher(instructions) + .MatchForward(false, + new CodeMatch(OpCodes.Ldarg_0), + new CodeMatch(i => i.opcode == OpCodes.Ldfld && ((FieldInfo)i.operand).Name == "veinPool"), // =>Nop + new CodeMatch(OpCodes.Ldloc_S), + new CodeMatch(OpCodes.Ldelema), // =>Nop + new CodeMatch(OpCodes.Ldloca_S), + new CodeMatch(OpCodes.Call), + new CodeMatch(OpCodes.Ldloc_S), + new CodeMatch(OpCodes.Call), + new CodeMatch(i => i.opcode == OpCodes.Stfld && ((FieldInfo)i.operand).Name == "pos") // =>SetVeinPos + ) + .Advance(1) + .SetAndAdvance(OpCodes.Nop, null) + .Advance(1) + .SetAndAdvance(OpCodes.Nop, null) + .Advance(4) + .SetAndAdvance(OpCodes.Call, AccessTools.Method(typeof(PlanetFactory_Transpiler), nameof(SetVeinPos))); + + return matcher.InstructionEnumeration(); + } + catch (Exception e) + { + Log.Error("Transpiler PlanetFactory.FlattenTerrainReform error! Burry vein will not sync"); + Log.Error(e); + return instructions; + } + } + + private static void SetVeinPos(PlanetFactory factory, int veinId, Vector3 pos) + { + var oldVeinPos = factory.veinPool[veinId].pos; + factory.veinPool[veinId].pos = pos; + + if (Multiplayer.IsActive && (oldVeinPos - pos).magnitude > 0.01f) + { + Multiplayer.Session.Network.SendPacketToLocalStar(new VeinPosUpdatePacket(factory.planetId, veinId, pos)); + } + } }