Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Item object sync #1076

Open
wants to merge 7 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 108 additions & 12 deletions source/E2E.Tests/Services/ItemObjects/ItemObjectSyncTest.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
using Common.Util;
using E2E.Tests.Environment;
using HarmonyLib;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using TaleWorlds.CampaignSystem;
using TaleWorlds.CampaignSystem.Settlements.Buildings;
using TaleWorlds.CampaignSystem.Siege;
using TaleWorlds.Core;
using TaleWorlds.Library;
using TaleWorlds.Localization;
using Xunit.Abstractions;

namespace E2E.Tests.Services.ItemObjectService
namespace E2E.Tests.Services.ItemObjects
{
public class ItemObjectSyncTest : IDisposable
{
Expand All @@ -35,34 +31,134 @@ public void ServerCreateItemObject_SyncAllClients()
string? itemObjectId = null;

var typeField = AccessTools.Field(typeof(ItemObject), nameof(ItemObject.Type));

var typeIntercept = TestEnvironment.GetIntercept(typeField);


var culture = new BasicCultureObject() { Name = new TextObject("Battania") };
var weaponDesign = ObjectHelper.SkipConstructor<WeaponDesign>();
var holsterPositionShift = new Vec3(1, 2, 3, 4);
string[] itemHolsters = { "holster12", "holster23", "holster34" };
var itemComponent = new TradeItemComponent();
var itemCategory = ObjectHelper.SkipConstructor<ItemCategory>();
var prerequisiteItem = new ItemObject();
var itemTypeEnum = ItemObject.ItemTypeEnum.OneHandedWeapon;

server.Call(() =>
{
ItemObject itemObject = new ItemObject();
Assert.True(server.ObjectManager.TryGetId(itemObject, out itemObjectId));

itemObject.Weight = 3.5f;
itemObject.Name = new TextObject("Name");
itemObject.MultiMeshName = "MultiMeshName";
itemObject.HolsterMeshName = "HolsterMeshName";
itemObject.HolsterWithWeaponMeshName = "WithWeaponMeshName";
itemObject.HolsterPositionShift = holsterPositionShift;
itemObject.FlyingMeshName = "FlyingMeshName";
itemObject.BodyName = "BodyName";
itemObject.HolsterBodyName = "HolsterBodyName";
itemObject.CollisionBodyName = "CollisionBodyName";
itemObject.RecalculateBody = false;
itemObject.Culture = culture;
itemObject.Difficulty = 1;
itemObject.ScaleFactor = 3.5f;
itemObject.ItemFlags = ItemFlags.Civilian;
itemObject.Appearance = 3.5f;
itemObject.WeaponDesign = weaponDesign;
itemObject.ItemHolsters = itemHolsters;

//Rest of Properties
itemObject.ItemComponent = itemComponent;
itemObject.HasLowerHolsterPriority = true;
itemObject.PrefabName = "PrefabName";
itemObject.ItemCategory = itemCategory;
itemObject.Value = 1;
itemObject.Effectiveness = 3.5f;
itemObject.IsUsingTableau = true;
itemObject.ArmBandMeshName = "ArmBandMeshName";
itemObject.IsFood = true;
itemObject.IsUniqueItem = true;
itemObject.MultiplayerItem = true;
itemObject.NotMerchandise = true;
itemObject.IsCraftedByPlayer = true;
itemObject.LodAtlasIndex = 1;
itemObject.PrerequisiteItem = prerequisiteItem;
itemObject.ItemType = itemTypeEnum;
});

// Assert
Assert.True(server.ObjectManager.TryGetObject(itemObjectId, out ItemObject itemObject));

server.Call(() =>
{
typeIntercept.Invoke(null, new object[] { itemObject, 69 });
//typeIntercept.Invoke(null, new object[] { itemObject, 69 });
});

server.ObjectManager.TryGetId(itemObject, out string serverObjectId);
Assert.True(server.ObjectManager.TryGetId(itemObject, out string serverObjectId));
Assert.True(server.ObjectManager.TryGetId(itemObject.Culture, out string serverCultureId));
Assert.True(server.ObjectManager.TryGetId(itemObject.WeaponDesign, out string serverWeaponDesignId));
Assert.True(server.ObjectManager.TryGetId(itemObject.ItemHolsters, out string serverItemHolstersId));
Assert.True(server.ObjectManager.TryGetId(itemObject.ItemComponent, out string serverItemComponentId));
Assert.True(server.ObjectManager.TryGetId(itemObject.ItemCategory, out string serverItemCategoryId));
Assert.True(server.ObjectManager.TryGetId(itemObject.PrerequisiteItem, out string serverPrerequisiteItemId));

foreach (var client in TestEnvironment.Clients)
{
Assert.True(client.ObjectManager.TryGetObject(serverObjectId, out ItemObject clientItemObject));

//Field
Assert.Equal(itemObject.Type, clientItemObject.Type);

client.ObjectManager.TryGetId(clientItemObject, out string clientObjectId);

Assert.True(client.ObjectManager.TryGetId(clientItemObject, out string clientObjectId));
Assert.True(client.ObjectManager.TryGetId(clientItemObject.Culture, out string clientCultureId));
Assert.True(client.ObjectManager.TryGetId(clientItemObject.WeaponDesign, out string clientWeaponDesignId));
Assert.True(client.ObjectManager.TryGetId(clientItemObject.ItemHolsters, out string clientItemHolstersId));
Assert.True(client.ObjectManager.TryGetId(clientItemObject.ItemComponent, out string clientItemComponentId));
Assert.True(client.ObjectManager.TryGetId(clientItemObject.ItemCategory, out string clientItemCategoryId));
Assert.True(client.ObjectManager.TryGetId(clientItemObject.PrerequisiteItem, out string clientPrerequisiteItemId));
Assert.Equal(serverObjectId, clientObjectId);


//Properties
Assert.Equal(3.5f, clientItemObject.Weight);
Assert.Equal("Name", clientItemObject.Name.ToString());
Assert.Equal("MultiMeshName", clientItemObject.MultiMeshName);
Assert.Equal("HolsterMeshName", clientItemObject.HolsterMeshName);
Assert.Equal("WithWeaponMeshName", clientItemObject.HolsterWithWeaponMeshName);
Assert.Equal(holsterPositionShift, clientItemObject.HolsterPositionShift);
Assert.Equal("FlyingMeshName", clientItemObject.FlyingMeshName);
Assert.Equal("BodyName", clientItemObject.BodyName);
Assert.Equal("HolsterBodyName", clientItemObject.HolsterBodyName);
Assert.Equal("CollisionBodyName", clientItemObject.CollisionBodyName);
Assert.False(clientItemObject.RecalculateBody);
Assert.Equal(clientCultureId, serverCultureId);
Assert.Equal(1, clientItemObject.Difficulty);
Assert.Equal(3.5f, clientItemObject.ScaleFactor);
Assert.Equal(ItemFlags.Civilian, clientItemObject.ItemFlags);
Assert.Equal(3.5f, clientItemObject.Appearance);
Assert.Equal(clientWeaponDesignId, serverWeaponDesignId);

//Rest of Properties
Assert.Equal(serverItemComponentId, clientItemComponentId);
Assert.True(clientItemObject.HasLowerHolsterPriority);
Assert.Equal("PrefabName", clientItemObject.PrefabName);
Assert.Equal(serverItemCategoryId, clientItemCategoryId);
Assert.Equal(1, clientItemObject.Value);
Assert.Equal(3.5f, clientItemObject.Effectiveness);
Assert.True(clientItemObject.IsUsingTableau);
Assert.Equal("ArmBandMeshName", clientItemObject.ArmBandMeshName);
Assert.True(clientItemObject.IsFood);
Assert.True(clientItemObject.IsUniqueItem);
Assert.True(clientItemObject.MultiplayerItem);
Assert.True(clientItemObject.NotMerchandise);
Assert.True(clientItemObject.IsCraftedByPlayer);
Assert.Equal(1, clientItemObject.LodAtlasIndex);
Assert.Equal(serverPrerequisiteItemId, clientPrerequisiteItemId);
Assert.Equal(ItemObject.ItemTypeEnum.OneHandedWeapon, clientItemObject.ItemType);

//Collection
Assert.Equal(itemHolsters, clientItemObject.ItemHolsters);
Assert.Equal(itemHolsters[0], clientItemObject.ItemHolsters[0]);
Assert.Equal(serverItemHolstersId, clientItemHolstersId);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion source/GameInterface.Tests/GameInterface.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Lib.Harmony" Version="2.3.3" />
<PackageReference Include="Lib.Harmony" Version="2.3.5" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="MonoMod.RuntimeDetour" Version="22.7.31.1" />
<PackageReference Include="MonoMod.Utils" Version="22.7.31.1" />
Expand Down
39 changes: 39 additions & 0 deletions source/GameInterface/Services/ItemObjects/ItemObjectSync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,46 @@ public class ItemObjectSync : IAutoSync
{
public ItemObjectSync(IAutoSyncBuilder autoSyncBuilder)
{
//Fields
autoSyncBuilder.AddField(AccessTools.Field(typeof(ItemObject), nameof(ItemObject.Type)));

//Properties
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.Weight)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.Name)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.MultiMeshName)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.HolsterMeshName)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.HolsterWithWeaponMeshName)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.HolsterPositionShift)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.FlyingMeshName)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.BodyName)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.HolsterBodyName)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.CollisionBodyName)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.RecalculateBody)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.Culture)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.Difficulty)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.ScaleFactor)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.ItemFlags)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.Appearance)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.WeaponDesign)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.ItemComponent)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.HasLowerHolsterPriority)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.PrefabName)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.ItemCategory)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.Value)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.Effectiveness)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.IsUsingTableau)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.ArmBandMeshName)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.IsFood)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.IsUniqueItem)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.MultiplayerItem)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.NotMerchandise)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.IsCraftedByPlayer)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.LodAtlasIndex)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.PrerequisiteItem)));
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.ItemType)));

