Skip to content

Commit

Permalink
Merge branch 'new-frontiers-14:master' into 2024-01-03-ReEmag
Browse files Browse the repository at this point in the history
  • Loading branch information
dvir001 authored Jan 9, 2024
2 parents 2e9997c + 0277223 commit 8521272
Show file tree
Hide file tree
Showing 47 changed files with 2,189 additions and 2,473 deletions.
42 changes: 41 additions & 1 deletion .github/mapchecker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,31 @@ directory which are marked as `DO NOT MAP`, `DEBUG`, ... and verifies that map c

## Usage

Glad I do not have to write this myself! Get detailed help information by running: `./mapchecker.py --help`
Glad I do not have to write this myself! Get detailed help information by running:
`python3 .github/mapchecker/mapchecker.py --help`

The following help block is printed:
```
usage: mapchecker.py [-h] [-v] [-p PROTOTYPES_PATH [PROTOTYPES_PATH ...]] [-m MAP_PATH [MAP_PATH ...]] [-w WHITELIST]
Map prototype usage checker for Frontier Station 14.
options:
-h, --help show this help message and exit
-v, --verbose Sets log level to DEBUG if present, spitting out a lot more information. False by default,.
-p PROTOTYPES_PATH [PROTOTYPES_PATH ...], --prototypes_path PROTOTYPES_PATH [PROTOTYPES_PATH ...]
Directory holding entity prototypes. Default: All entity prototypes in the Frontier Station 14 codebase.
-m MAP_PATH [MAP_PATH ...], --map_path MAP_PATH [MAP_PATH ...]
Map PROTOTYPES or directory of map prototypes to check. Can mix and match.Default: All maps in the Frontier Station 14 codebase.
-w WHITELIST, --whitelist WHITELIST
YML file that lists map names and prototypes to allow for them.
```

You should generally not need to configure `-p`, `-m` or `-w`, as they are autofilled with sensible defaults. You can do
this:
- Set `-p` to only check against prototypes in a specific directory.
- Set `-m` to just check a specific map. (Make sure to **point it at the prototype**, not the map file itself!)
- Set `-v` with `-m` set as per above to get detailed information about a possible rejection for just that map.

## Configuration

Expand All @@ -31,3 +54,20 @@ If a map has a prototype and you believe it should be whitelisted, add a key for
gameMap prototype), and add the prototype ID's to its list.

The whitelist the checker uses by default is `.github/mapchecker/whitelist.yml`.

## Shuttle group override

It is possible that a shuttle is set to group `None` because it is only used in custom shipyard listings. In this case,
you can force the MapChecker script to treat it as a different shipyard group by adding the following to the vessel
prototype:

```yml
...
group: None
# Add this line below.
mapchecker_group_override: ShipyardGroupHere
...
```

Note that for now this will cause a warning to be generated, but it will not cause a failure if the shuttle matches the
criteria for the overridden group.
14 changes: 13 additions & 1 deletion .github/mapchecker/mapchecker.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
# Collect all prototypes and sort into the collectors.
for proto_file in proto_paths:
with open(proto_file, "r") as proto:
logger.debug(f"Reading prototype file '{proto_file}'.")
file_data = yaml.load(proto, Loader=YamlLoaderIgnoringTags)
if file_data is None:
continue
Expand All @@ -146,7 +147,6 @@
for item in conditionally_illegal_prototypes[key]:
logger.debug(f" - {item}")


# ==================================================================================================================
# PHASE 2: Check all maps in map_proto_paths for illegal prototypes.

Expand All @@ -164,6 +164,9 @@
map_name = map_proto # The map name that will be reported over output.
map_file_location = None
shipyard_group = None # Shipyard group of this map, if it's a shuttle.
# Shipyard override of this map, in the case it's a custom shipyard shuttle but needs to be treated as a
# specific group.
shipyard_override = None

for item in file_data:
if item["type"] == "gameMap":
Expand All @@ -174,6 +177,7 @@
if item["type"] == "vessel":
# This yaml entry is a vessel descriptor!
shipyard_group = item["group"] if "group" in item.keys() else None
shipyard_override = item["mapchecker_group_override"] if "mapchecker_group_override" in item.keys() else None

if map_file_location is None:
# Silently skip. If the map doesn't have a mapPath, it won't appear in game anyways.
Expand All @@ -185,6 +189,14 @@
logger.warning(f"Map '{map_name}' (from prototype '{map_proto}') was blanket-whitelisted. Skipping it.")
continue

if shipyard_override is not None:
# Log a warning, indicating the override and the normal group this shuttle belongs to, then set
# shipyard_group to the override.
logger.warning(f"Map '{map_name}' (from prototype '{map_proto}') is using mapchecker_group_override. "
f"This map will be treated as a '{shipyard_override}' shuttle. (Normally: "
f"'{shipyard_group}'))")
shipyard_group = shipyard_override

