2023-12-25 02:15:33 -05:00
using System.Collections.Generic ;
2022-11-17 14:59:45 +01:00
using System.Linq ;
2023-07-08 14:08:32 +10:00
using System.Numerics ;
2022-11-17 14:59:45 +01:00
using Content.Server.Cargo.Components ;
2022-06-23 14:36:47 +10:00
using Content.Server.Cargo.Systems ;
2024-06-03 12:24:32 -04:00
using Content.Server.Nutrition.Components ;
using Content.Server.Nutrition.EntitySystems ;
2022-06-23 14:36:47 +10:00
using Content.Shared.Cargo.Prototypes ;
2024-06-03 12:24:32 -04:00
using Content.Shared.IdentityManagement ;
2023-03-27 04:01:42 +11:00
using Content.Shared.Stacks ;
2024-06-03 12:24:32 -04:00
using Content.Shared.Tag ;
using Content.Shared.Whitelist ;
2022-06-23 14:36:47 +10:00
using Robust.Shared.GameObjects ;
using Robust.Shared.Map ;
using Robust.Shared.Prototypes ;
namespace Content.IntegrationTests.Tests ;
[TestFixture]
public sealed class CargoTest
2024-11-18 14:40:52 +03:00
{ / *
2024-07-02 20:01:37 -04:00
private static readonly HashSet < ProtoId < CargoProductPrototype > > Ignored =
[
2023-12-25 02:15:33 -05:00
// This is ignored because it is explicitly intended to be able to sell for more than it costs.
new ( "FunCrateGambling" )
2024-07-02 20:01:37 -04:00
] ;
2023-12-25 02:15:33 -05:00
2022-06-23 14:36:47 +10:00
[Test]
2022-09-15 11:53:17 +10:00
public async Task NoCargoOrderArbitrage ( )
2022-06-23 14:36:47 +10:00
{
2023-08-25 02:56:51 +02:00
await using var pair = await PoolManager . GetServerClient ( ) ;
var server = pair . Server ;
2022-06-23 14:36:47 +10:00
2023-08-25 04:13:11 +02:00
var testMap = await pair . CreateTestMap ( ) ;
2023-01-01 16:58:18 -05:00
2022-06-23 14:36:47 +10:00
var entManager = server . ResolveDependency < IEntityManager > ( ) ;
var protoManager = server . ResolveDependency < IPrototypeManager > ( ) ;
var pricing = server . ResolveDependency < IEntitySystemManager > ( ) . GetEntitySystem < PricingSystem > ( ) ;
await server . WaitAssertion ( ( ) = >
{
2023-01-15 21:57:59 +13:00
Assert . Multiple ( ( ) = >
2022-06-23 14:36:47 +10:00
{
2023-01-15 21:57:59 +13:00
foreach ( var proto in protoManager . EnumeratePrototypes < CargoProductPrototype > ( ) )
{
2023-12-25 02:15:33 -05:00
if ( Ignored . Contains ( proto . ID ) )
continue ;
var ent = entManager . SpawnEntity ( proto . Product , testMap . MapCoords ) ;
2023-01-15 21:57:59 +13:00
var price = pricing . GetPrice ( ent ) ;
2022-06-23 14:36:47 +10:00
2024-01-19 22:47:08 -05:00
Assert . That ( price , Is . AtMost ( proto . Cost ) , $"Found arbitrage on {proto.ID} cargo product! Cost is {proto.Cost} but sell is {price}!" ) ;
2023-01-15 21:57:59 +13:00
entManager . DeleteEntity ( ent ) ;
}
} ) ;
2022-06-23 14:36:47 +10:00
} ) ;
2022-09-15 11:53:17 +10:00
2023-08-25 02:56:51 +02:00
await pair . CleanReturnAsync ( ) ;
2022-06-23 14:36:47 +10:00
}
2023-06-22 07:49:33 -04:00
[Test]
2023-10-29 04:21:02 +11:00
public async Task NoCargoBountyArbitrageTest ( )
2023-06-22 07:49:33 -04:00
{
2023-08-25 02:56:51 +02:00
await using var pair = await PoolManager . GetServerClient ( ) ;
var server = pair . Server ;
2023-06-22 07:49:33 -04:00
2023-08-25 04:13:11 +02:00
var testMap = await pair . CreateTestMap ( ) ;
2023-06-22 07:49:33 -04:00
var entManager = server . ResolveDependency < IEntityManager > ( ) ;
var mapManager = server . ResolveDependency < IMapManager > ( ) ;
var protoManager = server . ResolveDependency < IPrototypeManager > ( ) ;
var cargo = entManager . System < CargoSystem > ( ) ;
var bounties = protoManager . EnumeratePrototypes < CargoBountyPrototype > ( ) . ToList ( ) ;
await server . WaitAssertion ( ( ) = >
{
var mapId = testMap . MapId ;
Assert . Multiple ( ( ) = >
{
foreach ( var proto in protoManager . EnumeratePrototypes < CargoProductPrototype > ( ) )
{
var ent = entManager . SpawnEntity ( proto . Product , new MapCoordinates ( Vector2 . Zero , mapId ) ) ;
foreach ( var bounty in bounties )
{
if ( cargo . IsBountyComplete ( ent , bounty ) )
2024-01-19 22:47:08 -05:00
Assert . That ( proto . Cost , Is . GreaterThanOrEqualTo ( bounty . Reward ) , $"Found arbitrage on {bounty.ID} cargo bounty! Product {proto.ID} costs {proto.Cost} but fulfills bounty {bounty.ID} with reward {bounty.Reward}!" ) ;
2023-06-22 07:49:33 -04:00
}
entManager . DeleteEntity ( ent ) ;
}
} ) ;
mapManager . DeleteMap ( mapId ) ;
} ) ;
2023-08-25 02:56:51 +02:00
await pair . CleanReturnAsync ( ) ;
2023-06-22 07:49:33 -04:00
}
2022-11-17 14:59:45 +01:00
[Test]
public async Task NoStaticPriceAndStackPrice ( )
{
2023-08-25 02:56:51 +02:00
await using var pair = await PoolManager . GetServerClient ( ) ;
var server = pair . Server ;
2022-11-17 14:59:45 +01:00
2023-08-25 04:13:11 +02:00
var testMap = await pair . CreateTestMap ( ) ;
2023-01-01 16:58:18 -05:00
2022-11-17 14:59:45 +01:00
var entManager = server . ResolveDependency < IEntityManager > ( ) ;
var mapManager = server . ResolveDependency < IMapManager > ( ) ;
var protoManager = server . ResolveDependency < IPrototypeManager > ( ) ;
await server . WaitAssertion ( ( ) = >
{
2023-01-01 16:58:18 -05:00
var mapId = testMap . MapId ;
2024-01-20 17:15:10 +11:00
var grid = mapManager . CreateGridEntity ( mapId ) ;
2022-12-12 14:59:02 +11:00
var coord = new EntityCoordinates ( grid . Owner , 0 , 0 ) ;
2022-11-17 14:59:45 +01:00
var protoIds = protoManager . EnumeratePrototypes < EntityPrototype > ( )
2023-07-05 21:54:25 -07:00
. Where ( p = > ! p . Abstract )
2023-08-25 02:56:51 +02:00
. Where ( p = > ! pair . IsTestPrototype ( p ) )
2023-05-16 06:36:45 -05:00
. Where ( p = > ! p . Components . ContainsKey ( "MapGrid" ) ) // Grids are not for sale.
2022-11-17 14:59:45 +01:00
. Select ( p = > p . ID )
. ToList ( ) ;
foreach ( var proto in protoIds )
{
var ent = entManager . SpawnEntity ( proto , coord ) ;
if ( entManager . TryGetComponent < StackPriceComponent > ( ent , out var stackpricecomp )
& & stackpricecomp . Price > 0 )
{
if ( entManager . TryGetComponent < StaticPriceComponent > ( ent , out var staticpricecomp ) )
2023-01-01 16:58:18 -05:00
{
2022-11-17 14:59:45 +01:00
Assert . That ( staticpricecomp . Price , Is . EqualTo ( 0 ) ,
2023-03-27 04:01:42 +11:00
$"The prototype {proto} has a StackPriceComponent and StaticPriceComponent whose values are not compatible with each other." ) ;
2023-01-01 16:58:18 -05:00
}
2022-11-17 14:59:45 +01:00
}
2023-03-27 04:01:42 +11:00
if ( entManager . HasComponent < StackComponent > ( ent ) )
{
if ( entManager . TryGetComponent < StaticPriceComponent > ( ent , out var staticpricecomp ) )
{
Assert . That ( staticpricecomp . Price , Is . EqualTo ( 0 ) ,
$"The prototype {proto} has a StackComponent and StaticPriceComponent whose values are not compatible with each other." ) ;
}
}
2022-11-17 14:59:45 +01:00
entManager . DeleteEntity ( ent ) ;
}
mapManager . DeleteMap ( mapId ) ;
} ) ;
2023-04-25 11:48:29 +12:00
2023-08-25 02:56:51 +02:00
await pair . CleanReturnAsync ( ) ;
2022-11-17 14:59:45 +01:00
}
2023-03-27 04:01:42 +11:00
2024-06-03 12:24:32 -04:00
/// <summary>
/// Tests to see if any items that are valid for cargo bounties can be sliced into items that
/// are also valid for the same bounty entry.
/// </summary>
[Test]
public async Task NoSliceableBountyArbitrageTest ( )
{
await using var pair = await PoolManager . GetServerClient ( ) ;
var server = pair . Server ;
var testMap = await pair . CreateTestMap ( ) ;
var entManager = server . ResolveDependency < IEntityManager > ( ) ;
var mapManager = server . ResolveDependency < IMapManager > ( ) ;
var protoManager = server . ResolveDependency < IPrototypeManager > ( ) ;
var componentFactory = server . ResolveDependency < IComponentFactory > ( ) ;
var whitelist = entManager . System < EntityWhitelistSystem > ( ) ;
var cargo = entManager . System < CargoSystem > ( ) ;
var sliceableSys = entManager . System < SliceableFoodSystem > ( ) ;
var bounties = protoManager . EnumeratePrototypes < CargoBountyPrototype > ( ) . ToList ( ) ;
await server . WaitAssertion ( ( ) = >
{
var mapId = testMap . MapId ;
var grid = mapManager . CreateGridEntity ( mapId ) ;
var coord = new EntityCoordinates ( grid . Owner , 0 , 0 ) ;
var sliceableEntityProtos = protoManager . EnumeratePrototypes < EntityPrototype > ( )
. Where ( p = > ! p . Abstract )
. Where ( p = > ! pair . IsTestPrototype ( p ) )
. Where ( p = > p . TryGetComponent < SliceableFoodComponent > ( out _ , componentFactory ) )
. Select ( p = > p . ID )
. ToList ( ) ;
foreach ( var proto in sliceableEntityProtos )
{
var ent = entManager . SpawnEntity ( proto , coord ) ;
var sliceable = entManager . GetComponent < SliceableFoodComponent > ( ent ) ;
// Check each bounty
foreach ( var bounty in bounties )
{
// Check each entry in the bounty
foreach ( var entry in bounty . Entries )
{
// See if the entity counts as part of this bounty entry
if ( ! cargo . IsValidBountyEntry ( ent , entry ) )
continue ;
// Spawn a slice
var slice = entManager . SpawnEntity ( sliceable . Slice , coord ) ;
// See if the slice also counts for this bounty entry
if ( ! cargo . IsValidBountyEntry ( slice , entry ) )
{
entManager . DeleteEntity ( slice ) ;
continue ;
}
entManager . DeleteEntity ( slice ) ;
// If for some reason it can only make one slice, that's okay, I guess
Assert . That ( sliceable . TotalCount , Is . EqualTo ( 1 ) , $"{proto} counts as part of cargo bounty {bounty.ID} and slices into {sliceable.TotalCount} slices which count for the same bounty!" ) ;
}
}
entManager . DeleteEntity ( ent ) ;
}
mapManager . DeleteMap ( mapId ) ;
} ) ;
await pair . CleanReturnAsync ( ) ;
}
2023-08-05 16:16:48 +12:00
[TestPrototypes]
private const string StackProto = @ "
2023-03-27 04:01:42 +11:00
- type : entity
id : A
- type : stack
id : StackProto
spawn : A
- type : entity
id : StackEnt
components :
- type : StackPrice
price : 20
- type : Stack
stackType : StackProto
count : 5
";
2023-08-05 16:16:48 +12:00
[Test]
public async Task StackPrice ( )
{
2023-08-25 02:56:51 +02:00
await using var pair = await PoolManager . GetServerClient ( ) ;
var server = pair . Server ;
2023-03-27 04:01:42 +11:00
var entManager = server . ResolveDependency < IEntityManager > ( ) ;
2024-08-31 12:35:30 +10:00
await server . WaitAssertion ( ( ) = >
{
2024-08-31 07:49:20 +02:00
var priceSystem = entManager . System < PricingSystem > ( ) ;
2024-08-31 12:35:30 +10:00
var ent = entManager . SpawnEntity ( "StackEnt" , MapCoordinates . Nullspace ) ;
var price = priceSystem . GetPrice ( ent ) ;
Assert . That ( price , Is . EqualTo ( 100.0 ) ) ;
} ) ;
2023-03-27 04:01:42 +11:00
2023-08-25 02:56:51 +02:00
await pair . CleanReturnAsync ( ) ;
2024-11-18 14:40:52 +03:00
} * /
2022-06-23 14:36:47 +10:00
}