Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into Species-Custom-Sp…
Browse files Browse the repository at this point in the history
…rites
  • Loading branch information
FoxxoTrystan committed Jan 19, 2024
2 parents 9b9d7a6 + f1d3e1b commit 0f315e1
Show file tree
Hide file tree
Showing 301 changed files with 22,142 additions and 7,590 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
4 changes: 0 additions & 4 deletions .github/mapchecker/whitelist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ Metastable:
- SignSec
DartX:
- HighSecDoor
gourd:
- HoloprojectorSecurity
Praeda:
- ClothingEyesGlassesSecurity
- EncryptionKeyCommand
Expand All @@ -44,8 +42,6 @@ Pheonix:
Spectre:
- AirlockSecurity
- EncryptionKeyMedicalScience
Bazaar:
- AirlockSecurity
Anchor:
- AirlockSecurity
- IntercomCommand
Expand Down
2 changes: 1 addition & 1 deletion Content.Client/Lobby/LobbyState.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Content.Client.NewFrontier.Latejoin;
using Content.Client._NF.Latejoin;
using Content.Client.Chat.Managers;
using Content.Client.GameTicking.Managers;
using Content.Client.LateJoin;
Expand Down
2 changes: 1 addition & 1 deletion Content.Client/Shuttles/UI/RadarConsoleWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:ui="clr-namespace:Content.Client.Shuttles.UI"
Title="{Loc 'radar-console-window-title'}"
SetSize="648 648"
SetSize="648 672"
MinSize="256 256">
<ui:RadarControl Name="RadarScreen"
Margin="4"
Expand Down
2 changes: 1 addition & 1 deletion Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:ui="clr-namespace:Content.Client.Shuttles.UI"
Title="{Loc 'shuttle-console-window-title'}"
SetSize="1180 648"
SetSize="1180 672"
MinSize="788 320">
<GridContainer Columns="3"
HorizontalAlignment="Stretch"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<controls:FancyWindow
xmlns="https://spacestation14.io"
xmlns:lateJoin="clr-namespace:Content.Client.NewFrontier.Latejoin"
xmlns:lateJoin="clr-namespace:Content.Client._NF.Latejoin"
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
Title="Join Game"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;

namespace Content.Client.NewFrontier.Latejoin;
namespace Content.Client._NF.Latejoin;

[GenerateTypedNameReferences]
public sealed partial class NFLateJoinGui : FancyWindow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using Robust.Client.Utility;
using Robust.Shared.Prototypes;

namespace Content.Client.NewFrontier.Latejoin;
namespace Content.Client._NF.Latejoin;

[GenerateTypedNameReferences]
public sealed partial class NewFrontierLateJoinJobButton : Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Player;

namespace Content.Client.NewFrontier.Latejoin;
namespace Content.Client._NF.Latejoin;

[GenerateTypedNameReferences]
public sealed partial class VesselListControl : BoxContainer
Expand All @@ -24,6 +25,7 @@ public NetEntity? Selected
return (NetEntity) i.Metadata!;
}
}
private IReadOnlyDictionary<NetEntity, Dictionary<string, uint?>>? _lastJobState;

public VesselListControl()
{
Expand All @@ -34,6 +36,12 @@ public VesselListControl()
UpdateUi(_gameTicker.JobsAvailable);

Comparison = DefaultComparison;

FilterLineEdit.OnTextChanged += _ =>
{
if (_lastJobState != null)
UpdateUi(_lastJobState);
};
}

protected override void Dispose(bool disposing)
Expand All @@ -44,7 +52,8 @@ protected override void Dispose(bool disposing)

private int DefaultComparison(NetEntity x, NetEntity y)
{
return (int)(_gameTicker.JobsAvailable[x].Values.Sum(a => a ?? 0) - _gameTicker.JobsAvailable[y].Values.Sum(b => b ?? 0));
// Negated to enforce descending order
return -(int)(_gameTicker.JobsAvailable[x].Values.Sum(a => a ?? 0) - _gameTicker.JobsAvailable[y].Values.Sum(b => b ?? 0));
}

public void Sort()
Expand All @@ -55,27 +64,18 @@ public void Sort()

private void UpdateUi(IReadOnlyDictionary<NetEntity, Dictionary<string, uint?>> obj)
{
var itemsToRemove = new List<ItemList.Item>();
foreach (var (key, item) in VesselItemList.Select(x => ((NetEntity)x.Metadata!, x)))
{
if (!_gameTicker.StationNames.ContainsKey(key))
itemsToRemove.Add(item);
}

foreach (var item in itemsToRemove)
{
VesselItemList.Remove(item);
}
VesselItemList.Clear();

foreach (var (key, name) in _gameTicker.StationNames)
{
if (VesselItemList.Any(x => ((NetEntity)x.Metadata!) == key))
continue;

var jobsAvailable = _gameTicker.JobsAvailable[key].Values.Sum(a => a ?? 0).ToString();
var item = new ItemList.Item(VesselItemList)
{
Metadata = key,
Text = name
Text = name + $" ({jobsAvailable})"
};

if (!string.IsNullOrEmpty(FilterLineEdit.Text) &&
Expand All @@ -88,5 +88,7 @@ private void UpdateUi(IReadOnlyDictionary<NetEntity, Dictionary<string, uint?>>
}

Sort();

_lastJobState = obj;
}
}
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();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Content.Shared.Anomaly;
using Content.Shared.Anomaly;
using Content.Shared.Materials;
using Content.Shared.Radio;
using Robust.Shared.Audio;
Expand Down Expand Up @@ -37,13 +37,13 @@ public sealed partial class AnomalyGeneratorComponent : Component
/// The material needed to generate an anomaly
/// </summary>
[DataField("requiredMaterial", customTypeSerializer: typeof(PrototypeIdSerializer<MaterialPrototype>)), ViewVariables(VVAccess.ReadWrite)]
public string RequiredMaterial = "Plasma";
public string RequiredMaterial = "Bananium"; // Frontier - Plasma to Bananium

/// <summary>
/// The amount of material needed to generate a single anomaly
/// </summary>
[DataField("materialPerAnomaly"), ViewVariables(VVAccess.ReadWrite)]
public int MaterialPerAnomaly = 1500; // a bit less than a stack of plasma
public int MaterialPerAnomaly = 1000; // Frontier - Plasma to Bananium, 1500 to 1000

/// <summary>
/// The random anomaly spawner entity
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Content.Server.Item.PseudoItem;

/// <summary>
/// Signifies that pseudo-item creatures can sleep inside the container to which this component was added.
/// </summary>
[RegisterComponent]
public sealed partial class AllowsSleepInsideComponent : Component
{
}
Loading

0 comments on commit 0f315e1

Please sign in to comment.