logger.debug(f"Starting checks for '{map_name}' (Path: '{map_file_location}' | Shipyard: '{shipyard_group}')")

# Now construct a temporary list of all prototype ID's that are illegal for this map based on conditionals.
Expand Down
100 changes: 100 additions & 0 deletions Content.IntegrationTests/Tests/_NF/ShipyardTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
using System.Linq;
using Content.Server.Cargo.Systems;
using Content.Shared.Shipyard.Prototypes;
using Robust.Server.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Prototypes;

namespace Content.IntegrationTests.Tests._NF;

[TestFixture]
public sealed class ShipyardTest
{
[Test]
public async Task CheckAllShuttleGrids()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;

var entManager = server.ResolveDependency<IEntityManager>();
var protoManager = server.ResolveDependency<IPrototypeManager>();
var mapLoader = entManager.System<MapLoaderSystem>();
var mapManager = server.ResolveDependency<IMapManager>();

await server.WaitPost(() =>
{
Assert.Multiple(() =>
{
foreach (var vessel in protoManager.EnumeratePrototypes<VesselPrototype>())
{
var mapId = mapManager.CreateMap();
try
{
Assert.That(mapLoader.TryLoad(mapId, vessel.ShuttlePath.ToString(), out var roots));
Assert.That(roots.Where(uid => entManager.HasComponent<MapGridComponent>(uid)), Is.Not.Empty);
}
catch (Exception ex)
{
throw new Exception($"Failed to load shuttle {vessel.ShuttlePath}", ex);
}
try
{
mapManager.DeleteMap(mapId);
}
catch (Exception ex)
{
throw new Exception($"Failed to delete map {vessel.ShuttlePath}", ex);
}
}
});
});
await server.WaitRunTicks(1);
await pair.CleanReturnAsync();
}

[Test]
public async Task NoShipyardShipArbitrage()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;

var entManager = server.ResolveDependency<IEntityManager>();
var mapLoader = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<MapLoaderSystem>();
var mapManager = server.ResolveDependency<IMapManager>();
var protoManager = server.ResolveDependency<IPrototypeManager>();
var pricing = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<PricingSystem>();

await server.WaitAssertion(() =>
{
Assert.Multiple(() =>
{
foreach (var vessel in protoManager.EnumeratePrototypes<VesselPrototype>())
{
var mapId = mapManager.CreateMap();
double combinedPrice = 0;
Assert.That(mapLoader.TryLoad(mapId, vessel.ShuttlePath.ToString(), out var roots));
var shuttle = roots.FirstOrDefault(uid => entManager.HasComponent<MapGridComponent>(uid));
pricing.AppraiseGrid(shuttle, null, (uid, price) =>
{
combinedPrice += price;
});
Assert.That(combinedPrice, Is.AtMost(vessel.Price),
$"Found arbitrage on {vessel.ID} shuttle! Cost is {vessel.Price} but sell is {combinedPrice}!");
Assert.That(vessel.Price - combinedPrice, Is.GreaterThan(vessel.Price * 0.05),
$"Arbitrage possible on {vessel.ID}. {vessel.Price} - {combinedPrice} = {vessel.Price - combinedPrice} > 5% of the buy price!");
mapManager.DeleteMap(mapId);
}
});
});

await pair.CleanReturnAsync();
}
}
7 changes: 7 additions & 0 deletions Content.Shared/Shipyard/Prototypes/VesselPrototype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ public sealed class VesselPrototype : IPrototype
[DataField("group")]
public string Group = string.Empty;

/// Frontier - Add this field for the MapChecker script.
/// <summary>
/// The MapChecker override group for this vessel.
/// </summary>
[DataField("mapchecker_group_override")]
public string MapcheckerGroup = string.Empty;

/// <summary>
/// Relative directory path to the given shuttle, i.e. `/Maps/Shuttles/yourshittle.yml`
/// </summary>
Expand Down
20 changes: 20 additions & 0 deletions Resources/Changelog/Changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2723,3 +2723,23 @@ Entries:
message: Praeda was reworked.
id: 4733
time: '2024-01-07T19:48:50.0000000+00:00'
- author: TsjipTsjip
changes:
- type: Tweak
message: Sprinter was reworked.
id: 4734
time: '2024-01-07T20:45:57.0000000+00:00'
- author: ghostprince
changes:
- type: Add
message: NT Has added more ingredients to the ChefVend to allow ease of cooking.
id: 4735
time: '2024-01-08T23:57:21.0000000+00:00'
- author: SungYandy
changes:
- type: Add
message: >-
NT Provided the janitors with fancy new lockers, coming to your ships
soon.
id: 4736
time: '2024-01-09T03:52:40.0000000+00:00'
Loading

0 comments on commit 8521272

Please sign in to comment.