Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
jhett12321 committed Oct 8, 2022
2 parents e21d0f9 + 17194e7 commit c57ee09
Show file tree
Hide file tree
Showing 11 changed files with 330 additions and 20 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,25 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## 8193.34.20
https://github.com/nwn-dotnet/Anvil/compare/v8193.34.19...v8193.34.20

### Added
- CollectionExtensions: Added IList `AddRange` extension.
- NwCreature: Added `IsBartering` property.
- NwObject: Added `TryGetUUID` method.
- NwObject: Added `SerializeToJson` method.
- NwStore: Added `BuyStolenGoods`, `MarkDown`, `MarkDownStolen`, `MarkUp`, `WillNotBuyItems`, `WillOnlyBuyItems` properties.

### Package Updates
- LightInject: 6.5.1 -> 6.6.1

### Changed
- Exposed Json engine structure.

### Fixed
- VirtualMachine: Fixed an issue where ObjectSelf would not be correctly assigned.

## 8193.34.19
https://github.com/nwn-dotnet/Anvil/compare/v8193.34.18...v8193.34.19

Expand Down
2 changes: 1 addition & 1 deletion NWN.Anvil.TestRunner/NWN.Anvil.TestRunner.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.1" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="all" />
</ItemGroup>
Expand Down
65 changes: 65 additions & 0 deletions NWN.Anvil.Tests/src/main/Services/API/Utils/VirtualMachineTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Anvil.API;
using Anvil.Services;
using NUnit.Framework;

namespace Anvil.Tests.Services.API.Utils
{
[TestFixture(Category = "Services.API")]
public sealed class VirtualMachineTests
{
[Inject]
private static VirtualMachine VirtualMachine { get; set; } = null!;

[Inject]
private static ScriptHandleFactory ScriptHandleFactory { get; set; } = null!;

[Test(Description = "Running ExecuteScript correctly executes the specified script with the right object context.")]
[Timeout(5000)]
public void ExecuteScriptAssignsCorrectObjectSelf()
{
foreach (NwObject nwObject in GetTestObjects())
{
ExecuteScript(nwObject);
}
}

[Test(Description = "Running ExecuteScript in the main loop correctly executes the specified script with the right object context.")]
[Timeout(5000)]
public async Task ExecuteScriptInvalidContextAssignsCorrectObjectSelf()
{
await NwTask.NextFrame();
foreach (NwObject nwObject in GetTestObjects())
{
ExecuteScript(nwObject);
}
}

private void ExecuteScript(NwObject nwObject)
{
string scriptParamKey = "someParamKey";
string scriptParamValue = "someParamValue";

ScriptCallbackHandle handle = ScriptHandleFactory.CreateUniqueHandler(info =>
{
Assert.That(info.ObjectSelf, Is.EqualTo(nwObject));
Assert.That(info.ScriptParams[scriptParamKey], Is.EqualTo(scriptParamValue));
return ScriptHandleResult.Handled;
});

VirtualMachine.Execute(handle.ScriptName, nwObject, (scriptParamKey, scriptParamValue));
}

private static IEnumerable<NwObject> GetTestObjects()
{
yield return NwModule.Instance;

foreach (NwGameObject gameObject in NwModule.Instance.Areas.First().Objects)
{
yield return gameObject;
}
}
}
}
2 changes: 1 addition & 1 deletion NWN.Anvil/NWN.Anvil.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="LightInject" Version="6.5.1" />
<PackageReference Include="LightInject" Version="6.6.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NLog" Version="5.0.4" />
<PackageReference Include="Paket.Core" Version="7.1.5" PrivateAssets="all" />
Expand Down
12 changes: 11 additions & 1 deletion NWN.Anvil/src/main/API/EngineStructure/Json.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Anvil.API
{
internal sealed class Json : EngineStructure
public sealed class Json : EngineStructure
{
internal Json(IntPtr handle, bool memoryOwn) : base(handle, memoryOwn) {}

Expand All @@ -23,5 +23,15 @@ public string Dump()
{
return NWScript.JsonDump(this);
}

public NwObject? ToNwObject(Location location, NwGameObject? owner = null, bool loadObjectState = true)
{
return NWScript.JsonToObject(this, location, owner, loadObjectState.ToInt()).ToNwObject();
}

public T? ToNwObject<T>(Location location, NwGameObject? owner = null, bool loadObjectState = true) where T : NwObject
{
return NWScript.JsonToObject(this, location, owner, loadObjectState.ToInt()).ToNwObject<T>();
}
}
}
21 changes: 21 additions & 0 deletions NWN.Anvil/src/main/API/Extensions/CollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,27 @@ public static bool ContainsElement<TKey, TValue, TCollection>(this IDictionary<T
return mutableLookup.TryGetValue(key, out TCollection? values) && values.Contains(value);
}