//Collection
autoSyncBuilder.AddProperty(AccessTools.Property(typeof(ItemObject), nameof(ItemObject.ItemHolsters)));
}
}
}
111 changes: 111 additions & 0 deletions source/GameInterface/Surrogates/ArmorComponentSurrogate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
using Common.Util;
using ProtoBuf;
using System;
using System.Collections.Generic;
using TaleWorlds.Core;

namespace GameInterface.Surrogates
{
[ProtoContract]
internal struct ArmorComponentSurrogate
{
[ProtoMember(1)]
public ItemObject Item { get; set; }
[ProtoMember(2)]
public ItemModifierGroup ItemModifierGroup { get; set; }
[ProtoMember(3)]
public int HeadArmor { get; set; }
[ProtoMember(4)]
public int BodyArmor { get; set; }
[ProtoMember(5)]
public int LegArmor { get; set; }
[ProtoMember(6)]
public int ArmArmor { get; set; }
[ProtoMember(7)]
public int ManeuverBonus { get; set; }
[ProtoMember(8)]
public int SpeedBonus { get; set; }
[ProtoMember(9)]
public int ChargeBonus { get; set; }
[ProtoMember(10)]
public int FamilyType { get; set; }
[ProtoMember(11)]
public ArmorComponent.ArmorMaterialTypes MaterialType { get; set; }
[ProtoMember(12)]
public SkinMask MeshesMask { get; set; }
[ProtoMember(13)]
public ArmorComponent.BodyMeshTypes BodyMeshType { get; set; }
[ProtoMember(14)]
public ArmorComponent.BodyDeformTypes BodyDeformType { get; set; }
[ProtoMember(15)]
public ArmorComponent.HairCoverTypes HairCoverType { get; set; }
[ProtoMember(16)]
public ArmorComponent.BeardCoverTypes BeardCoverType { get; set; }
[ProtoMember(17)]
public ArmorComponent.HorseHarnessCoverTypes ManeCoverType { get; set; }
[ProtoMember(18)]
public ArmorComponent.HorseTailCoverTypes TailCoverType { get; set; }
[ProtoMember(19)]
public string ReinsMesh { get; set; }


public ArmorComponentSurrogate(ArmorComponent armorComponent)
{
if (armorComponent == null)
{
Item = ObjectHelper.SkipConstructor<ItemObject>();
ItemModifierGroup = ObjectHelper.SkipConstructor<ItemModifierGroup>();
HeadArmor = -1;
BodyArmor = -1;
LegArmor = -1;
ArmArmor = -1;
ManeuverBonus = -1;
SpeedBonus = -1;
ChargeBonus = -1;
FamilyType = -1;
MaterialType = ArmorComponent.ArmorMaterialTypes.None;
MeshesMask = ObjectHelper.SkipConstructor<SkinMask>();
BodyMeshType = ArmorComponent.BodyMeshTypes.Normal;
BodyDeformType = ArmorComponent.BodyDeformTypes.Medium;
HairCoverType = ArmorComponent.HairCoverTypes.None;
BeardCoverType = ArmorComponent.BeardCoverTypes.None;
ManeCoverType = ArmorComponent.HorseHarnessCoverTypes.None;
TailCoverType = ArmorComponent.HorseTailCoverTypes.None;
ReinsMesh = "";

}
else
{
Item = armorComponent.Item;
ItemModifierGroup = armorComponent.ItemModifierGroup;
HeadArmor = armorComponent.HeadArmor;
BodyArmor = armorComponent.BodyArmor;
LegArmor = armorComponent.LegArmor;
ArmArmor = armorComponent.ArmArmor;
ManeuverBonus = armorComponent.ManeuverBonus;
SpeedBonus = armorComponent.SpeedBonus;
ChargeBonus = armorComponent.ChargeBonus;
FamilyType = armorComponent.FamilyType;
MaterialType = armorComponent.MaterialType;
MeshesMask = armorComponent.MeshesMask;
BodyMeshType = armorComponent.BodyMeshType;
BodyDeformType = armorComponent.BodyDeformType;
HairCoverType = armorComponent.HairCoverType;
BeardCoverType = armorComponent.BeardCoverType;
ManeCoverType = armorComponent.ManeCoverType;
TailCoverType = armorComponent.TailCoverType;
ReinsMesh = armorComponent.ReinsMesh;
}
}

public static implicit operator ArmorComponentSurrogate(ArmorComponent armorComponent)
{
return new ArmorComponentSurrogate(armorComponent);
}

public static implicit operator ArmorComponent(ArmorComponentSurrogate surrogate)
{
return new ArmorComponent(surrogate.Item);
}
}
}
Loading
Loading