Compare commits
2 Commits
0776da883f
...
8ac2f2df1c
| Author | SHA1 | Date | |
|---|---|---|---|
| 8ac2f2df1c | |||
| b351e0c707 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,6 +1,7 @@
|
|||||||
# Logs / local debug output
|
# Logs / local debug output
|
||||||
output*.txt
|
output*.txt
|
||||||
*.log
|
*.log
|
||||||
|
/log.txt
|
||||||
|
|
||||||
# OS junk
|
# OS junk
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ using KCM.Packets.Game.GameVillager;
|
|||||||
using KCM.Packets.State;
|
using KCM.Packets.State;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace KCM.StateManagement.Sync
|
namespace KCM.StateManagement.Sync
|
||||||
@@ -151,78 +151,83 @@ namespace KCM.StateManagement.Sync
|
|||||||
|
|
||||||
private static byte[] BuildBuildingSnapshotPayload(List<Building> buildings, ref int startIndex)
|
private static byte[] BuildBuildingSnapshotPayload(List<Building> buildings, ref int startIndex)
|
||||||
{
|
{
|
||||||
using (var ms = new MemoryStream())
|
byte[] buffer = new byte[MaxBuildingSnapshotBytes];
|
||||||
using (var bw = new BinaryWriter(ms))
|
int offset = 0;
|
||||||
{
|
int countOffset = offset;
|
||||||
long countPos = ms.Position;
|
if (!TryWriteInt32(buffer, ref offset, 0))
|
||||||
bw.Write(0); // placeholder for record count
|
return new byte[0];
|
||||||
int written = 0;
|
|
||||||
|
|
||||||
|
int written = 0;
|
||||||
for (; startIndex < buildings.Count; startIndex++)
|
for (; startIndex < buildings.Count; startIndex++)
|
||||||
{
|
{
|
||||||
Building b = buildings[startIndex];
|
Building b = buildings[startIndex];
|
||||||
if (b == null)
|
if (b == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
long before = ms.Position;
|
int before = offset;
|
||||||
try
|
if (!TryWriteBuildingRecord(buffer, ref offset, b))
|
||||||
{
|
{
|
||||||
WriteBuildingRecord(bw, b);
|
offset = before;
|
||||||
written++;
|
startIndex++;
|
||||||
}
|
break;
|
||||||
catch
|
|
||||||
{
|
|
||||||
ms.Position = before;
|
|
||||||
ms.SetLength(before);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ms.Length >= MaxBuildingSnapshotBytes)
|
written++;
|
||||||
|
|
||||||
|
if (offset >= MaxBuildingSnapshotBytes - 256)
|
||||||
{
|
{
|
||||||
startIndex++;
|
startIndex++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long endPos = ms.Position;
|
WriteInt32At(buffer, countOffset, written);
|
||||||
ms.Position = countPos;
|
byte[] result = new byte[offset];
|
||||||
bw.Write(written);
|
Buffer.BlockCopy(buffer, 0, result, 0, offset);
|
||||||
ms.Position = endPos;
|
return result;
|
||||||
|
|
||||||
return ms.ToArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WriteBuildingRecord(BinaryWriter bw, Building b)
|
private static bool TryWriteBuildingRecord(byte[] buffer, ref int offset, Building b)
|
||||||
{
|
{
|
||||||
bw.Write(b.TeamID());
|
if (!TryWriteInt32(buffer, ref offset, b.TeamID()))
|
||||||
bw.Write(b.guid.ToByteArray());
|
return false;
|
||||||
|
if (!TryWriteGuidBytes(buffer, ref offset, b.guid))
|
||||||
|
return false;
|
||||||
|
|
||||||
bw.Write(b.UniqueName ?? "");
|
if (!TryWriteString(buffer, ref offset, b.UniqueName ?? ""))
|
||||||
bw.Write(b.customName ?? "");
|
return false;
|
||||||
|
if (!TryWriteString(buffer, ref offset, b.customName ?? ""))
|
||||||
|
return false;
|
||||||
|
|
||||||
Vector3 globalPosition = b.transform.position;
|
Vector3 globalPosition = b.transform.position;
|
||||||
Quaternion rotation = b.transform.childCount > 0 ? b.transform.GetChild(0).rotation : b.transform.rotation;
|
Quaternion rotation = b.transform.childCount > 0 ? b.transform.GetChild(0).rotation : b.transform.rotation;
|
||||||
Vector3 localPosition = b.transform.childCount > 0 ? b.transform.GetChild(0).localPosition : Vector3.zero;
|
Vector3 localPosition = b.transform.childCount > 0 ? b.transform.GetChild(0).localPosition : Vector3.zero;
|
||||||
|
|
||||||
bw.Write(globalPosition.x);
|
if (!TryWriteSingle(buffer, ref offset, globalPosition.x) ||
|
||||||
bw.Write(globalPosition.y);
|
!TryWriteSingle(buffer, ref offset, globalPosition.y) ||
|
||||||
bw.Write(globalPosition.z);
|
!TryWriteSingle(buffer, ref offset, globalPosition.z))
|
||||||
|
return false;
|
||||||
|
|
||||||
bw.Write(rotation.x);
|
if (!TryWriteSingle(buffer, ref offset, rotation.x) ||
|
||||||
bw.Write(rotation.y);
|
!TryWriteSingle(buffer, ref offset, rotation.y) ||
|
||||||
bw.Write(rotation.z);
|
!TryWriteSingle(buffer, ref offset, rotation.z) ||
|
||||||
bw.Write(rotation.w);
|
!TryWriteSingle(buffer, ref offset, rotation.w))
|
||||||
|
return false;
|
||||||
|
|
||||||
bw.Write(localPosition.x);
|
if (!TryWriteSingle(buffer, ref offset, localPosition.x) ||
|
||||||
bw.Write(localPosition.y);
|
!TryWriteSingle(buffer, ref offset, localPosition.y) ||
|
||||||
bw.Write(localPosition.z);
|
!TryWriteSingle(buffer, ref offset, localPosition.z))
|
||||||
|
return false;
|
||||||
|
|
||||||
bw.Write(b.IsBuilt());
|
if (!TryWriteBool(buffer, ref offset, b.IsBuilt()) ||
|
||||||
bw.Write(b.IsPlaced());
|
!TryWriteBool(buffer, ref offset, b.IsPlaced()) ||
|
||||||
bw.Write(b.Open);
|
!TryWriteBool(buffer, ref offset, b.Open) ||
|
||||||
bw.Write(b.doBuildAnimation);
|
!TryWriteBool(buffer, ref offset, b.doBuildAnimation) ||
|
||||||
bw.Write(b.constructionPaused);
|
!TryWriteBool(buffer, ref offset, b.constructionPaused))
|
||||||
bw.Write(b.constructionProgress);
|
return false;
|
||||||
|
|
||||||
|
if (!TryWriteSingle(buffer, ref offset, b.constructionProgress))
|
||||||
|
return false;
|
||||||
|
|
||||||
float resourceProgress = 0f;
|
float resourceProgress = 0f;
|
||||||
try
|
try
|
||||||
@@ -232,10 +237,12 @@ namespace KCM.StateManagement.Sync
|
|||||||
resourceProgress = (float)field.GetValue(b);
|
resourceProgress = (float)field.GetValue(b);
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
bw.Write(resourceProgress);
|
if (!TryWriteSingle(buffer, ref offset, resourceProgress))
|
||||||
|
return false;
|
||||||
|
|
||||||
bw.Write(b.Life);
|
if (!TryWriteSingle(buffer, ref offset, b.Life) ||
|
||||||
bw.Write(b.ModifiedMaxLife);
|
!TryWriteSingle(buffer, ref offset, b.ModifiedMaxLife))
|
||||||
|
return false;
|
||||||
|
|
||||||
int yearBuilt = 0;
|
int yearBuilt = 0;
|
||||||
try
|
try
|
||||||
@@ -245,48 +252,218 @@ namespace KCM.StateManagement.Sync
|
|||||||
yearBuilt = (int)field.GetValue(b);
|
yearBuilt = (int)field.GetValue(b);
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
bw.Write(yearBuilt);
|
if (!TryWriteInt32(buffer, ref offset, yearBuilt))
|
||||||
|
return false;
|
||||||
|
|
||||||
bw.Write(b.decayProtection);
|
if (!TryWriteSingle(buffer, ref offset, b.decayProtection))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ApplyBuildingSnapshot(byte[] payload)
|
public static void ApplyBuildingSnapshot(byte[] payload)
|
||||||
{
|
{
|
||||||
using (var ms = new MemoryStream(payload))
|
if (payload == null || payload.Length < 4)
|
||||||
using (var br = new BinaryReader(ms))
|
return;
|
||||||
{
|
|
||||||
int count = br.ReadInt32();
|
int offset = 0;
|
||||||
|
int count;
|
||||||
|
if (!TryReadInt32(payload, ref offset, out count))
|
||||||
|
return;
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
int teamId = br.ReadInt32();
|
int teamId;
|
||||||
Guid guid = new Guid(br.ReadBytes(16));
|
Guid guid;
|
||||||
|
string uniqueName;
|
||||||
|
string customName;
|
||||||
|
Vector3 globalPosition;
|
||||||
|
Quaternion rotation;
|
||||||
|
Vector3 localPosition;
|
||||||
|
bool built;
|
||||||
|
bool placed;
|
||||||
|
bool open;
|
||||||
|
bool doBuildAnimation;
|
||||||
|
bool constructionPaused;
|
||||||
|
float constructionProgress;
|
||||||
|
float resourceProgress;
|
||||||
|
float life;
|
||||||
|
float modifiedMaxLife;
|
||||||
|
int yearBuilt;
|
||||||
|
float decayProtection;
|
||||||
|
|
||||||
string uniqueName = br.ReadString();
|
if (!TryReadInt32(payload, ref offset, out teamId))
|
||||||
string customName = br.ReadString();
|
break;
|
||||||
|
if (!TryReadGuid(payload, ref offset, out guid))
|
||||||
|
break;
|
||||||
|
if (!TryReadString(payload, ref offset, out uniqueName))
|
||||||
|
break;
|
||||||
|
if (!TryReadString(payload, ref offset, out customName))
|
||||||
|
break;
|
||||||
|
|
||||||
Vector3 globalPosition = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
|
float gx, gy, gz;
|
||||||
Quaternion rotation = new Quaternion(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
|
float rx, ry, rz, rw;
|
||||||
Vector3 localPosition = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
|
float lx, ly, lz;
|
||||||
|
if (!TryReadSingle(payload, ref offset, out gx) ||
|
||||||
|
!TryReadSingle(payload, ref offset, out gy) ||
|
||||||
|
!TryReadSingle(payload, ref offset, out gz))
|
||||||
|
break;
|
||||||
|
globalPosition = new Vector3(gx, gy, gz);
|
||||||
|
|
||||||
bool built = br.ReadBoolean();
|
if (!TryReadSingle(payload, ref offset, out rx) ||
|
||||||
bool placed = br.ReadBoolean();
|
!TryReadSingle(payload, ref offset, out ry) ||
|
||||||
bool open = br.ReadBoolean();
|
!TryReadSingle(payload, ref offset, out rz) ||
|
||||||
bool doBuildAnimation = br.ReadBoolean();
|
!TryReadSingle(payload, ref offset, out rw))
|
||||||
bool constructionPaused = br.ReadBoolean();
|
break;
|
||||||
float constructionProgress = br.ReadSingle();
|
rotation = new Quaternion(rx, ry, rz, rw);
|
||||||
float resourceProgress = br.ReadSingle();
|
|
||||||
float life = br.ReadSingle();
|
if (!TryReadSingle(payload, ref offset, out lx) ||
|
||||||
float modifiedMaxLife = br.ReadSingle();
|
!TryReadSingle(payload, ref offset, out ly) ||
|
||||||
int yearBuilt = br.ReadInt32();
|
!TryReadSingle(payload, ref offset, out lz))
|
||||||
float decayProtection = br.ReadSingle();
|
break;
|
||||||
|
localPosition = new Vector3(lx, ly, lz);
|
||||||
|
|
||||||
|
if (!TryReadBool(payload, ref offset, out built) ||
|
||||||
|
!TryReadBool(payload, ref offset, out placed) ||
|
||||||
|
!TryReadBool(payload, ref offset, out open) ||
|
||||||
|
!TryReadBool(payload, ref offset, out doBuildAnimation) ||
|
||||||
|
!TryReadBool(payload, ref offset, out constructionPaused))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!TryReadSingle(payload, ref offset, out constructionProgress) ||
|
||||||
|
!TryReadSingle(payload, ref offset, out resourceProgress) ||
|
||||||
|
!TryReadSingle(payload, ref offset, out life) ||
|
||||||
|
!TryReadSingle(payload, ref offset, out modifiedMaxLife) ||
|
||||||
|
!TryReadInt32(payload, ref offset, out yearBuilt) ||
|
||||||
|
!TryReadSingle(payload, ref offset, out decayProtection))
|
||||||
|
break;
|
||||||
|
|
||||||
ApplyBuildingRecord(teamId, guid, uniqueName, customName, globalPosition, rotation, localPosition, built, placed, open, doBuildAnimation, constructionPaused, constructionProgress, resourceProgress, life, modifiedMaxLife, yearBuilt, decayProtection);
|
ApplyBuildingRecord(teamId, guid, uniqueName, customName, globalPosition, rotation, localPosition, built, placed, open, doBuildAnimation, constructionPaused, constructionProgress, resourceProgress, life, modifiedMaxLife, yearBuilt, decayProtection);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
TryRefreshFieldSystem();
|
TryRefreshFieldSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool EnsureCapacity(byte[] buffer, int offset, int bytesToWrite)
|
||||||
|
{
|
||||||
|
return buffer != null && offset >= 0 && (offset + bytesToWrite) <= buffer.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryWriteInt32(byte[] buffer, ref int offset, int value)
|
||||||
|
{
|
||||||
|
if (!EnsureCapacity(buffer, offset, 4))
|
||||||
|
return false;
|
||||||
|
byte[] bytes = BitConverter.GetBytes(value);
|
||||||
|
Buffer.BlockCopy(bytes, 0, buffer, offset, 4);
|
||||||
|
offset += 4;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteInt32At(byte[] buffer, int offset, int value)
|
||||||
|
{
|
||||||
|
if (!EnsureCapacity(buffer, offset, 4))
|
||||||
|
return;
|
||||||
|
byte[] bytes = BitConverter.GetBytes(value);
|
||||||
|
Buffer.BlockCopy(bytes, 0, buffer, offset, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryWriteSingle(byte[] buffer, ref int offset, float value)
|
||||||
|
{
|
||||||
|
if (!EnsureCapacity(buffer, offset, 4))
|
||||||
|
return false;
|
||||||
|
byte[] bytes = BitConverter.GetBytes(value);
|
||||||
|
Buffer.BlockCopy(bytes, 0, buffer, offset, 4);
|
||||||
|
offset += 4;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryWriteBool(byte[] buffer, ref int offset, bool value)
|
||||||
|
{
|
||||||
|
if (!EnsureCapacity(buffer, offset, 1))
|
||||||
|
return false;
|
||||||
|
buffer[offset++] = (byte)(value ? 1 : 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryWriteGuidBytes(byte[] buffer, ref int offset, Guid guid)
|
||||||
|
{
|
||||||
|
if (!EnsureCapacity(buffer, offset, 16))
|
||||||
|
return false;
|
||||||
|
byte[] bytes = guid.ToByteArray();
|
||||||
|
Buffer.BlockCopy(bytes, 0, buffer, offset, 16);
|
||||||
|
offset += 16;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryWriteString(byte[] buffer, ref int offset, string value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
value = "";
|
||||||
|
|
||||||
|
byte[] bytes = Encoding.UTF8.GetBytes(value);
|
||||||
|
if (!TryWriteInt32(buffer, ref offset, bytes.Length))
|
||||||
|
return false;
|
||||||
|
if (!EnsureCapacity(buffer, offset, bytes.Length))
|
||||||
|
return false;
|
||||||
|
Buffer.BlockCopy(bytes, 0, buffer, offset, bytes.Length);
|
||||||
|
offset += bytes.Length;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryReadInt32(byte[] buffer, ref int offset, out int value)
|
||||||
|
{
|
||||||
|
value = 0;
|
||||||
|
if (!EnsureCapacity(buffer, offset, 4))
|
||||||
|
return false;
|
||||||
|
value = BitConverter.ToInt32(buffer, offset);
|
||||||
|
offset += 4;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryReadSingle(byte[] buffer, ref int offset, out float value)
|
||||||
|
{
|
||||||
|
value = 0f;
|
||||||
|
if (!EnsureCapacity(buffer, offset, 4))
|
||||||
|
return false;
|
||||||
|
value = BitConverter.ToSingle(buffer, offset);
|
||||||
|
offset += 4;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryReadBool(byte[] buffer, ref int offset, out bool value)
|
||||||
|
{
|
||||||
|
value = false;
|
||||||
|
if (!EnsureCapacity(buffer, offset, 1))
|
||||||
|
return false;
|
||||||
|
value = buffer[offset++] != 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryReadGuid(byte[] buffer, ref int offset, out Guid value)
|
||||||
|
{
|
||||||
|
value = Guid.Empty;
|
||||||
|
if (!EnsureCapacity(buffer, offset, 16))
|
||||||
|
return false;
|
||||||
|
byte[] bytes = new byte[16];
|
||||||
|
Buffer.BlockCopy(buffer, offset, bytes, 0, 16);
|
||||||
|
offset += 16;
|
||||||
|
value = new Guid(bytes);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryReadString(byte[] buffer, ref int offset, out string value)
|
||||||
|
{
|
||||||
|
value = "";
|
||||||
|
int len;
|
||||||
|
if (!TryReadInt32(buffer, ref offset, out len))
|
||||||
|
return false;
|
||||||
|
if (len < 0 || !EnsureCapacity(buffer, offset, len))
|
||||||
|
return false;
|
||||||
|
value = len == 0 ? "" : Encoding.UTF8.GetString(buffer, offset, len);
|
||||||
|
offset += len;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static void ApplyBuildingRecord(int teamId, Guid guid, string uniqueName, string customName, Vector3 globalPosition, Quaternion rotation, Vector3 localPosition, bool built, bool placed, bool open, bool doBuildAnimation, bool constructionPaused, float constructionProgress, float resourceProgress, float life, float modifiedMaxLife, int yearBuilt, float decayProtection)
|
private static void ApplyBuildingRecord(int teamId, Guid guid, string uniqueName, string customName, Vector3 globalPosition, Quaternion rotation, Vector3 localPosition, bool built, bool placed, bool open, bool doBuildAnimation, bool constructionPaused, float constructionProgress, float resourceProgress, float life, float modifiedMaxLife, int yearBuilt, float decayProtection)
|
||||||
{
|
{
|
||||||
Player p = Main.GetPlayerByTeamID(teamId);
|
Player p = Main.GetPlayerByTeamID(teamId);
|
||||||
|
|||||||
Reference in New Issue
Block a user