/// <summary>
/// Adds a range of values to the specified IList.
/// </summary>
/// <param name="list">The list to update.</param>
/// <param name="values">The elements to add to the list.</param>
/// <typeparam name="T">The list element type.</typeparam>
public static void AddRange<T>(this IList<T> list, IEnumerable<T> values)
{
if (list is List<T> genericList)
{
genericList.AddRange(values);
}
else
{
foreach (T value in values)
{
list.Add(value);
}
}
}

public static void DisposeAll(this IEnumerable<IDisposable?>? disposables)
{
if (disposables == null)
Expand Down
5 changes: 5 additions & 0 deletions NWN.Anvil/src/main/API/Object/NwCreature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,11 @@ public bool Immortal
/// </summary>
public Inventory Inventory { get; }

/// <summary>
/// Gets a value indicating whether this creature is currently bartering.
/// </summary>
public bool IsBartering => Creature.m_pBarterInfo?.m_bWindowOpen.ToBool() == true;

/// <summary>
/// Gets a value indicating whether this creature is a dead NPC, dead PC, or dying PC.
/// </summary>
Expand Down
41 changes: 36 additions & 5 deletions NWN.Anvil/src/main/API/Object/NwObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,23 +142,26 @@ public string Tag
/// <summary>
/// Gets the globally unique identifier for this object.
/// </summary>
/// <remarks>
/// If the UUID conflicts with an existing object, a new one will be generated.<br/>
/// Use <see cref="TryGetUUID"/> to control this behaviour.
/// </remarks>
public Guid UUID
{
get
{
if (this == Invalid)
if (!IsValid)
{
return Guid.Empty;
}

string uid = NWScript.GetObjectUUID(this);
if (string.IsNullOrEmpty(uid))
if (!TryGetUUID(out Guid uid))
{
ForceRefreshUUID();
uid = NWScript.GetObjectUUID(this);
TryGetUUID(out uid);
}

return Guid.TryParse(uid, out Guid guid) ? guid : Guid.Empty;
return uid;
}
}

Expand Down Expand Up @@ -334,6 +337,34 @@ public override string ToString()
return ObjectId.ToString("x");
}

/// <summary>
/// Attempts to get the UUID for this object, assigning a new ID if it does not already exist.<br/>
/// </summary>
/// <remarks>See <see cref="PeekUUID"/> to check if the object has an existing UUID, without creating a new one.<br/>
/// This function will return false if the UUID is not globally unique, and conflicts with an existing object.
/// </remarks>
/// <param name="uid">The object's UUID.</param>
/// <returns>True if the object has a valid unique identifier, otherwise false.</returns>
public bool TryGetUUID(out Guid uid)
{
string uidString = NWScript.GetObjectUUID(this);
if (!string.IsNullOrEmpty(uidString))
{
return Guid.TryParse(uidString, out uid);
}

uid = Guid.Empty;
return false;
}

/// <summary>
/// Serializes this game object to a json representation
/// </summary>
public Json SerializeToJson(bool saveObjectState)
{
return NWScript.ObjectToJson(this, saveObjectState.ToInt());
}

/// <summary>
/// Notifies then awaits for this object to become the current active object for the purpose of implicitly assigned values (e.g. effect creators).<br/>
/// If the current active object is already this object, then the code runs immediately. Otherwise, it will be run with all other closures.<br/>
Expand Down
90 changes: 79 additions & 11 deletions NWN.Anvil/src/main/API/Object/NwStore.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Anvil.Native;
using NWN.Core;
using NWN.Native.API;

Expand Down Expand Up @@ -27,6 +28,15 @@ internal NwStore(CNWSStore store) : base(store)
this.store = store;
}

