diff --git a/.github/scripts/thunderstore_bundle.js b/.github/scripts/thunderstore_bundle.js
index aa2a1cac7..b7b4e2f92 100644
--- a/.github/scripts/thunderstore_bundle.js
+++ b/.github/scripts/thunderstore_bundle.js
@@ -135,7 +135,7 @@ function generateManifest() {
function generateApiManifest() {
const manifest = {
name: apiPluginInfo.name,
- description: "API for other mods to work with the Nebula Multiplayer Mod",
+ description: "API for other mods to work with the Nebula Multiplayer Mod. (Does NOT require Nebula)",
version_number: apiPluginInfo.version,
dependencies: [
BEPINEX_DEPENDENCY
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 06eeb8775..becbee9f0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
## Changelog
+0.6.0:
+
+- Fixed cases where a multiplayer session could hang on the player joining screen.
+- Fixed issue where foundations built by clients would not sync to other clients.
+- Fixed issue where the user would not be informed if they were kicked due to a mod mismatch.
+- Enabled pausing in Multiplayer when no clients are connected. (thanks to @starfi5h)
+- Now supports DSP version 0.8.21.8562+ (also thanks to @starfi5h!)
+- Mecha color configuration has been removed from the options in favor of the new option in the Mecha panel
+
0.5.0:
- Added API that enables other mods to sync over multiplayer! (Big thanks to @kremnev8!)
diff --git a/Directory.Build.props b/Directory.Build.props
index e15a63ce0..c1b4ad590 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -46,12 +46,12 @@
-
+
+
-
-
+
diff --git a/Libs/Assembly-CSharp.dll b/Libs/Assembly-CSharp.dll
deleted file mode 100644
index c0be65263..000000000
Binary files a/Libs/Assembly-CSharp.dll and /dev/null differ
diff --git a/NebulaAPI/CHANGELOG.md b/NebulaAPI/CHANGELOG.md
index 0a520df56..3dbe320e9 100644
--- a/NebulaAPI/CHANGELOG.md
+++ b/NebulaAPI/CHANGELOG.md
@@ -1,5 +1,10 @@
## Changelog
+1.1.0:
+
+- Float3 IPlayerData.MechaColor has been changed to Float4[] IPlayerData.MechaColors in line with changes introduced in DSP version 0.8.21.8562.
+- Edited description.
+
1.0.0:
- initial release on thunderstore
diff --git a/NebulaAPI/DataStructures/Float4.cs b/NebulaAPI/DataStructures/Float4.cs
index e99753e33..8f9d865b2 100644
--- a/NebulaAPI/DataStructures/Float4.cs
+++ b/NebulaAPI/DataStructures/Float4.cs
@@ -26,6 +26,40 @@ public Float4(Quaternion value)
w = value.w;
}
+ public Color ToColor()
+ {
+ return new Color(x, y, z, w);
+ }
+
+ public Color32 ToColor32()
+ {
+ return new Color32((byte)x, (byte)y, (byte)z, (byte)w);
+ }
+
+ public static Color32[] ToColor32(Float4[] float4s)
+ {
+ Color32[] color32s = new Color32[float4s.Length];
+ for (int i = 0; i < float4s.Length; i++)
+ {
+ color32s[i] = float4s[i].ToColor32();
+ }
+ return color32s;
+ }
+ public static Float4 ToFloat4(Color32 color32)
+ {
+ return new Float4(color32.r, color32.g, color32.b, color32.a);
+ }
+
+ public static Float4[] ToFloat4(Color32[] color32s)
+ {
+ Float4[] float4s = new Float4[color32s.Length];
+ for (int i = 0; i < color32s.Length; i++)
+ {
+ float4s[i] = new Float4(color32s[i].r, color32s[i].g, color32s[i].b, color32s[i].a);
+ }
+ return float4s;
+ }
+
public void Serialize(INetDataWriter writer)
{
writer.Put(x);
diff --git a/NebulaAPI/GameState/IPlayerData.cs b/NebulaAPI/GameState/IPlayerData.cs
index 9941c60f4..bbba2cdc2 100644
--- a/NebulaAPI/GameState/IPlayerData.cs
+++ b/NebulaAPI/GameState/IPlayerData.cs
@@ -5,7 +5,7 @@ public interface IPlayerData : INetSerializable
string Username { get; set; }
ushort PlayerId { get; set; }
int LocalPlanetId { get; set; }
- Float3 MechaColor { get; set; }
+ Float4[] MechaColors { get; set; }
Float3 LocalPlanetPosition { get; set; }
Double3 UPosition { get; set; }
Float3 Rotation { get; set; }
diff --git a/NebulaAPI/version.json b/NebulaAPI/version.json
index c2143a858..9f53ebb31 100644
--- a/NebulaAPI/version.json
+++ b/NebulaAPI/version.json
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
- "version": "1.0.0",
+ "version": "1.1.0",
"assemblyVersion": {
"precision": "build"
},
diff --git a/NebulaModel/DataStructures/PlayerData.cs b/NebulaModel/DataStructures/PlayerData.cs
index 6b7168f91..6b5e32b21 100644
--- a/NebulaModel/DataStructures/PlayerData.cs
+++ b/NebulaModel/DataStructures/PlayerData.cs
@@ -8,7 +8,7 @@ public class PlayerData : IPlayerData
public string Username { get; set; }
public ushort PlayerId { get; set; }
public int LocalPlanetId { get; set; }
- public Float3 MechaColor { get; set; }
+ public Float4[] MechaColors { get; set; }
public Float3 LocalPlanetPosition { get; set; }
public Double3 UPosition { get; set; }
public Float3 Rotation { get; set; }
@@ -17,13 +17,13 @@ public class PlayerData : IPlayerData
public int LocalStarId { get; set; }
public PlayerData() { }
- public PlayerData(ushort playerId, int localPlanetId, Float3 mechaColor, string username = null, Float3 localPlanetPosition = new Float3(), Double3 position = new Double3(), Float3 rotation = new Float3(), Float3 bodyRotation = new Float3())
+ public PlayerData(ushort playerId, int localPlanetId, Float4[] mechaColors, string username = null, Float3 localPlanetPosition = new Float3(), Double3 position = new Double3(), Float3 rotation = new Float3(), Float3 bodyRotation = new Float3())
{
PlayerId = playerId;
LocalPlanetId = localPlanetId;
+ MechaColors = mechaColors;
Username = !string.IsNullOrWhiteSpace(username) ? username : $"Player {playerId}";
LocalPlanetPosition = localPlanetPosition;
- MechaColor = mechaColor;
UPosition = position;
Rotation = rotation;
BodyRotation = bodyRotation;
@@ -35,7 +35,11 @@ public void Serialize(INetDataWriter writer)
writer.Put(Username);
writer.Put(PlayerId);
writer.Put(LocalPlanetId);
- MechaColor.Serialize(writer);
+ writer.Put(MechaColors?.Length ?? 0);
+ for (int i = 0; i < (MechaColors?.Length ?? 0); i++)
+ {
+ MechaColors[i].Serialize(writer);
+ }
LocalPlanetPosition.Serialize(writer);
UPosition.Serialize(writer);
Rotation.Serialize(writer);
@@ -48,7 +52,11 @@ public void Deserialize(INetDataReader reader)
Username = reader.GetString();
PlayerId = reader.GetUShort();
LocalPlanetId = reader.GetInt();
- MechaColor = reader.GetFloat3();
+ MechaColors = new Float4[reader.GetInt()];
+ for (int i = 0; i < MechaColors.Length; i++)
+ {
+ MechaColors[i] = reader.GetFloat4();
+ }
LocalPlanetPosition = reader.GetFloat3();
UPosition = reader.GetDouble3();
Rotation = reader.GetFloat3();
@@ -59,7 +67,7 @@ public void Deserialize(INetDataReader reader)
public IPlayerData CreateCopyWithoutMechaData()
{
- return new PlayerData(PlayerId, LocalPlanetId, MechaColor, Username, LocalPlanetPosition, UPosition, Rotation, BodyRotation);
+ return new PlayerData(PlayerId, LocalPlanetId, MechaColors, Username, LocalPlanetPosition, UPosition, Rotation, BodyRotation);
}
}
}
diff --git a/NebulaModel/MultiplayerOptions.cs b/NebulaModel/MultiplayerOptions.cs
index 982438c32..ebf12662e 100644
--- a/NebulaModel/MultiplayerOptions.cs
+++ b/NebulaModel/MultiplayerOptions.cs
@@ -1,4 +1,5 @@
-using NebulaModel.Attributes;
+using NebulaAPI;
+using NebulaModel.Attributes;
using System;
using System.ComponentModel;
@@ -10,18 +11,6 @@ public class MultiplayerOptions : ICloneable
[DisplayName("Nickname")]
public string Nickname { get; set; } = string.Empty;
- [DisplayName("Mecha Color Red")]
- [UIRange(0, 255, true)]
- public float MechaColorR { get; set; } = 255;
-
- [DisplayName("Mecha Color Green")]
- [UIRange(0, 255, true)]
- public float MechaColorG { get; set; } = 174;
-
- [DisplayName("Mecha Color Blue")]
- [UIRange(0, 255, true)]
- public float MechaColorB { get; set; } = 61;
-
[DisplayName("Host Port")]
[UIRange(1, ushort.MaxValue)]
public ushort HostPort { get; set; } = 8469;
@@ -31,6 +20,38 @@ public class MultiplayerOptions : ICloneable
public string LastIP { get; set; } = string.Empty;
+ public string MechaColors { get; set; } = "209 151 76 255;184 90 72 255;94 92 92 255;123 234 255 255;229 155 94 255;255 243 235 255;255 248 245 255;255 255 255 255;";
+
+ public Float4[] GetMechaColors()
+ {
+ string[] colors = MechaColors.Split(';');
+ Float4[] mechaColors = new Float4[colors.Length - 1];
+ for (int i = 0; i < colors.Length - 1; i++)
+ {
+ string[] color = colors[i].Split(' ');
+ if (!float.TryParse(color[0], out mechaColors[i].x) ||
+ !float.TryParse(color[1], out mechaColors[i].y) ||
+ !float.TryParse(color[2], out mechaColors[i].z) ||
+ !float.TryParse(color[3], out mechaColors[i].w))
+ {
+ Logger.Log.Error($"Color {i} is invalid.");
+ }
+ }
+ return mechaColors;
+ }
+
+ public void SetMechaColors()
+ {
+ UnityEngine.Color32[] mainColors = GameMain.mainPlayer.mecha.mainColors;
+ string mechaColors = string.Empty;
+ for (int i = 0; i < mainColors.Length; i++)
+ {
+ mechaColors += $"{(int)mainColors[i].r} {(int)mainColors[i].g} {(int)mainColors[i].b} {(int)mainColors[i].a};";
+ }
+ MechaColors = mechaColors;
+ Config.SaveOptions();
+ }
+
// Detail function group buttons
public bool PowerGridEnabled { get; set; } = false;
public bool VeinDistributionEnabled { get; set; } = false;
@@ -41,7 +62,7 @@ public class MultiplayerOptions : ICloneable
public object Clone()
{
- return this.MemberwiseClone();
+ return MemberwiseClone();
}
}
}
diff --git a/NebulaModel/Packets/Players/PlayerAnimationUpdate.cs b/NebulaModel/Packets/Players/PlayerAnimationUpdate.cs
index ca34c1edb..28e116dbd 100644
--- a/NebulaModel/Packets/Players/PlayerAnimationUpdate.cs
+++ b/NebulaModel/Packets/Players/PlayerAnimationUpdate.cs
@@ -1,5 +1,7 @@
using NebulaAPI;
using NebulaModel.DataStructures;
+using Unity;
+using UnityEngine;
namespace NebulaModel.Packets.Players
{
@@ -7,23 +9,41 @@ namespace NebulaModel.Packets.Players
public class PlayerAnimationUpdate
{
public ushort PlayerId { get; set; }
+ public float JumpWeight { get; set; }
+ public float JumpNormalizedTime { get; set; }
+ public int IdleAnimIndex { get; set; }
+ public int SailAnimIndex { get; set; }
+ public float MiningWeight { get; set; }
+ public int MiningAnimIndex { get; set; }
- // TODO: They don't use a finite state machine for there animation. But we need to find a way to optimized this packet.
- // maybe we could only send the variables that are used to changed the animation state.
- // See: (Game: PlayerAnimator class)
- public NebulaAnimationState Idle { get; set; }
- public NebulaAnimationState RunSlow { get; set; }
- public NebulaAnimationState RunFast { get; set; }
- public NebulaAnimationState Drift { get; set; }
- public NebulaAnimationState DriftF { get; set; }
- public NebulaAnimationState DriftL { get; set; }
- public NebulaAnimationState DriftR { get; set; }
- public NebulaAnimationState Fly { get; set; }
- public NebulaAnimationState Sail { get; set; }
- public NebulaAnimationState Mining0 { get; set; }
- // some extra values to compute backpack flame size
- // i put them here because i update the player fx together with the animation update
- public float vertSpeed { get; set; }
- public float horzSpeed { get; set; }
+ public EMovementState MovementState { get; set; }
+ public float HorzSpeed { get; set; }
+ public float VertSpeed { get; set; }
+ public float Turning { get; set; }
+ public float Altitude { get; set; }
+
+ public PlayerAnimationUpdate() { }
+
+ public PlayerAnimationUpdate(ushort playerId, PlayerAnimator animator)
+ {
+ PlayerId = playerId;
+
+ JumpWeight = animator.jumpWeight;
+ JumpNormalizedTime = animator.jumpNormalizedTime;
+ IdleAnimIndex = animator.idleAnimIndex;
+ SailAnimIndex = animator.sailAnimIndex;
+ MiningWeight = animator.miningWeight;
+ MiningAnimIndex = animator.miningAnimIndex;
+
+ MovementState = animator.movementState;
+ HorzSpeed = animator.controller.horzSpeed;
+ VertSpeed = animator.controller.vertSpeed;
+ Turning = animator.turning;
+ Altitude = 1f;
+ if (GameMain.localPlanet != null)
+ {
+ Altitude = Mathf.Clamp01((animator.player.position.magnitude - GameMain.localPlanet.realRadius - 7f) * 0.15f);
+ }
+ }
}
}
diff --git a/NebulaModel/Packets/Players/PlayerColorChanged.cs b/NebulaModel/Packets/Players/PlayerColorChanged.cs
index 91f66045d..3c26cfb67 100644
--- a/NebulaModel/Packets/Players/PlayerColorChanged.cs
+++ b/NebulaModel/Packets/Players/PlayerColorChanged.cs
@@ -5,13 +5,13 @@ namespace NebulaModel.Packets.Players
public class PlayerColorChanged
{
public ushort PlayerId { get; set; }
- public Float3 Color { get; set; }
+ public Float4[] Colors { get; set; }
public PlayerColorChanged() { }
- public PlayerColorChanged(ushort playerID, Float3 color)
+ public PlayerColorChanged(ushort playerID, Float4[] colors)
{
PlayerId = playerID;
- Color = color;
+ Colors = colors;
}
}
}
diff --git a/NebulaModel/Packets/Session/HandshakeRequest.cs b/NebulaModel/Packets/Session/HandshakeRequest.cs
index d69c24fd1..d7444b346 100644
--- a/NebulaModel/Packets/Session/HandshakeRequest.cs
+++ b/NebulaModel/Packets/Session/HandshakeRequest.cs
@@ -6,7 +6,7 @@ namespace NebulaModel.Packets.Session
public class HandshakeRequest
{
public string Username { get; set; }
- public Float3 MechaColor { get; set; }
+ public Float4[] MechaColors { get; set; }
public byte[] ModsVersion { get; set; }
public int ModsCount { get; set; }
public int GameVersionSig { get; set; }
@@ -14,15 +14,15 @@ public class HandshakeRequest
public HandshakeRequest() { }
- public HandshakeRequest(byte[] clientCert, string username, Float3 mechaColor)
+ public HandshakeRequest(byte[] clientCert, string username, Float4[] mechaColors)
{
Username = username;
- MechaColor = mechaColor;
+ MechaColors = mechaColors;
using (BinaryUtils.Writer writer = new BinaryUtils.Writer())
{
int count = 0;
- foreach (var pluginInfo in BepInEx.Bootstrap.Chainloader.PluginInfos)
+ foreach (System.Collections.Generic.KeyValuePair pluginInfo in BepInEx.Bootstrap.Chainloader.PluginInfos)
{
if (pluginInfo.Value.Instance is IMultiplayerMod mod)
{
diff --git a/NebulaNetwork/Client.cs b/NebulaNetwork/Client.cs
index 1cce3f040..8b9df2481 100644
--- a/NebulaNetwork/Client.cs
+++ b/NebulaNetwork/Client.cs
@@ -161,7 +161,7 @@ private void ClientSocket_OnOpen(object sender, System.EventArgs e)
SendPacket(new HandshakeRequest(
CryptoUtils.GetPublicKey(CryptoUtils.GetOrCreateUserCert()),
!string.IsNullOrWhiteSpace(Config.Options.Nickname) ? Config.Options.Nickname : GameMain.data.account.userName,
- new Float3(Config.Options.MechaColorR / 255, Config.Options.MechaColorG / 255, Config.Options.MechaColorB / 255)));
+ Config.Options.GetMechaColors()));
}
private void ClientSocket_OnClose(object sender, CloseEventArgs e)
diff --git a/NebulaNetwork/PacketProcessors/Players/PlayerColorChangedProcessor.cs b/NebulaNetwork/PacketProcessors/Players/PlayerColorChangedProcessor.cs
index 9fa668a71..d49a18409 100644
--- a/NebulaNetwork/PacketProcessors/Players/PlayerColorChangedProcessor.cs
+++ b/NebulaNetwork/PacketProcessors/Players/PlayerColorChangedProcessor.cs
@@ -9,7 +9,7 @@ namespace NebulaNetwork.PacketProcessors.Players
[RegisterPacketProcessor]
public class PlayerColorChangedProcessor : PacketProcessor
{
- private IPlayerManager playerManager;
+ private readonly IPlayerManager playerManager;
public PlayerColorChangedProcessor()
{
@@ -25,7 +25,7 @@ public override void ProcessPacket(PlayerColorChanged packet, NebulaConnection c
INebulaPlayer player = playerManager.GetPlayer(conn);
if (player != null)
{
- player.Data.MechaColor = packet.Color;
+ player.Data.MechaColors = packet.Colors;
playerManager.SendPacketToOtherPlayers(packet, player);
}
else
@@ -36,7 +36,7 @@ public override void ProcessPacket(PlayerColorChanged packet, NebulaConnection c
if (valid)
{
- Multiplayer.Session.World.UpdatePlayerColor(packet.PlayerId, packet.Color);
+ Multiplayer.Session.World.UpdatePlayerColor(packet.PlayerId, packet.Colors);
}
}
}
diff --git a/NebulaNetwork/PacketProcessors/Session/HandshakeRequestProcessor.cs b/NebulaNetwork/PacketProcessors/Session/HandshakeRequestProcessor.cs
index 5fd2d2ee5..6b0492b70 100644
--- a/NebulaNetwork/PacketProcessors/Session/HandshakeRequestProcessor.cs
+++ b/NebulaNetwork/PacketProcessors/Session/HandshakeRequestProcessor.cs
@@ -112,7 +112,7 @@ public override void ProcessPacket(HandshakeRequest packet, NebulaConnection con
player.Data.Username = !string.IsNullOrWhiteSpace(packet.Username) ? packet.Username : $"Player {player.Id}";
// Add the Mecha Color to the player data
- player.Data.MechaColor = packet.MechaColor;
+ player.Data.MechaColors = packet.MechaColors;
// Make sure that each player that is currently in the game receives that a new player as join so they can create its RemotePlayerCharacter
PlayerJoining pdata = new PlayerJoining((PlayerData)player.Data.CreateCopyWithoutMechaData()); // Remove inventory from mecha data
diff --git a/NebulaNetwork/PlayerManager.cs b/NebulaNetwork/PlayerManager.cs
index f19431910..6db92eeac 100644
--- a/NebulaNetwork/PlayerManager.cs
+++ b/NebulaNetwork/PlayerManager.cs
@@ -9,7 +9,6 @@
using NebulaWorld;
using System.Collections.Generic;
using System.Threading;
-using Config = NebulaModel.Config;
namespace NebulaNetwork
{
@@ -227,9 +226,8 @@ public INebulaPlayer PlayerConnected(INebulaConnection conn)
// Generate new data for the player
ushort playerId = GetNextAvailablePlayerId();
- Float3 playerColor = new Float3(Config.Options.MechaColorR / 255, Config.Options.MechaColorG / 255, Config.Options.MechaColorB / 255);
PlanetData birthPlanet = GameMain.galaxy.PlanetById(GameMain.galaxy.birthPlanetId);
- PlayerData playerData = new PlayerData(playerId, -1, playerColor, position: new Double3(birthPlanet.uPosition.x, birthPlanet.uPosition.y, birthPlanet.uPosition.z));
+ PlayerData playerData = new PlayerData(playerId, -1, Config.Options.GetMechaColors(), position: new Double3(birthPlanet.uPosition.x, birthPlanet.uPosition.y, birthPlanet.uPosition.z));
INebulaPlayer newPlayer = new NebulaPlayer((NebulaConnection)conn, playerData);
using (GetPendingPlayers(out Dictionary pendingPlayers))
diff --git a/NebulaNetwork/Server.cs b/NebulaNetwork/Server.cs
index 0738c7279..1a91619ec 100644
--- a/NebulaNetwork/Server.cs
+++ b/NebulaNetwork/Server.cs
@@ -18,9 +18,9 @@ namespace NebulaNetwork
{
public class Server : NetworkProvider
{
- const float GAME_STATE_UPDATE_INTERVAL = 1;
- const float GAME_RESEARCH_UPDATE_INTERVAL = 2;
- const float STATISTICS_UPDATE_INTERVAL = 1;
+ private const float GAME_STATE_UPDATE_INTERVAL = 1;
+ private const float GAME_RESEARCH_UPDATE_INTERVAL = 2;
+ private const float STATISTICS_UPDATE_INTERVAL = 1;
private float gameStateUpdateTimer = 0;
private float gameResearchHashUpdateTimer = 0;
@@ -69,7 +69,7 @@ public override void Start()
((LocalPlayer)Multiplayer.Session.LocalPlayer).SetPlayerData(new PlayerData(
PlayerManager.GetNextAvailablePlayerId(),
GameMain.localPlanet?.id ?? -1,
- new Float3(Config.Options.MechaColorR / 255, Config.Options.MechaColorG / 255, Config.Options.MechaColorB / 255),
+ Config.Options.GetMechaColors(),
!string.IsNullOrWhiteSpace(Config.Options.Nickname) ? Config.Options.Nickname : GameMain.data.account.userName), loadSaveFile);
NebulaModAPI.OnMultiplayerGameStarted?.Invoke();
@@ -148,7 +148,7 @@ public override void Update()
PacketProcessor.ProcessPacketQueue();
}
- void DisableNagleAlgorithm(WebSocketServer socketServer)
+ private void DisableNagleAlgorithm(WebSocketServer socketServer)
{
TcpListener listener = AccessTools.FieldRefAccess("_listener")(socketServer);
listener.Server.NoDelay = true;
@@ -190,7 +190,9 @@ protected override void OnClose(CloseEventArgs e)
// we don't need to inform the other clients since the disconnected client never
// joined the game in the first place.
if (e.Code == (short)DisconnectionReason.HostStillLoading)
+ {
return;
+ }
NebulaModel.Logger.Log.Info($"Client disconnected: {ID}, reason: {e.Reason}");
UnityDispatchQueue.RunOnMainThread(() =>
diff --git a/NebulaPatcher/Patches/Dynamic/UIMechaWindow_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIMechaWindow_Patch.cs
new file mode 100644
index 000000000..92271a7f6
--- /dev/null
+++ b/NebulaPatcher/Patches/Dynamic/UIMechaWindow_Patch.cs
@@ -0,0 +1,25 @@
+using HarmonyLib;
+using NebulaAPI;
+using NebulaModel;
+using NebulaModel.Packets.Players;
+using NebulaWorld;
+
+namespace NebulaPatcher.Patches.Dynamic
+{
+ [HarmonyPatch(typeof(UIMechaWindow))]
+ internal class UIMechaWindow_Patch
+ {
+ [HarmonyPostfix]
+ [HarmonyPatch(nameof(UIMechaWindow._OnClose))]
+ public static void _OnClose_Postfix()
+ {
+ if (!Multiplayer.IsActive)
+ {
+ return;
+ }
+
+ Multiplayer.Session.Network.SendPacket(new PlayerColorChanged(Multiplayer.Session.LocalPlayer.Id, Float4.ToFloat4(GameMain.mainPlayer.mecha.mainColors)));
+ Config.Options.SetMechaColors();
+ }
+ }
+}
diff --git a/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs b/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs
index 99c413b28..cef6345eb 100644
--- a/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs
+++ b/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs
@@ -7,15 +7,15 @@
namespace NebulaPatcher.Patches.Transpilers
{
[HarmonyPatch(typeof(PowerSystem))]
- class PowerSystem_Transpiler
+ internal class PowerSystem_Transpiler
{
- delegate void PlayerChargesAtTower(PowerSystem _this, int powerNodeId, int powerNetId);
+ private delegate void PlayerChargesAtTower(PowerSystem _this, int powerNodeId, int powerNetId);
[HarmonyTranspiler]
[HarmonyPatch(nameof(PowerSystem.GameTick))]
public static IEnumerable PowerSystem_GameTick_Transpiler(IEnumerable instructions)
{
- instructions = new CodeMatcher(instructions)
+ CodeMatcher codeMatcher = new CodeMatcher(instructions)
.MatchForward(true,
new CodeMatch(OpCodes.Ldarg_0),
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerSystem), nameof(PowerSystem.nodePool))),
@@ -26,10 +26,18 @@ public static IEnumerable PowerSystem_GameTick_Transpiler(IEnum
new CodeMatch(OpCodes.Ldloc_S),
new CodeMatch(OpCodes.Ldelema),
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerNodeComponent), nameof(PowerNodeComponent.workEnergyPerTick))),
- new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(PowerNodeComponent), nameof(PowerNodeComponent.requiredEnergy))))
+ new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(PowerNodeComponent), nameof(PowerNodeComponent.requiredEnergy))));
+
+ if (codeMatcher.IsInvalid)
+ {
+ NebulaModel.Logger.Log.Error("PowerSystem_GameTick_Transpiler 1 failed. Mod version not compatible with game version.");
+ return instructions;
+ }
+
+ codeMatcher = codeMatcher
.Advance(1)
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
- .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 58))
+ .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 59))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 22))
.Insert(HarmonyLib.Transpilers.EmitDelegate((PowerSystem _this, int powerNodeId, int powerNetId) =>
{
@@ -71,13 +79,21 @@ public static IEnumerable PowerSystem_GameTick_Transpiler(IEnum
new CodeMatch(OpCodes.Ldloc_S),
new CodeMatch(OpCodes.Ldelema),
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerNodeComponent), nameof(PowerNodeComponent.idleEnergyPerTick))),
- new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(PowerNodeComponent), nameof(PowerNodeComponent.requiredEnergy))))
+ new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(PowerNodeComponent), nameof(PowerNodeComponent.requiredEnergy))));
+
+ if (codeMatcher.IsInvalid)
+ {
+ NebulaModel.Logger.Log.Error("PowerSystem_GameTick_Transpiler 2 failed. Mod version not compatible with game version.");
+ return codeMatcher.InstructionEnumeration();
+ }
+
+ return codeMatcher
.Repeat(matcher =>
{
matcher
.Advance(1)
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
- .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 58))
+ .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 59))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 22))
.Insert(HarmonyLib.Transpilers.EmitDelegate((PowerSystem _this, int powerNodeId, int powerNetId) =>
{
@@ -109,8 +125,6 @@ public static IEnumerable PowerSystem_GameTick_Transpiler(IEnum
}));
})
.InstructionEnumeration();
-
- return instructions;
}
}
}
diff --git a/NebulaWorld/MonoBehaviours/Local/LocalPlayerAnimation.cs b/NebulaWorld/MonoBehaviours/Local/LocalPlayerAnimation.cs
index db7eef289..f53833922 100644
--- a/NebulaWorld/MonoBehaviours/Local/LocalPlayerAnimation.cs
+++ b/NebulaWorld/MonoBehaviours/Local/LocalPlayerAnimation.cs
@@ -1,5 +1,4 @@
-using NebulaModel.DataStructures;
-using NebulaModel.Packets.Players;
+using NebulaModel.Packets.Players;
using UnityEngine;
namespace NebulaWorld.MonoBehaviours.Local
@@ -24,28 +23,7 @@ void Update()
if (time >= BROADCAST_INTERVAL)
{
time = 0;
-
- PlayerController controller = playerAnimator.player.controller;
- float vertSpeed = Vector3.Dot(base.transform.up, controller.velocity);
- Vector3 horzVel = controller.velocity - vertSpeed * base.transform.up;
- float horzSpeed = horzVel.magnitude;
-
- Multiplayer.Session.Network.SendPacket(new PlayerAnimationUpdate()
- {
- PlayerId = Multiplayer.Session.LocalPlayer.Id,
- Idle = playerAnimator.idle.ToNebula(),
- RunSlow = playerAnimator.runSlow.ToNebula(),
- RunFast = playerAnimator.runFast.ToNebula(),
- Drift = playerAnimator.drift.ToNebula(),
- DriftF = playerAnimator.driftF.ToNebula(),
- DriftL = playerAnimator.driftL.ToNebula(),
- DriftR = playerAnimator.driftR.ToNebula(),
- Fly = playerAnimator.fly.ToNebula(),
- Sail = playerAnimator.sail.ToNebula(),
- Mining0 = playerAnimator.mining0.ToNebula(),
- horzSpeed = horzSpeed,
- vertSpeed = vertSpeed,
- });
+ Multiplayer.Session.Network.SendPacket(new PlayerAnimationUpdate(Multiplayer.Session.LocalPlayer.Id, playerAnimator));
}
}
}
diff --git a/NebulaWorld/MonoBehaviours/Remote/RemotePlayerAnimation.cs b/NebulaWorld/MonoBehaviours/Remote/RemotePlayerAnimation.cs
index ce1586bfc..92a29dbae 100644
--- a/NebulaWorld/MonoBehaviours/Remote/RemotePlayerAnimation.cs
+++ b/NebulaWorld/MonoBehaviours/Remote/RemotePlayerAnimation.cs
@@ -1,5 +1,4 @@
-using NebulaModel.DataStructures;
-using NebulaModel.Packets.Players;
+using NebulaModel.Packets.Players;
using UnityEngine;
namespace NebulaWorld.MonoBehaviours.Remote
@@ -7,73 +6,119 @@ namespace NebulaWorld.MonoBehaviours.Remote
// TODO: Missing client side interpolation
public class RemotePlayerAnimation : MonoBehaviour
{
- private Animation anim;
+ public PlayerAnimator PlayerAnimator;
- public AnimationState Idle { get; private set; }
- public AnimationState RunSlow { get; private set; }
- public AnimationState RunFast { get; private set; }
- public AnimationState Drift { get; private set; }
- public AnimationState DriftF { get; private set; }
- public AnimationState DriftL { get; private set; }
- public AnimationState DriftR { get; private set; }
- public AnimationState Fly { get; private set; }
- public AnimationState Sail { get; private set; }
- public AnimationState Mining0 { get; private set; }
+ private float altitude;
private void Awake()
{
- anim = GetComponentInChildren();
+ PlayerAnimator = GetComponentInChildren();
+ }
+
+ public void UpdateState(PlayerAnimationUpdate packet)
+ {
+ if (PlayerAnimator == null)
+ {
+ return;
+ }
+
+ PlayerAnimator.jumpWeight = packet.JumpWeight;
+ PlayerAnimator.jumpNormalizedTime = packet.JumpNormalizedTime;
+ PlayerAnimator.idleAnimIndex = packet.IdleAnimIndex;
+ PlayerAnimator.sailAnimIndex = packet.SailAnimIndex;
+ PlayerAnimator.miningWeight = packet.MiningWeight;
+ PlayerAnimator.miningAnimIndex = packet.MiningAnimIndex;
+
+ PlayerAnimator.movementState = packet.MovementState;
+ PlayerAnimator.horzSpeed = packet.HorzSpeed;
+ PlayerAnimator.turning = packet.Turning;
+ altitude = packet.Altitude;
+
+ float deltaTime = Time.deltaTime;
+ CalculateMovementStateWeights(PlayerAnimator, deltaTime);
+ CalculateDirectionWeights(PlayerAnimator, deltaTime);
+
+ PlayerAnimator.AnimateIdleState(deltaTime);
+ PlayerAnimator.AnimateRunState(deltaTime);
+ PlayerAnimator.AnimateDriftState(deltaTime);
+ AnimateFlyState(PlayerAnimator);
+ AnimateSailState(PlayerAnimator);
- Idle = anim["idle"];
- RunSlow = anim["run-slow"];
- RunFast = anim["run-fast"];
- Drift = anim["drift"];
- DriftF = anim["drift-f"];
- DriftL = anim["drift-l"];
- DriftR = anim["drift-r"];
- Fly = anim["fly"];
- Sail = anim["sail"];
- Mining0 = anim["mining-0"];
+ PlayerAnimator.AnimateJumpState(deltaTime);
+ PlayerAnimator.AnimateSkills(deltaTime);
+ AnimateRenderers(PlayerAnimator);
+ }
+
+ private void CalculateMovementStateWeights(PlayerAnimator animator, float dt)
+ {
+ float runTarget = (animator.horzSpeed > 0.15f) ? 1f : 0f;
+ float driftTarget = (animator.movementState >= EMovementState.Drift) ? 1f : 0f;
+ float flyTarget = (animator.movementState >= EMovementState.Fly) ? 1f : 0f;
+ float sailTarget = (animator.movementState >= EMovementState.Sail) ? 1f : 0f;
+ animator.runWeight = Mathf.MoveTowards(animator.runWeight, runTarget, dt / 0.22f);
+ animator.driftWeight = Mathf.MoveTowards(animator.driftWeight, driftTarget, dt / 0.2f);
+ animator.flyWeight = Mathf.MoveTowards(animator.flyWeight, flyTarget, dt / ((flyTarget > 0.5) ? 0.4f : 0.2f));
+ animator.sailWeight = Mathf.MoveTowards(animator.sailWeight, sailTarget, dt / ((sailTarget > 0.5) ? 0.8f : 0.2f));
+ for (int i = 0; i < animator.sails.Length; i++)
+ {
+ animator.sailAnimWeights[i] = Mathf.MoveTowards(animator.sailAnimWeights[i], (i == animator.sailAnimIndex) ? 1f : 0f, dt / 0.3f);
+ }
+ }
+
+ private void CalculateDirectionWeights(PlayerAnimator animator, float dt)
+ {
+ animator.leftWeight = Mathf.InverseLerp(-animator.minTurningAngle, -animator.maxTurningAngle, animator.turning);
+ animator.rightWeight = Mathf.InverseLerp(animator.minTurningAngle, animator.maxTurningAngle, animator.turning);
+ animator.forwardWeight = Mathf.Clamp01(1f - animator.leftWeight - animator.rightWeight);
+ float num = Mathf.Clamp01((animator.horzSpeed - 0.01f) / ((animator.movementState == EMovementState.Drift) ? 5f : 12.5f));
+ animator.forwardWeight *= num;
+ animator.leftWeight *= num;
+ animator.rightWeight *= num;
+ animator.zeroWeight = 1f - animator.forwardWeight - animator.leftWeight - animator.rightWeight;
+ }
- Idle.layer = 0;
- RunSlow.layer = 1;
- RunFast.layer = 1;
- Drift.layer = 2;
- DriftF.layer = 2;
- DriftL.layer = 2;
- DriftR.layer = 2;
- Fly.layer = 3;
- Sail.layer = 3;
- Mining0.layer = 4;
- Idle.weight = 1f;
- RunSlow.weight = 0.0f;
- RunFast.weight = 0.0f;
- Drift.weight = 0.0f;
- Fly.weight = 0.0f;
- Sail.weight = 0.0f;
- Mining0.weight = 0.0f;
- Mining0.speed = 0.8f;
+ public void AnimateFlyState(PlayerAnimator animator)
+ {
+ bool flag = animator.flyWeight > 0.001f;
+ animator.fly_0.enabled = flag;
+ animator.fly_f.enabled = flag;
+ animator.fly_l.enabled = flag;
+ animator.fly_r.enabled = flag;
+ animator.fly_0.weight = altitude * animator.flyWeight * animator.zeroWeight;
+ animator.fly_f.weight = altitude * animator.flyWeight * animator.forwardWeight;
+ animator.fly_l.weight = altitude * animator.flyWeight * animator.leftWeight;
+ animator.fly_r.weight = altitude * animator.flyWeight * animator.rightWeight;
+ animator.fly_0.speed = 0.44f;
+ animator.fly_f.speed = 0.44f;
+ animator.fly_l.speed = 0.44f;
+ animator.fly_r.speed = 0.44f;
+ if (!flag)
+ {
+ animator.fly_0.normalizedTime = 0f;
+ animator.fly_f.normalizedTime = 0f;
+ animator.fly_l.normalizedTime = 0f;
+ animator.fly_r.normalizedTime = 0f;
+ }
}
- public void UpdateState(PlayerAnimationUpdate packet)
+ public void AnimateSailState(PlayerAnimator animator)
{
- ApplyAnimationState(Idle, packet.Idle);
- ApplyAnimationState(RunSlow, packet.RunSlow);
- ApplyAnimationState(RunFast, packet.RunFast);
- ApplyAnimationState(Drift, packet.Drift);
- ApplyAnimationState(DriftF, packet.DriftF);
- ApplyAnimationState(DriftL, packet.DriftL);
- ApplyAnimationState(DriftR, packet.DriftR);
- ApplyAnimationState(Fly, packet.Fly);
- ApplyAnimationState(Sail, packet.Sail);
- ApplyAnimationState(Mining0, packet.Mining0);
+ bool flag = animator.sailWeight > 0.001f;
+ for (int i = 0; i < animator.sails.Length; i++)
+ {
+ animator.sails[i].weight = altitude * animator.sailWeight * animator.sailAnimWeights[i];
+ animator.sails[i].enabled = flag;
+ animator.sails[i].speed = 1f;
+ if (!flag)
+ {
+ animator.sails[i].normalizedTime = 0f;
+ }
+ }
}
- private void ApplyAnimationState(AnimationState animState, NebulaAnimationState newState)
+ public void AnimateRenderers(PlayerAnimator animator)
{
- animState.weight = newState.Weight;
- animState.speed = newState.Speed;
- animState.enabled = newState.Enabled;
+ animator.inst_armor_mat.SetVector("_InitPositionSet", transform.position);
}
}
}
diff --git a/NebulaWorld/MonoBehaviours/Remote/RemotePlayerEffects.cs b/NebulaWorld/MonoBehaviours/Remote/RemotePlayerEffects.cs
index e3eadbe3a..a90590231 100644
--- a/NebulaWorld/MonoBehaviours/Remote/RemotePlayerEffects.cs
+++ b/NebulaWorld/MonoBehaviours/Remote/RemotePlayerEffects.cs
@@ -5,7 +5,7 @@
namespace NebulaWorld.MonoBehaviours.Remote
{
public class RemoteWarpEffect : MonoBehaviour
- {
+ {
private Transform rootTransform;
private VFWarpEffect warpEffect = null;
@@ -39,11 +39,11 @@ public class RemoteWarpEffect : MonoBehaviour
Vector4[] warpRotations;
Vector3 velocity;
- RemotePlayerAnimation rootAnimation = null;
+ PlayerAnimator rootAnimation = null;
public void Awake()
{
rootTransform = GetComponent();
- rootAnimation = GetComponent();
+ rootAnimation = GetComponent();
warpEffect = Instantiate(Configs.builtin.warpEffectPrefab, GetComponent());
warpEffect.enabled = false;
@@ -124,7 +124,7 @@ private void ToggleEffect(bool toggle)
public void StartWarp()
{
- if (!rootAnimation.Sail.enabled || isWarping)
+ if (rootAnimation.sailWeight <= 0.001f || isWarping)
{
return;
}
@@ -134,7 +134,7 @@ public void StartWarp()
public void StopWarp()
{
- if (!rootAnimation.Sail.enabled || !isWarping)
+ if (rootAnimation.sailWeight <= 0.001f || !isWarping)
{
return;
}
@@ -205,16 +205,17 @@ public void Update()
astrosMat.SetFloat("_Multiplier", astrosMul * num2);
nebulasMat.SetFloat("_Multiplier", nebulasMul * num2);
}
+
}
+
public class RemotePlayerEffects : MonoBehaviour
{
- private RemotePlayerAnimation rootAnimation;
+ private PlayerAnimator rootAnimation;
private Transform rootTransform;
private Transform rootModelTransform;
private RemoteWarpEffect rootWarp;
private ParticleSystem[] WaterEffect;
- private ParticleSystem[][] FootSmokeEffect;
private ParticleSystem[] FootSmallSmoke;
private ParticleSystem[] FootLargeSmoke;
private ParticleSystem[] FootEffect;
@@ -238,7 +239,7 @@ public class RemotePlayerEffects : MonoBehaviour
public void Awake()
{
- rootAnimation = GetComponent();
+ rootAnimation = GetComponentInChildren();
rootTransform = GetComponent();
rootModelTransform = rootTransform.Find("Model");
@@ -247,13 +248,11 @@ public void Awake()
torchEffect = rootModelTransform.Find("bip/pelvis/spine-1/spine-2/spine-3/r-clavicle/r-upper-arm/r-forearm/r-torch/vfx-torch/blast").GetComponent();
FootEffect = new ParticleSystem[2];
WaterEffect = new ParticleSystem[2];
- FootSmokeEffect = new ParticleSystem[2][];
- FootSmokeEffect[0] = new ParticleSystem[2];
- FootSmokeEffect[1] = new ParticleSystem[2];
FootSmallSmoke = new ParticleSystem[2];
FootLargeSmoke = new ParticleSystem[2];
- Transform VFX = rootModelTransform.Find("bip/pelvis/spine-1/spine-2/spine-3/backpack/VFX").GetComponent();
+
+ Transform VFX = rootModelTransform.Find("bip/pelvis/spine-1/spine-2/spine-3/backpack/backpack_end/VFX").GetComponent();
psys[0] = VFX.GetChild(0).GetComponent();
psys[1] = VFX.GetChild(1).GetComponent();
@@ -261,18 +260,15 @@ public void Awake()
psysr[0] = VFX.GetChild(0).Find("flames").GetComponent();
psysr[1] = VFX.GetChild(1).Find("flames").GetComponent();
- WaterEffect[0] = rootModelTransform.Find("bip/pelvis/l-thigh/l-calf/l-ankle/l-foot/vfx-footsteps/water").GetComponent();
- WaterEffect[1] = rootModelTransform.Find("bip/pelvis/r-thigh/r-calf/r-ankle/r-foot/vfx-footsteps/water").GetComponent();
- FootSmokeEffect[0][0] = rootModelTransform.Find("bip/pelvis/l-thigh/l-calf/l-ankle/l-foot/vfx-footsteps/smoke").GetComponent();
- FootSmokeEffect[0][1] = rootModelTransform.Find("bip/pelvis/l-thigh/l-calf/l-ankle/l-foot/vfx-footsteps/smoke-2").GetComponent();
- FootSmokeEffect[1][0] = rootModelTransform.Find("bip/pelvis/r-thigh/r-calf/r-ankle/r-foot/vfx-footsteps/smoke").GetComponent();
- FootSmokeEffect[1][1] = rootModelTransform.Find("bip/pelvis/r-thigh/r-calf/r-ankle/r-foot/vfx-footsteps/smoke-2").GetComponent();
- FootEffect[0] = rootModelTransform.Find("bip/pelvis/l-thigh/l-calf/l-ankle/l-foot/vfx-footsteps").GetComponent();
- FootEffect[1] = rootModelTransform.Find("bip/pelvis/r-thigh/r-calf/r-ankle/r-foot/vfx-footsteps").GetComponent();
- FootSmallSmoke[0] = rootModelTransform.Find("bip/pelvis/l-thigh/l-calf/l-ankle/l-foot/vfx-footsteps/smoke").GetComponent();
- FootSmallSmoke[1] = rootModelTransform.Find("bip/pelvis/r-thigh/r-calf/r-ankle/r-foot/vfx-footsteps/smoke").GetComponent();
- FootLargeSmoke[0] = rootModelTransform.Find("bip/pelvis/l-thigh/l-calf/l-ankle/l-foot/vfx-footsteps/smoke-2").GetComponent();
- FootLargeSmoke[1] = rootModelTransform.Find("bip/pelvis/r-thigh/r-calf/r-ankle/r-foot/vfx-footsteps/smoke-2").GetComponent();
+
+ WaterEffect[0] = rootModelTransform.Find("bip/pelvis/l-thigh/l-calf/l-ankle/l-foot/l-foot_end/vfx-footsteps/water").GetComponent();
+ WaterEffect[1] = rootModelTransform.Find("bip/pelvis/r-thigh/r-calf/r-ankle/r-foot/r-foot_end/vfx-footsteps/water").GetComponent();
+ FootEffect[0] = rootModelTransform.Find("bip/pelvis/l-thigh/l-calf/l-ankle/l-foot/l-foot_end/vfx-footsteps").GetComponent();
+ FootEffect[1] = rootModelTransform.Find("bip/pelvis/r-thigh/r-calf/r-ankle/r-foot/r-foot_end/vfx-footsteps").GetComponent();
+ FootSmallSmoke[0] = rootModelTransform.Find("bip/pelvis/l-thigh/l-calf/l-ankle/l-foot/l-foot_end/vfx-footsteps/smoke").GetComponent();
+ FootSmallSmoke[1] = rootModelTransform.Find("bip/pelvis/r-thigh/r-calf/r-ankle/r-foot/r-foot_end/vfx-footsteps/smoke").GetComponent();
+ FootLargeSmoke[0] = rootModelTransform.Find("bip/pelvis/l-thigh/l-calf/l-ankle/l-foot/l-foot_end/vfx-footsteps/smoke-2").GetComponent();
+ FootLargeSmoke[1] = rootModelTransform.Find("bip/pelvis/r-thigh/r-calf/r-ankle/r-foot/r-foot_end/vfx-footsteps/smoke-2").GetComponent();
solidSoundEvents[0] = "footsteps-0";
solidSoundEvents[1] = "footsteps-1";
@@ -340,13 +336,13 @@ private bool IsGrounded()
private void PlayFootsteps()
{
- float moveWeight = Mathf.Max(1f, Mathf.Pow(rootAnimation.RunSlow.weight + rootAnimation.RunFast.weight, 2f));
- bool trigger = (rootAnimation.RunSlow.enabled || rootAnimation.RunFast.enabled) && moveWeight > 0.15f;
+ float moveWeight = Mathf.Max(1f, Mathf.Pow(rootAnimation.run_slow.weight + rootAnimation.run_fast.weight, 2f));
+ bool trigger = (rootAnimation.run_slow.enabled || rootAnimation.run_fast.enabled) && moveWeight > 0.15f;
if (trigger)
{
- int normalizedTime = Mathf.FloorToInt(rootAnimation.RunFast.normalizedTime * 2f - 0.02f);
- float normalizedTimeDiff = (rootAnimation.RunFast.normalizedTime * 2f - 0.02f) - (float)normalizedTime;
+ int normalizedTime = Mathf.FloorToInt(rootAnimation.run_fast.normalizedTime * 2f - 0.02f);
+ float normalizedTimeDiff = (rootAnimation.run_fast.normalizedTime * 2f - 0.02f) - (float)normalizedTime;
bool timeIsEven = normalizedTime % 2 == 0;
if (lastTriggeredFood != normalizedTime)
@@ -439,7 +435,7 @@ private void PlayFootstepEffect(bool lr, float biomo, bool water)
}
ParticleSystem waterParticle = (!lr) ? WaterEffect[0] : WaterEffect[1];
- ParticleSystem[] smokeParticle = (!lr) ? FootSmokeEffect[0] : FootSmokeEffect[1];
+ ParticleSystem[] smokeParticle = (!lr) ? FootSmallSmoke : FootLargeSmoke;
ParticleSystem footEffect = (!lr) ? FootEffect[0] : FootEffect[1];
AmbientDesc ambientDesc = GameMain.galaxy.PlanetById(localPlanetId).ambientDesc;
Color color = Color.clear;
@@ -588,7 +584,7 @@ private void UpdateExtraSoundEffects(PlayerAnimationUpdate packet)
tmpMaxAltitude = 1000f;
}
- if (rootAnimation.RunSlow.enabled || rootAnimation.RunFast.enabled || rootAnimation.Drift.enabled || rootAnimation.DriftF.enabled || rootAnimation.DriftR.enabled || rootAnimation.DriftL.enabled)
+ if (rootAnimation.runWeight > 0.001f || rootAnimation.driftWeight > 0.001f)
{
bool ground = IsGrounded();
@@ -622,7 +618,7 @@ private void UpdateExtraSoundEffects(PlayerAnimationUpdate packet)
}
// NOTE: the pPhys can only be loaded if the player trying to load it has the planet actually loaded (meaning he is on the same planet or near it)
- if (pPhys != null && pFactory != null && packet.horzSpeed > 5f)
+ if (pPhys != null && pFactory != null && packet.HorzSpeed > 5f)
{
int number = Physics.OverlapSphereNonAlloc(base.transform.localPosition, 1.8f, collider, 1024, QueryTriggerInteraction.Collide);
for (int i = 0; i < number; i++)
@@ -655,8 +651,8 @@ private void UpdateExtraSoundEffects(PlayerAnimationUpdate packet)
public void UpdateState(PlayerAnimationUpdate packet)
{
- bool anyMovingAnimationActive = rootAnimation.RunSlow.enabled || rootAnimation.RunFast.enabled || rootAnimation.Fly.enabled || rootAnimation.Sail.enabled || rootAnimation.Drift.enabled || rootAnimation.DriftF.enabled || rootAnimation.DriftL.enabled || rootAnimation.DriftR.enabled || !IsGrounded();
- bool anyDriftActive = rootAnimation.Drift.enabled || rootAnimation.DriftR.enabled || rootAnimation.DriftL.enabled || rootAnimation.DriftF.enabled;
+ bool anyMovingAnimationActive = rootAnimation.runWeight > 0.001f || rootAnimation.flyWeight > 0.001f || rootAnimation.sailWeight > 0.001f || rootAnimation.driftWeight > 0.001f || !IsGrounded();
+ bool anyDriftActive = rootAnimation.driftWeight > 0.001f;
bool fireParticleOkay = psys != null && psysr != null && (psys[0] != null && psys[1] != null && psysr[0] != null && psysr[1] != null);
if (anyMovingAnimationActive)
@@ -664,7 +660,7 @@ public void UpdateState(PlayerAnimationUpdate packet)
UpdateExtraSoundEffects(packet);
if (fireParticleOkay)
{
- if ((!rootAnimation.RunSlow.enabled && !rootAnimation.RunFast.enabled) || anyDriftActive || rootAnimation.Sail.enabled)
+ if ((!rootAnimation.run_slow.enabled && !rootAnimation.run_fast.enabled) || anyDriftActive || rootAnimation.sailWeight > 0.001f)
{
for (int i = 0; i < psys.Length; i++)
{
@@ -688,20 +684,20 @@ public void UpdateState(PlayerAnimationUpdate packet)
}
for (int i = 0; i < psysr.Length; i++)
{
- if (rootAnimation.RunSlow.enabled || rootAnimation.RunFast.enabled)
+ if (rootAnimation.run_slow.enabled || rootAnimation.run_fast.enabled)
{
- if (rootAnimation.RunFast.weight != 0)
+ if (rootAnimation.run_fast.weight != 0)
{
// when flying over the planet
- psysr[i].lengthScale = Mathf.Lerp(-3.5f, -8f, Mathf.Max(packet.horzSpeed, packet.vertSpeed) * 0.04f);
+ psysr[i].lengthScale = Mathf.Lerp(-3.5f, -8f, Mathf.Max(packet.HorzSpeed, packet.VertSpeed) * 0.04f);
}
else
{
// when "walking" over water and moving in air without button press or while "walking" over water
- psysr[i].lengthScale = Mathf.Lerp(-3.5f, -8f, Mathf.Max(packet.horzSpeed, packet.vertSpeed) * 0.03f);
+ psysr[i].lengthScale = Mathf.Lerp(-3.5f, -8f, Mathf.Max(packet.HorzSpeed, packet.VertSpeed) * 0.03f);
}
}
- if (rootAnimation.Drift.enabled)
+ if (rootAnimation.drift_0.enabled)
{
// when in air without pressing spacebar
psysr[i].lengthScale = -3.5f;
@@ -719,10 +715,10 @@ public void UpdateState(PlayerAnimationUpdate packet)
driftAudio = null;
}
}
- if (rootAnimation.Fly.enabled)
+ if (rootAnimation.fly_0.enabled)
{
// when pressing spacebar but also when landing (Drift is disabled when landing)
- psysr[i].lengthScale = Mathf.Lerp(-3.5f, -10f, Mathf.Max(packet.horzSpeed, packet.vertSpeed) * 0.03f);
+ psysr[i].lengthScale = Mathf.Lerp(-3.5f, -10f, Mathf.Max(packet.HorzSpeed, packet.VertSpeed) * 0.03f);
if (flyAudio0 == null)
{
flyAudio0 = VFAudio.Create("fly-atmos", base.transform, Vector3.zero, false);
@@ -737,9 +733,9 @@ public void UpdateState(PlayerAnimationUpdate packet)
flyAudio0 = null;
}
}
- if (rootAnimation.Sail.enabled)
+ if (rootAnimation.sailWeight > 0.001f)
{
- psysr[i].lengthScale = Mathf.Lerp(-3.5f, -10f, Mathf.Max(packet.horzSpeed, packet.vertSpeed) * 15f);
+ psysr[i].lengthScale = Mathf.Lerp(-3.5f, -10f, Mathf.Max(packet.HorzSpeed, packet.VertSpeed) * 15f);
if (flyAudio1 == null)
{
flyAudio1 = VFAudio.Create("fly-space", base.transform, Vector3.zero, false);
@@ -772,7 +768,7 @@ public void UpdateState(PlayerAnimationUpdate packet)
}
}
- if (torchEffect != null && rootAnimation.Mining0.weight > 0.99f)
+ if (torchEffect != null && rootAnimation.miningWeight > 0.99f)
{
if (!torchEffect.isPlaying && miningAudio == null)
{
@@ -781,7 +777,7 @@ public void UpdateState(PlayerAnimationUpdate packet)
miningAudio?.Play();
}
}
- else if (torchEffect != null && rootAnimation.Mining0.weight <= 0.99f)
+ else if (torchEffect != null && rootAnimation.miningWeight <= 0.99f)
{
if (torchEffect.isPlaying)
{
@@ -796,5 +792,6 @@ public void UpdatePlanet(int localPlanet)
{
localPlanetId = localPlanet;
}
+
}
}
diff --git a/NebulaWorld/RemotePlayerModel.cs b/NebulaWorld/RemotePlayerModel.cs
index a8d41482e..add1b9e31 100644
--- a/NebulaWorld/RemotePlayerModel.cs
+++ b/NebulaWorld/RemotePlayerModel.cs
@@ -35,7 +35,6 @@ public RemotePlayerModel(ushort playerId, string username)
Object.Destroy(PlayerTransform.GetComponent());
Object.Destroy(PlayerTransform.GetComponent());
Object.Destroy(PlayerTransform.GetComponent());
- Object.Destroy(PlayerTransform.GetComponent());
Object.Destroy(PlayerTransform.GetComponent());
PlayerTransform.GetComponent().isKinematic = true;
@@ -43,6 +42,9 @@ public RemotePlayerModel(ushort playerId, string username)
Movement = PlayerTransform.gameObject.AddComponent();
Animator = PlayerTransform.gameObject.AddComponent();
Effects = PlayerTransform.gameObject.AddComponent();
+
+ PlayerTransform.GetComponent().Start();
+ PlayerTransform.GetComponent().enabled = false;
}
PlayerTransform.gameObject.name = $"Remote Player ({playerId})";
diff --git a/NebulaWorld/SimulatedWorld.cs b/NebulaWorld/SimulatedWorld.cs
index b1bb8f3d6..b8599d0ea 100644
--- a/NebulaWorld/SimulatedWorld.cs
+++ b/NebulaWorld/SimulatedWorld.cs
@@ -20,7 +20,7 @@ namespace NebulaWorld
///
public class SimulatedWorld : IDisposable
{
- sealed class ThreadSafe
+ private sealed class ThreadSafe
{
internal readonly Dictionary RemotePlayersModels = new Dictionary();
}
@@ -31,8 +31,10 @@ sealed class ThreadSafe
private LocalPlayerMovement localPlayerMovement;
private LocalPlayerAnimation localPlayerAnimation;
- public Locker GetRemotePlayersModels(out Dictionary remotePlayersModels) =>
- threadSafe.RemotePlayersModels.GetLocked(out remotePlayersModels);
+ public Locker GetRemotePlayersModels(out Dictionary remotePlayersModels)
+ {
+ return threadSafe.RemotePlayersModels.GetLocked(out remotePlayersModels);
+ }
public bool IsPlayerJoining { get; set; }
@@ -43,9 +45,9 @@ public SimulatedWorld()
public void Dispose()
{
- using (GetRemotePlayersModels(out var remotePlayersModels))
+ using (GetRemotePlayersModels(out Dictionary remotePlayersModels))
{
- foreach (var model in remotePlayersModels.Values)
+ foreach (RemotePlayerModel model in remotePlayersModels.Values)
{
model.Destroy();
}
@@ -55,6 +57,7 @@ public void Dispose()
UnityEngine.Object.Destroy(localPlayerMovement);
UnityEngine.Object.Destroy(localPlayerAnimation);
+ SetPauseIndicator(true);
}
public void SetupInitialPlayerState()
@@ -74,7 +77,7 @@ public void SetupInitialPlayerState()
LocalPlayer player = Multiplayer.Session.LocalPlayer as LocalPlayer;
// Assign our own color
- UpdatePlayerColor(Multiplayer.Session.LocalPlayer.Id, player.Data.MechaColor);
+ UpdatePlayerColor(Multiplayer.Session.LocalPlayer.Id, player.Data.MechaColors);
// If not a new client, we need to update the player position to put him where he was previously
if (player.IsClient && !player.IsNewPlayer)
@@ -154,7 +157,7 @@ public void OnAllPlayersSyncCompleted()
public void SpawnRemotePlayerModel(IPlayerData playerData)
{
- using (GetRemotePlayersModels(out var remotePlayersModels))
+ using (GetRemotePlayersModels(out Dictionary remotePlayersModels))
{
if (!remotePlayersModels.ContainsKey(playerData.PlayerId))
{
@@ -163,12 +166,12 @@ public void SpawnRemotePlayerModel(IPlayerData playerData)
}
}
- UpdatePlayerColor(playerData.PlayerId, playerData.MechaColor);
+ UpdatePlayerColor(playerData.PlayerId, playerData.MechaColors);
}
public void DestroyRemotePlayerModel(ushort playerId)
{
- using (GetRemotePlayersModels(out var remotePlayersModels))
+ using (GetRemotePlayersModels(out Dictionary remotePlayersModels))
{
if (remotePlayersModels.TryGetValue(playerId, out RemotePlayerModel player))
{
@@ -184,7 +187,7 @@ public void DestroyRemotePlayerModel(ushort playerId)
public void UpdateRemotePlayerPosition(PlayerMovement packet)
{
- using (GetRemotePlayersModels(out var remotePlayersModels))
+ using (GetRemotePlayersModels(out Dictionary remotePlayersModels))
{
if (remotePlayersModels.TryGetValue(packet.PlayerId, out RemotePlayerModel player))
{
@@ -195,11 +198,12 @@ public void UpdateRemotePlayerPosition(PlayerMovement packet)
public void UpdateRemotePlayerAnimation(PlayerAnimationUpdate packet)
{
- using (GetRemotePlayersModels(out var remotePlayersModels))
+ using (GetRemotePlayersModels(out Dictionary remotePlayersModels))
{
if (remotePlayersModels.TryGetValue(packet.PlayerId, out RemotePlayerModel player))
{
player.Animator.UpdateState(packet);
+
player.Effects.UpdateState(packet);
}
}
@@ -207,9 +211,13 @@ public void UpdateRemotePlayerAnimation(PlayerAnimationUpdate packet)
public void UpdateRemotePlayerWarpState(PlayerUseWarper packet)
{
- using (GetRemotePlayersModels(out var remotePlayersModels))
+ using (GetRemotePlayersModels(out Dictionary remotePlayersModels))
{
- if (packet.PlayerId == 0) packet.PlayerId = 1; // host sends himself as PlayerId 0 but clients see him as id 1
+ if (packet.PlayerId == 0)
+ {
+ packet.PlayerId = 1; // host sends himself as PlayerId 0 but clients see him as id 1
+ }
+
if (remotePlayersModels.TryGetValue(packet.PlayerId, out RemotePlayerModel player))
{
if (packet.WarpCommand)
@@ -226,14 +234,14 @@ public void UpdateRemotePlayerWarpState(PlayerUseWarper packet)
public void UpdateRemotePlayerDrone(NewDroneOrderPacket packet)
{
- using (GetRemotePlayersModels(out var remotePlayersModels))
+ using (GetRemotePlayersModels(out Dictionary remotePlayersModels))
{
if (remotePlayersModels.TryGetValue(packet.PlayerId, out RemotePlayerModel player))
{
//Setup drone of remote player based on the drone data
ref MechaDrone drone = ref player.PlayerInstance.mecha.drones[packet.DroneId];
MechaDroneLogic droneLogic = player.PlayerInstance.mecha.droneLogic;
- var tmpFactory = droneLogic.factory;
+ PlanetFactory tmpFactory = droneLogic.factory;
droneLogic.factory = GameMain.galaxy.PlanetById(packet.PlanetId).factory;
@@ -266,48 +274,61 @@ public void UpdateRemotePlayerDrone(NewDroneOrderPacket packet)
}
}
- public void UpdatePlayerColor(ushort playerId, Float3 color)
+ public void UpdatePlayerColor(ushort playerId, Float4[] colors)
{
- using (GetRemotePlayersModels(out var remotePlayersModels))
+ if (colors == null || colors.Length == 0)
{
- Transform transform;
+ return;
+ }
+
+ using (GetRemotePlayersModels(out Dictionary remotePlayersModels))
+ {
+ PlayerAnimator playerAnimator;
if (playerId == Multiplayer.Session.LocalPlayer.Id)
{
- transform = GameMain.data.mainPlayer.transform;
+ playerAnimator = GameMain.data.mainPlayer.animator;
}
else if (remotePlayersModels.TryGetValue(playerId, out RemotePlayerModel remotePlayerModel))
{
- transform = remotePlayerModel.PlayerTransform;
+ playerAnimator = remotePlayerModel.Animator.PlayerAnimator;
}
else
{
- Log.Error("Could not find the transform for player with ID " + playerId);
+ Log.Error("Could not find the playerAnimator for player with ID " + playerId);
return;
}
- Log.Info($"Changing color of player {playerId} to {color}");
-
- // Apply new color to each part of the mecha
- SkinnedMeshRenderer[] componentsInChildren = transform.gameObject.GetComponentsInChildren();
- foreach (Renderer r in componentsInChildren)
+ Log.Info($"Changing color of player {playerId}");
+ for (int i = 0; i < colors.Length; i++)
{
- if (r.material != null && r.material.name.StartsWith("icarus-armor", System.StringComparison.Ordinal))
- {
- r.material.SetColor("_Color", color.ToColor());
- }
+ Log.Info($"Color {i}: {colors[i]}");
}
+ playerAnimator.inst_armor_mat.SetColor("_Color", colors[0].ToColor() / 255);
+ playerAnimator.inst_armor_mat.SetColor("_Color2", colors[1].ToColor() / 255);
+ playerAnimator.inst_armor_mat.SetColor("_Color3", colors[2].ToColor() / 255);
+ playerAnimator.inst_armor_mat.SetColor("_SpecularColor", colors[5].ToColor() / 255);
+ playerAnimator.inst_armor_mat.SetColor("_SpecularColor3", colors[6].ToColor() / 255);
+ playerAnimator.inst_skelt_mat.SetColor("_Color", colors[0].ToColor() / 255);
+ playerAnimator.inst_skelt_mat.SetColor("_Color2", colors[1].ToColor() / 255);
+ playerAnimator.inst_skelt_mat.SetColor("_Color3", colors[2].ToColor() / 255);
+ playerAnimator.inst_skelt_mat.SetColor("_SpecularColor", colors[5].ToColor() / 255);
+ playerAnimator.inst_skelt_mat.SetColor("_SpecularColor3", colors[6].ToColor() / 255);
+ playerAnimator.inst_armor_light_mat.SetColor("_EmissionMask", colors[3].ToColor() / 255);
+ playerAnimator.inst_skelt_light_mat.SetColor("_EmissionMask", colors[4].ToColor() / 255);
+
// We changed our own color, so we have to let others know
if (Multiplayer.Session.LocalPlayer.Id == playerId)
{
- Multiplayer.Session.Network.SendPacket(new PlayerColorChanged(playerId, color));
+ GameMain.mainPlayer.mecha.mainColors = Float4.ToColor32(colors);
+ Multiplayer.Session.Network.SendPacket(new PlayerColorChanged(playerId, colors));
}
}
}
public int GenerateTrashOnPlayer(TrashSystemNewTrashCreatedPacket packet)
{
- using (GetRemotePlayersModels(out var remotePlayersModels))
+ using (GetRemotePlayersModels(out Dictionary remotePlayersModels))
{
if (remotePlayersModels.TryGetValue(packet.PlayerId, out RemotePlayerModel player))
{
@@ -338,7 +359,7 @@ public int GenerateTrashOnPlayer(TrashSystemNewTrashCreatedPacket packet)
public void OnDronesDraw()
{
- using (GetRemotePlayersModels(out var remotePlayersModels))
+ using (GetRemotePlayersModels(out Dictionary remotePlayersModels))
{
foreach (KeyValuePair remoteModel in remotePlayersModels)
{
@@ -356,17 +377,17 @@ public void OnDronesGameTick(float dt)
double tmp = 1e10; //fake energy of remote player, needed to do the Update()
double tmp2 = 1;
- using (GetRemotePlayersModels(out var remotePlayersModels))
+ using (GetRemotePlayersModels(out Dictionary remotePlayersModels))
{
//Update drones positions based on their targets
- var prebuildPool = GameMain.localPlanet?.factory?.prebuildPool;
+ PrebuildData[] prebuildPool = GameMain.localPlanet?.factory?.prebuildPool;
foreach (KeyValuePair remoteModel in remotePlayersModels)
{
Mecha remoteMecha = remoteModel.Value.MechaInstance;
MechaDrone[] drones = remoteMecha.drones;
int droneCount = remoteMecha.droneCount;
- var remotePosition = remoteModel.Value.Movement.GetLastPosition().LocalPlanetPosition.ToVector3();
+ Vector3 remotePosition = remoteModel.Value.Movement.GetLastPosition().LocalPlanetPosition.ToVector3();
for (int i = 0; i < droneCount; i++)
{
@@ -393,9 +414,9 @@ public void RenderPlayerNameTagsOnStarmap(UIStarmap starmap)
Text starmap_playerNameText = starmap.playerNameText;
Transform starmap_playerTrack = starmap.playerTrack;
- using (GetRemotePlayersModels(out var remotePlayersModels))
+ using (GetRemotePlayersModels(out Dictionary remotePlayersModels))
{
- foreach (var player in remotePlayersModels)
+ foreach (KeyValuePair player in remotePlayersModels)
{
RemotePlayerModel playerModel = player.Value;
@@ -450,13 +471,13 @@ public void RenderPlayerNameTagsOnStarmap(UIStarmap starmap)
if (playerModel.Movement.localPlanetId > 0)
{
PlanetData planet = GameMain.galaxy.PlanetById(playerModel.Movement.localPlanetId);
- var rotation = planet.runtimeRotation *
+ Quaternion rotation = planet.runtimeRotation *
Quaternion.LookRotation(playerModel.PlayerModelTransform.forward, playerModel.Movement.GetLastPosition().LocalPlanetPosition.ToVector3());
starmapTracker.rotation = rotation;
}
else
{
- var rotation = Quaternion.LookRotation(playerModel.PlayerModelTransform.forward, playerModel.PlayerTransform.localPosition);
+ Quaternion rotation = Quaternion.LookRotation(playerModel.PlayerModelTransform.forward, playerModel.PlayerTransform.localPosition);
starmapTracker.rotation = rotation;
}
@@ -472,9 +493,9 @@ public void RenderPlayerNameTagsOnStarmap(UIStarmap starmap)
public void ClearPlayerNameTagsOnStarmap()
{
- using (GetRemotePlayersModels(out var remotePlayersModels))
+ using (GetRemotePlayersModels(out Dictionary remotePlayersModels))
{
- foreach (var player in remotePlayersModels)
+ foreach (KeyValuePair player in remotePlayersModels)
{
// Destroy the marker and name so they don't linger and cause problems
GameObject.Destroy(player.Value.StarmapNameText.gameObject);
@@ -491,9 +512,9 @@ public void RenderPlayerNameTagsInGame()
{
TextMesh uiSailIndicator_targetText = null;
- using (GetRemotePlayersModels(out var remotePlayersModels))
+ using (GetRemotePlayersModels(out Dictionary remotePlayersModels))
{
- foreach (var player in remotePlayersModels)
+ foreach (KeyValuePair player in remotePlayersModels)
{
RemotePlayerModel playerModel = player.Value;
@@ -543,8 +564,8 @@ public void RenderPlayerNameTagsInGame()
playerNameText.transform.rotation = GameCamera.main.transform.rotation;
// Resizes the text based on distance from camera for better visual quality
- var distanceFromCamera = Vector3.Distance(playerNameText.transform.position, GameCamera.main.transform.position);
- var nameTextMesh = playerNameText.GetComponent();
+ float distanceFromCamera = Vector3.Distance(playerNameText.transform.position, GameCamera.main.transform.position);
+ TextMesh nameTextMesh = playerNameText.GetComponent();
if (distanceFromCamera > 100f)
{
@@ -608,9 +629,9 @@ public void UpdatePingIndicator(string text)
public void SetPauseIndicator(bool canPause)
{
//Tell the user if the game is paused or not
- var targetObject = GameObject.Find("UI Root/Overlay Canvas/In Game/Esc Menu/pause-text");
- var pauseText = targetObject?.GetComponent();
- var pauseLocalizer = targetObject?.GetComponent();
+ GameObject targetObject = GameObject.Find("UI Root/Overlay Canvas/In Game/Esc Menu/pause-text");
+ Text pauseText = targetObject?.GetComponent();
+ Localizer pauseLocalizer = targetObject?.GetComponent();
if (pauseText && pauseLocalizer)
{
if (!canPause)
@@ -624,7 +645,7 @@ public void SetPauseIndicator(bool canPause)
pauseLocalizer.stringKey = "游戏已暂停".Translate();
}
}
-
+
}
}
}
diff --git a/nuget.config b/nuget.config
index 4b1385e40..1864ded52 100644
--- a/nuget.config
+++ b/nuget.config
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/version.json b/version.json
index ff6748a6d..9c966362d 100644
--- a/version.json
+++ b/version.json
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
- "version": "0.5.0",
+ "version": "0.6.0",
"assemblyVersion": {
"precision": "build"
},