diff --git a/README.md b/README.md index b750f06..eaae9a1 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ # srmp-public -This is the code for the Slime Rancher MultiPlayer Mod (SRMP). +Currently working on going through the code, adding notes and fixing some of the bugs in my free time. +I adore this mod and want to give both credit and a huge thank you to Saty for the origional creation of the mod. -The suer manual can be found [here](/manual.md). + +I am slowly working my way through the list of bugs as seen below. -## Bug Status +# Bug Status Notes: Bug list compiled from last known bug list of version 1488 FIXED: - Multiplayer window doesn't show up on resolutions < 1920x1080 - -IN PROGRESS (NEEDS MORE TESTING): - Exchange sometimes skips rewards if multiple players put items in at the same time - Exchange chest disappears without rewards @@ -30,20 +30,14 @@ Known Bugs: - Upgrades sometimes does not get applied to All players -##Current Status -@Twirlbug -- Currently working on going through the code, adding notes and fixing some of the bugs in my free time. -- I adore this mod and want to give both credit and a huge thank you to Saty for the origional creation of the mod. -I am slowly working my way through the list of bugs as seen above. - -###Notation Status -Files in the following folders still need more notation: + #Notes Status +Files in the following folders still need notes: - Networking - Packets - Patches - --------------------------------------------------------------------------------- -##Origional File From SatyPardus + +Origional File From SatyPardus It's bad. It's really really bad. diff --git a/SRMP/Console/SRMPConsole.cs b/SRMP/Console/SRMPConsole.cs index 185267f..d309f3a 100644 --- a/SRMP/Console/SRMPConsole.cs +++ b/SRMP/Console/SRMPConsole.cs @@ -290,6 +290,7 @@ namespace SRMultiplayer //mark target transform location PacketPlayerPosition packet = null; + string destSummary = ""; //first check distination switch (destination.ToLower()) @@ -304,7 +305,7 @@ namespace SRMultiplayer RegionSet = (byte)home.GetRegionSetId() }; - + destSummary = "Home"; break; default: //check for a player name var play = Globals.Players.Values.FirstOrDefault(p => p.Username.Equals(destination, StringComparison.CurrentCultureIgnoreCase)); @@ -320,7 +321,7 @@ namespace SRMultiplayer Rotation = play.transform.eulerAngles.y, RegionSet = (byte)play.CurrentRegionSet }; - + destSummary = play.Username; break; } @@ -346,10 +347,12 @@ namespace SRMultiplayer return; } + ConsoleLog("Teleporting " + targetPlayer.Username + " to " + destSummary); if (!targetPlayer.IsLocal) { //if a target is located and is not the local player send the teleport command + packet.ID = targetPlayer.ID; packet.WeaponY = targetPlayer.GetWeaponLocation(); packet.Send(); return; @@ -361,6 +364,8 @@ namespace SRMultiplayer SRSingleton.Instance.player.transform.position = packet.Position; SRSingleton.Instance.player.transform.eulerAngles = new Vector3(0, packet.Rotation, 0); SRSingleton.Instance.PlayerState.model.SetCurrRegionSet((RegionRegistry.RegionSetId)packet.RegionSet); + // play the teleport animation + SRSingleton.Instance.PlayTeleport(); } } diff --git a/SRMP/Networking/Communication/NetworkHandlerClient.cs b/SRMP/Networking/Communication/NetworkHandlerClient.cs index 2514e65..29a5fa7 100644 --- a/SRMP/Networking/Communication/NetworkHandlerClient.cs +++ b/SRMP/Networking/Communication/NetworkHandlerClient.cs @@ -1,15 +1,12 @@ using DG.Tweening; using Lidgren.Network; using MonomiPark.SlimeRancher.DataModel; -using MonomiPark.SlimeRancher.Persist; using MonomiPark.SlimeRancher.Regions; using SRMultiplayer.Packets; using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; -using System.Threading.Tasks; using UnityEngine; namespace SRMultiplayer.Networking @@ -30,7 +27,7 @@ namespace SRMultiplayer.Networking case PacketType.PlayerJoined: OnPlayerJoined(new PacketPlayerJoined(im)); break; case PacketType.PlayerLeft: OnPlayerLeft(new PacketPlayerLeft(im)); break; case PacketType.PlayerLoaded: OnPlayerLoaded(new PacketPlayerLoaded(im)); break; - case PacketType.PlayerPosition: OnPlayerPosition(new PacketPlayerPosition(im)); break; + case PacketType.PlayerPosition: OnPlayerPosition(new PacketPlayerPosition(im)); break; case PacketType.PlayerFX: OnPlayerFX(new PacketPlayerFX(im)); break; case PacketType.PlayerCurrency: OnPlayerCurrency(new PacketPlayerCurrency(im)); break; case PacketType.PlayerCurrencyDisplay: OnPlayerCurrencyDisplay(new PacketPlayerCurrencyDisplay(im)); break; @@ -151,7 +148,7 @@ namespace SRMultiplayer.Networking // Race case PacketType.RaceActivate: OnRaceActivate(new PacketRaceActivate(im)); break; case PacketType.RaceEnd: OnRaceEnd(new PacketRaceEnd(im)); break; - case PacketType.RaceTime: OnRaceTime(new PacketRaceTime(im)); break; + case PacketType.RaceTime: OnRaceTime(new PacketRaceTime(im)); break; case PacketType.RaceTrigger: OnRaceTrigger(new PacketRaceTrigger(im)); break; default: SRMP.Log($"Got unhandled packet: {type} " + Enum.GetName(typeof(PacketType), type)); @@ -372,7 +369,7 @@ namespace SRMultiplayer.Networking //send off fireworks SRBehaviour.InstantiateDynamic(eject.awardFX, eject.awardAt.position, eject.awardAt.rotation); } - + //dont clear out the offer yet, we arent done with it //SRSingleton.Instance.ExchangeDirector.ClearOffer(type); } @@ -383,7 +380,7 @@ namespace SRMultiplayer.Networking } } } - private static void OnExchangePrepareDaily(PacketExchangePrepareDaily packet) + private static void OnExchangePrepareDaily(PacketExchangePrepareDaily packet) { SRSingleton.Instance.ExchangeDirector.worldModel.pendingOfferRancherIds = packet.pendingOfferRancherIds; SRSingleton.Instance.ExchangeDirector.OfferDidChange(); @@ -1940,7 +1937,9 @@ namespace SRMultiplayer.Networking if(type == PacketPlayerAnimation.AnimationType.Speed) player.ReadAnimatorSpeed(packet.internalData); else if (type == PacketPlayerAnimation.AnimationType.Parameters) + { player.ReadParameters(packet.internalData); + } else player.ReadAnimatorLayer(packet.internalData); } @@ -1954,59 +1953,74 @@ namespace SRMultiplayer.Networking { if (player.IsLocal) { - var euler = SRSingleton.Instance.player.GetComponentInChildren().transform.eulerAngles; - euler.x = packet.WeaponY; - SRSingleton.Instance.player.GetComponentInChildren().transform.eulerAngles = euler; - SRSingleton.Instance.player.transform.position = packet.Position; - SRSingleton.Instance.player.transform.eulerAngles = new Vector3(0, packet.Rotation, 0); - SRSingleton.Instance.PlayerState.model.SetCurrRegionSet((RegionRegistry.RegionSetId)packet.RegionSet); - - - //only reload inventory if this is a load up packet and NOT a tp packet - if (!Globals.IsServer && packet.OnLoad) + if (packet.OnLoad) { - try + + var euler = SRSingleton.Instance.player.GetComponentInChildren().transform.eulerAngles; + euler.x = packet.WeaponY; + SRSingleton.Instance.player.GetComponentInChildren().transform.eulerAngles = euler; + SRSingleton.Instance.player.transform.position = packet.Position; + SRSingleton.Instance.player.transform.eulerAngles = new Vector3(0, packet.Rotation, 0); + SRSingleton.Instance.PlayerState.model.SetCurrRegionSet((RegionRegistry.RegionSetId)packet.RegionSet); + + + //only reload inventory if this is a load up packet and NOT a tp packet + if (!Globals.IsServer) { - using (FileStream file = new FileStream(Path.Combine(SRMP.ModDataPath, Globals.CurrentGameName + ".player"), FileMode.Open)) + try { - using (BinaryReader reader = new BinaryReader(file)) + using (FileStream file = new FileStream(Path.Combine(SRMP.ModDataPath, Globals.CurrentGameName + ".player"), FileMode.Open)) { - Debug.Log($"Loading {Path.Combine(SRMP.ModDataPath, Globals.CurrentGameName + ".player")}"); - var ammoCount = reader.ReadInt32(); - for (int i = 0; i < ammoCount; i++) + using (BinaryReader reader = new BinaryReader(file)) { - var state = (PlayerState.AmmoMode)reader.ReadByte(); - SRSingleton.Instance.PlayerState.model.ammoDict[state].usableSlots = reader.ReadInt32(); - var slotCount = reader.ReadInt32(); - SRSingleton.Instance.PlayerState.model.ammoDict[state].slots = new Ammo.Slot[slotCount]; - for (int j = 0; j < slotCount; j++) + Debug.Log($"Loading {Path.Combine(SRMP.ModDataPath, Globals.CurrentGameName + ".player")}"); + var ammoCount = reader.ReadInt32(); + for (int i = 0; i < ammoCount; i++) { - if (reader.ReadBoolean()) + var state = (PlayerState.AmmoMode)reader.ReadByte(); + SRSingleton.Instance.PlayerState.model.ammoDict[state].usableSlots = reader.ReadInt32(); + var slotCount = reader.ReadInt32(); + SRSingleton.Instance.PlayerState.model.ammoDict[state].slots = new Ammo.Slot[slotCount]; + for (int j = 0; j < slotCount; j++) { - SRSingleton.Instance.PlayerState.model.ammoDict[state].slots[j] = new Ammo.Slot((Identifiable.Id)reader.ReadUInt16(), reader.ReadInt32()); if (reader.ReadBoolean()) { - SRSingleton.Instance.PlayerState.model.ammoDict[state].slots[j].emotions = new SlimeEmotionData(); - var emotionCount = reader.ReadInt32(); - for (int k = 0; k < emotionCount; k++) + SRSingleton.Instance.PlayerState.model.ammoDict[state].slots[j] = new Ammo.Slot((Identifiable.Id)reader.ReadUInt16(), reader.ReadInt32()); + if (reader.ReadBoolean()) { - SRSingleton.Instance.PlayerState.model.ammoDict[state].slots[j].emotions.Add((SlimeEmotions.Emotion)reader.ReadUInt16(), reader.ReadSingle()); + SRSingleton.Instance.PlayerState.model.ammoDict[state].slots[j].emotions = new SlimeEmotionData(); + var emotionCount = reader.ReadInt32(); + for (int k = 0; k < emotionCount; k++) + { + SRSingleton.Instance.PlayerState.model.ammoDict[state].slots[j].emotions.Add((SlimeEmotions.Emotion)reader.ReadUInt16(), reader.ReadSingle()); + } } } - } - else - { - SRSingleton.Instance.PlayerState.model.ammoDict[state].slots[j] = null; + else + { + SRSingleton.Instance.PlayerState.model.ammoDict[state].slots[j] = null; + } } } } } } + catch (Exception ex) + { + Debug.Log($"No savefile for {Globals.CurrentGameName}: {ex.Message}"); + } } - catch (Exception ex) - { - Debug.Log($"No savefile for {Globals.CurrentGameName}: {ex.Message}"); - } + } + else + { + SRMP.Log("Player is being teleported", "CLIENT"); + + SRSingleton.Instance.player.transform.position = packet.Position; + SRSingleton.Instance.player.transform.eulerAngles = new Vector3(0, packet.Rotation, 0); + SRSingleton.Instance.PlayerState.model.SetCurrRegionSet((RegionRegistry.RegionSetId)packet.RegionSet); + + SRSingleton.Instance.PlayTeleport(); + } } else diff --git a/SRMP/Networking/Communication/NetworkHandlerServer.cs b/SRMP/Networking/Communication/NetworkHandlerServer.cs index fcaf43e..f84f831 100644 --- a/SRMP/Networking/Communication/NetworkHandlerServer.cs +++ b/SRMP/Networking/Communication/NetworkHandlerServer.cs @@ -335,7 +335,7 @@ namespace SRMultiplayer.Networking } } packet.SendToAllExcept(player); - } + } private static void OnExchangePrepareDaily(PacketExchangePrepareDaily packet, NetworkPlayer player) { @@ -1650,27 +1650,42 @@ namespace SRMultiplayer.Networking break; case (byte)PacketPlayerAnimation.AnimationType.Layer: player.ReadAnimatorLayer(packet.internalData); - break; + break; case (byte)PacketPlayerAnimation.AnimationType.Parameters: player.ReadParameters(packet.internalData); break; } - + //make the incoming message an out going message packet.SendToAllExcept(player, NetDeliveryMethod.Unreliable); } } - private static void OnPlayerPosition(PacketPlayerPosition packet, NetworkPlayer player) + private static void OnPlayerPosition(PacketPlayerPosition packet, NetworkPlayer netPlayer) { + //get player id from packet in case of a teleport + NetworkPlayer player = Globals.Players.Values.FirstOrDefault(p => p.ID.Equals(packet.ID)); + if (player.HasLoaded) { - player.PositionRotationUpdate(packet.Position, packet.Rotation, false); - player.UpdateWeaponRotation(packet.WeaponY); - player.CurrentRegionSet = (RegionRegistry.RegionSetId)packet.RegionSet; + if (player.IsLocal) //if the server player is the one being moved, teleport them + { + SRSingleton.Instance.player.transform.position = packet.Position; + SRSingleton.Instance.player.transform.eulerAngles = new Vector3(0, packet.Rotation, 0); + SRSingleton.Instance.PlayerState.model.SetCurrRegionSet((RegionRegistry.RegionSetId)packet.RegionSet); - packet.ID = player.ID; - packet.SendToAllExcept(player, NetDeliveryMethod.Unreliable); + SRSingleton.Instance.PlayTeleport(); + } + else //else process player movement + { + player.PositionRotationUpdate(packet.Position, packet.Rotation, false); + player.UpdateWeaponRotation(packet.WeaponY); + player.CurrentRegionSet = (RegionRegistry.RegionSetId)packet.RegionSet; + packet.ID = player.ID; + packet.SendToAllExcept(netPlayer, NetDeliveryMethod.Unreliable); + } + + } } diff --git a/SRMP/Networking/NetworkPlayer.Animation.cs b/SRMP/Networking/NetworkPlayer.Animation.cs index 921fb20..0ea4470 100644 --- a/SRMP/Networking/NetworkPlayer.Animation.cs +++ b/SRMP/Networking/NetworkPlayer.Animation.cs @@ -1,12 +1,10 @@ using Lidgren.Network; using SRMultiplayer.Packets; -using System; using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using UnityEngine; +using static SRMultiplayer.Packets.PacketPlayerAnimation; namespace SRMultiplayer.Networking { @@ -68,37 +66,36 @@ namespace SRMultiplayer.Networking var packet = new PacketPlayerAnimation() { Type = (byte)PacketPlayerAnimation.AnimationType.Layer, - ID = Globals.LocalID, - internalData = new NetBuffer() + ID = Globals.LocalID }; //add extra parameters - WriteAnimatorLayer(packet.internalData, stateHash, normalizedTime, i, layerWeight[i]); - + WriteAnimatorLayer(packet, stateHash, normalizedTime, i, layerWeight[i]); + //send the changes - //packet.Send(); + packet.Send(); } CheckSpeed(); } - void WriteAnimatorLayer(NetBuffer writer, int stateHash, float normalizedTime, int layerNumber, float layerWeight) + void WriteAnimatorLayer(PacketPlayerAnimation writer, int stateHash, float normalizedTime, int layerNumber, float layerWeight) { - writer.Write(stateHash); - writer.Write(normalizedTime); - writer.Write(layerNumber); - writer.Write(layerWeight); + writer.Add(stateHash); + writer.Add(normalizedTime); + writer.Add(layerNumber); + writer.Add(layerWeight); WriteParameters(writer); } - public void ReadAnimatorLayer(NetBuffer im) + public void ReadAnimatorLayer(Queue im) { if (m_Animator == null) return; - int stateHash = im.ReadInt32(); - float normalizedTime = im.ReadFloat(); - int layerNumber = im.ReadInt32(); - float layerWeight = im.ReadFloat(); + int stateHash = im.Dequeue().iData.Value; + float normalizedTime = im.Dequeue().fData.Value; + int layerNumber = im.Dequeue().iData.Value; + float layerWeight = im.Dequeue().fData.Value; if (stateHash != 0 && m_Animator.enabled) { @@ -122,28 +119,27 @@ namespace SRMultiplayer.Networking var packet = new PacketPlayerAnimation() { Type = (byte)PacketPlayerAnimation.AnimationType.Speed, - ID = Globals.LocalID, - internalData = new NetBuffer() + ID = Globals.LocalID }; //add extra parameters - WriteAnimatorSpeed(packet.internalData, newSpeed); + WriteAnimatorSpeed(packet, newSpeed); //send the speed change - //packet.Send(); + packet.Send(); } } - void WriteAnimatorSpeed(NetBuffer writer, float newSpeed) + void WriteAnimatorSpeed(PacketPlayerAnimation writer, float newSpeed) { - writer.Write(newSpeed); + writer.Add(newSpeed); } - public void ReadAnimatorSpeed(NetBuffer im) + public void ReadAnimatorSpeed(Queue im) { if (m_Animator == null) return; - var newSpeed = im.ReadFloat(); + var newSpeed = im.Dequeue().fData.Value; // set m_Animator m_Animator.speed = newSpeed; m_AnimatorSpeed = newSpeed; @@ -203,14 +199,14 @@ namespace SRMultiplayer.Networking var packet = new PacketPlayerAnimation() { Type = (byte)PacketPlayerAnimation.AnimationType.Parameters, - ID = Globals.LocalID, - internalData = new NetBuffer() + ID = Globals.LocalID }; //add extra parameters - WriteParameters(packet.internalData); - - //packet.Send(); + if (WriteParameters(packet)) + { + packet.Send(); + } } } @@ -251,10 +247,10 @@ namespace SRMultiplayer.Networking return dirtyBits; } - bool WriteParameters(NetBuffer writer, bool forceAll = false) + bool WriteParameters(PacketPlayerAnimation writer, bool forceAll = false) { ulong dirtyBits = forceAll ? (~0ul) : NextDirtyBits(); - writer.Write(dirtyBits); + writer.Add(dirtyBits); for (int i = 0; i < parameters.Length; i++) { if ((dirtyBits & (1ul << i)) == 0) @@ -264,53 +260,55 @@ namespace SRMultiplayer.Networking if (par.type == AnimatorControllerParameterType.Int) { int newIntValue = m_Animator.GetInteger(par.nameHash); - writer.Write(newIntValue); + writer.Add(newIntValue); } else if (par.type == AnimatorControllerParameterType.Float) { float newFloatValue = m_Animator.GetFloat(par.nameHash); - writer.Write(newFloatValue); + writer.Add(newFloatValue); } else if (par.type == AnimatorControllerParameterType.Bool) { bool newBoolValue = m_Animator.GetBool(par.nameHash); - writer.Write(newBoolValue); + writer.Add(newBoolValue); } } return dirtyBits != 0; } - public void ReadParameters(NetBuffer reader) - { + public void ReadParameters(Queue im) + { //make sure if (m_Animator == null) return; bool m_AnimatorEnabled = m_Animator.enabled; - // need to read values from NetworkReader even if m_Animator is disabled - ulong dirtyBits = reader.ReadUInt64(); + // need to read values from NetworkReader even if m_Animator is disabled + ulong dirtyBits = im.Dequeue().uData.Value; for (int i = 0; i < parameters.Length; i++) { if ((dirtyBits & (1ul << i)) == 0) continue; + AnimatorControllerParameter par = parameters[i]; + if (par.type == AnimatorControllerParameterType.Int) { - int newIntValue = reader.ReadInt32(); + int? newIntValue = im.Dequeue().iData; if (m_AnimatorEnabled) - m_Animator.SetInteger(par.nameHash, newIntValue); + m_Animator.SetInteger(par.nameHash, newIntValue.Value); } else if (par.type == AnimatorControllerParameterType.Float) { - float newFloatValue = reader.ReadSingle(); + float? newFloatValue = im.Dequeue().fData; if (m_AnimatorEnabled) - m_Animator.SetFloat(par.nameHash, newFloatValue); + m_Animator.SetFloat(par.nameHash, newFloatValue.Value); } else if (par.type == AnimatorControllerParameterType.Bool) { - bool newBoolValue = reader.ReadBoolean(); + bool? newBoolValue = im.Dequeue().bData; if (m_AnimatorEnabled) - m_Animator.SetBool(par.nameHash, newBoolValue); + m_Animator.SetBool(par.nameHash, newBoolValue.Value); } } } diff --git a/SRMP/Packets/Actors/PacketPlayerAnimation.cs b/SRMP/Packets/Actors/PacketPlayerAnimation.cs index f48894e..35f18f9 100644 --- a/SRMP/Packets/Actors/PacketPlayerAnimation.cs +++ b/SRMP/Packets/Actors/PacketPlayerAnimation.cs @@ -1,9 +1,12 @@ using Lidgren.Network; +using MonomiPark.SlimeRancher.DataModel; using System; using System.Collections.Generic; +using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; +using static SRMultiplayer.Packets.PacketAccessDoors; namespace SRMultiplayer.Packets { @@ -20,16 +23,111 @@ namespace SRMultiplayer.Packets public byte ID; public byte Type; - public NetBuffer internalData; + public struct animateData + { + public byte type + { + get + { + if (fData.HasValue) return 0; + if (bData.HasValue) return 1; + if (iData.HasValue) return 2; + if (uData.HasValue) return 3; + return 8; + } + } + public float? fData; + public bool? bData; + public int? iData; + public ulong? uData; + } + + public Queue internalData { get; set; } = new Queue(); + + public void Add(T obj) + { + switch (obj) + { + case float itm: + internalData.Enqueue(new animateData() { fData = itm }); + break; + case bool itm: + internalData.Enqueue(new animateData() { bData = itm }); + break; + case int itm: + internalData.Enqueue(new animateData() { iData = itm }); + break; + case ulong itm: + internalData.Enqueue(new animateData() { uData = itm }); + break; + } + } + /// /// mark construction inheritance incase we need it /// - public PacketPlayerAnimation():base() { } + public PacketPlayerAnimation() : base() { } /// /// mark construction inheritance so the deserialization automatically happens for is /// since the base decalres this /// - public PacketPlayerAnimation(NetIncomingMessage im):base(im) { } + public PacketPlayerAnimation(NetIncomingMessage im) : base(im) { } + + public override void Serialize(NetOutgoingMessage om) + { + base.Serialize(om); + + om.Write(internalData.Count); + foreach (var data in internalData) + { + om.Write(data.type); + switch (data.type) + { + case 0: + om.Write(data.fData.Value); + break; + case 1: + om.Write(data.bData.Value); + break; + case 2: + om.Write(data.iData.Value); + break; + case 3: + om.Write(data.uData.Value); + break; + } + } + } + + public override void Deserialize(NetIncomingMessage im) + { + base.Deserialize(im); + + internalData = new Queue(); + int Count = im.ReadInt32(); + for (int i = 0; i < Count; i++) + { + var data = new animateData(); + byte type = im.ReadByte(); + switch (type) + { + case 0: + data.fData = im.ReadFloat(); + break; + case 1: + data.bData = im.ReadBoolean(); + break; + case 2: + data.iData = im.ReadInt32(); + break; + case 3: + data.uData = im.ReadUInt64(); + break; + } + + internalData.Enqueue(data); + } + } } } diff --git a/SRMP/Packets/Players/PacketPlayerPosition.cs b/SRMP/Packets/Players/PacketPlayerPosition.cs index 18398e4..0a4597e 100644 --- a/SRMP/Packets/Players/PacketPlayerPosition.cs +++ b/SRMP/Packets/Players/PacketPlayerPosition.cs @@ -15,6 +15,7 @@ namespace SRMultiplayer.Packets public float Rotation; public float WeaponY; public byte RegionSet; + public bool OnLoad = true; public PacketPlayerPosition() { } public PacketPlayerPosition(NetIncomingMessage im) { Deserialize(im); }