/// <summary>
/// Gets or sets if this store purchases stolen goods.
/// </summary>
public bool BuyStolenGoods
{
get => Store.m_bBlackMarket.ToBool();
set => Store.m_bBlackMarket = value.ToInt();
}

/// <summary>
/// Gets the current customers of this store.
/// </summary>
Expand Down Expand Up @@ -55,10 +65,14 @@ public IReadOnlyList<NwCreature> CurrentCustomers
/// </summary>
public int CustomerCount => Store.m_aCurrentCustomers.Count;

/// <summary>
/// Gets or sets the amount this store charges to identify an item.<br/>
/// Returns -1 if the store does not identify items.
/// </summary>
public int IdentifyCost
{
get => NWScript.GetStoreIdentifyCost(this);
set => NWScript.SetStoreIdentifyCost(this, value);
get => Store.m_iIdentifyCost;
set => Store.m_iIdentifyCost = value;
}

/// <summary>
Expand All @@ -75,16 +89,71 @@ public IEnumerable<NwItem> Items
}
}

/// <summary>
/// Gets or sets the base markdown price for items sold to this store.
/// </summary>
public int MarkDown
{
get => Store.m_nMarkDown;
set => Store.m_nMarkDown = value;
}

/// <summary>
/// Gets or sets the base markdown price for stolen items sold to this store.
/// </summary>
public int MarkDownStolen
{
get => Store.m_nBlackMarketMarkDown;
set => Store.m_nBlackMarketMarkDown = value;
}

/// <summary>
/// Gets or sets the base markup price for items in the store's inventory.
/// </summary>
public int MarkUp
{
get => Store.m_nMarkUp;
set => Store.m_nMarkUp = value;
}

/// <summary>
/// Gets or sets the maximum price this store will pay for an item.<br/>
/// Returns -1 if the store has no limit.
/// </summary>
public int MaxBuyPrice
{
get => NWScript.GetStoreMaxBuyPrice(this);
set => NWScript.SetStoreMaxBuyPrice(this, value);
get => Store.m_iMaxBuyPrice;
set => Store.m_iMaxBuyPrice = value;
}

public int StoreGold
{
get => NWScript.GetStoreGold(this);
set => NWScript.SetStoreGold(this, value);
get => Store.m_iGold;
set => Store.m_iGold = value;
}

/// <summary>
/// Gets the list of base item types that this store will not buy.<br/>
/// Has precedence over <see cref="WillOnlyBuyItems"/>.
/// </summary>
public IList<NwBaseItem?> WillNotBuyItems
{
get
{
return new ListWrapper<int, NwBaseItem?>(Store.m_lstWillNotBuy, NwBaseItem.FromItemId, item => (int)(item?.Id ?? 0));
}
}

/// <summary>
/// Gets the list of base item types that this store will only buy.<br/>
/// Does nothing if <see cref="WillNotBuyItems"/> is populated.
/// </summary>
public IList<NwBaseItem?> WillOnlyBuyItems
{
get
{
return new ListWrapper<int, NwBaseItem?>(Store.m_lstWillOnlyBuy, NwBaseItem.FromItemId, item => (int)(item?.Id ?? 0));
}
}

public static NwStore? Create(string template, Location location, bool useAppearAnim = false, string newTag = "")
Expand Down Expand Up @@ -124,13 +193,12 @@ public int StoreGold
return store?.Store;
}

/// <summary>
/// Adds the specified item to this store's inventory.
/// </summary>
/// <param name="item">The item to add.</param>
public void AcquireItem(NwItem item)
{
if (item == null)
{
throw new ArgumentNullException(nameof(item), "Item cannot be null.");
}

Store.AcquireItem(item.Item, true.ToInt(), 0xFF, 0xFF);
}

Expand Down
2 changes: 1 addition & 1 deletion NWN.Anvil/src/main/API/Utils/VirtualMachine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public void Execute(string scriptName, NwObject? target, params (string ParamNam
NWScript.SetScriptParam(paramName, paramValue);
}

NWScript.ExecuteScript(scriptName, target);
virtualMachine.RunScript(scriptName.ToExoString(), target);
}

/// <summary>
Expand Down
Loading

0 comments on commit c57ee09

Please sign in to comment.