Skip to content

Commit

Permalink
Selection window cleanup (#358)
Browse files Browse the repository at this point in the history
The object selection windows have some things in them that I think are
noise and should be removed. Specifically, blueprint parameters and,
occasionally, the I and O objects. This hides those objects more often,
though I would understand an argument for not hiding them, if someone
wants to make that. The recycling recipes for Item.parameter-# are still
present, unfortunately, but I think that's a Factorio bug, not a Yafc
bug.


![image](https://github.com/user-attachments/assets/a1b15e62-ea07-4c0c-8968-c1a28b0607a6)
![image](https://github.com/user-attachments/assets/a49489a2-5048-4cda-a3b2-c53770a56f5a)
  • Loading branch information
shpaass authored Nov 21, 2024
2 parents d75ff3d + 3528fad commit b107caa
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 35 deletions.
3 changes: 3 additions & 0 deletions Yafc.Model/Data/DataClasses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,9 @@ public enum AllowedEffects {
}

public class Tile : FactorioObject {
// Tiles participate in accessibility analysis, but only until the pumping recipes get around to reading the locations where their tiles
// appear. They often don't have an icon, and don't participate in anything else Yafc cares about, so hide them.
public Tile() => showInExplorers = false;
public Fluid? Fluid { get; internal set; }

internal override FactorioObjectSortOrder sortingOrder => FactorioObjectSortOrder.Tiles;
Expand Down
11 changes: 5 additions & 6 deletions Yafc.Parser/Data/FactorioDataDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,8 @@ private static EffectReceiver ParseEffectReceiver(LuaTable? table) {
}

private void DeserializeItem(LuaTable table, ErrorCollector _1) {
string name = table.Get("name", "");
if (table.Get("type", "") == "module" && table.Get("effect", out LuaTable? moduleEffect)) {
Module module = GetObject<Item, Module>(name);
Module module = GetObject<Item, Module>(table);
var effect = ParseEffect(moduleEffect);
module.moduleSpecification = new ModuleSpecification {
category = table.Get("category", ""),
Expand All @@ -394,7 +393,7 @@ private void DeserializeItem(LuaTable table, ErrorCollector _1) {
};
}
else if (table.Get("type", "") == "ammo" && table["ammo_type"] is LuaTable ammo_type) {
Ammo ammo = GetObject<Item, Ammo>(name);
Ammo ammo = GetObject<Item, Ammo>(table);
ammo_type.ReadObjectOrArray(readAmmoType);

if (ammo_type["target_filter"] is LuaTable targets) {
Expand Down Expand Up @@ -556,13 +555,13 @@ private void DeserializeFluid(LuaTable table, ErrorCollector _) {
private Goods? LoadItemOrFluid(LuaTable table, bool useTemperature) {
if (table.Get("type", out string? type) && table.Get("name", out string? name)) {
if (type == "item") {
return GetObject<Item>(name);
return GetObject<Item>(table);
}
else if (type == "fluid") {
if (useTemperature && table.Get("temperature", out int temperature)) {
return GetFluidFixedTemp(name, temperature);
}
return GetObject<Fluid>(name);
return GetObject<Fluid>(table);
}
}

Expand Down Expand Up @@ -599,7 +598,7 @@ private void DeserializeLocation(LuaTable table, ErrorCollector collector) {
throw new NotSupportedException($"Read a definition of a {prototypeType} that does not have a name.");
}

var target = GetObject<T>(name);
var target = GetObject<T>(table);
target.factorioType = table.Get("type", "");

if (table.Get("localised_name", out object? loc)) { // Keep UK spelling for Factorio/LUA data objects
Expand Down
46 changes: 46 additions & 0 deletions Yafc.Parser/Data/FactorioDataDeserializer_Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,54 @@ Item createSpecialItem(string name, string locName, string locDescr, string icon
totalItemOutput = createSpecialItem("item-total-output", "Total item production", "This item represents the combined total item output of a multi-product recipe. It can be used to set or measure the number of sushi belts required to handle the products of this recipe row.", "__base__/graphics/icons/signal/signal_O.png");
}

/// <summary>
/// Calls <see cref="GetObject{TNominal, TActual}(LuaTable)"/>, with both type parameters set to <typeparamref name="T"/>.
/// </summary>
private T GetObject<T>(LuaTable table) where T : FactorioObject, new() => GetObject<T, T>(table);

/// <summary>
/// Gets or creates an object with the specified nominal and actual types, based on the supplied <see cref="LuaTable"/>. If
/// <paramref name="table"/> describes a blueprint parameter, the returned object will not be shown in NEIE, Dependency Explorer, or
/// Desired Product windows.
/// </summary>
/// <typeparam name="TNominal">The nominal type. In general, this is the most-derived type such that all possible callers will know the
/// object is of this type, and the least-derived type such that <c>(typeof(<typeparamref name="TNominal"/>),
/// <paramref name="table"/>["name"])</c> is unique across all objects.</typeparam>
/// <typeparam name="TActual">The concrete type of the object. This can be either same as <typeparamref name="TNominal"/>, or a type derived
/// from it. If the object already exists, it must have been created as an object of this type (or a derived type).</typeparam>
/// <param name="table">The <see cref="LuaTable"/> to read when to get the object's name. This table must have a <c>name</c> key. If the
/// value of its <c>parameter</c> key is <see langword="true"/>, <see cref="FactorioObject.showInExplorers"/> and
/// <see cref="Goods.isLinkable"/>, if applicable, will be set to <see langword="false"/>.</param>
/// <returns>The new or pre-existing object described by <typeparamref name="TNominal"/> and <c><paramref name="table"/>["name"]</c>.</returns>
private TActual GetObject<TNominal, TActual>(LuaTable table) where TNominal : FactorioObject where TActual : TNominal, new() {
if (!table.Get("name", out string? name)) {
throw new ArgumentException($"{nameof(table)} must contain a 'name' key. Call GetObject(string) instead.", nameof(table));
}
TActual result = GetObject<TNominal, TActual>(name);
if (table.Get("parameter", false)) {
result.showInExplorers = false;
if (result is Goods goods) {
goods.isLinkable = false;
}
}
return result;
}

/// <summary>
/// Calls <see cref="GetObject{TNominal, TActual}(string)"/>, with both type parameters set to <typeparamref name="T"/>.
/// </summary>
private T GetObject<T>(string name) where T : FactorioObject, new() => GetObject<T, T>(name);

/// <summary>
/// Gets or creates an object with the specified nominal and actual types, with the supplied name.
/// </summary>
/// <typeparam name="TNominal">The nominal type. In general, this is the most-derived type such that all possible callers will know the
/// object is of this type, and the least-derived type such that <c>(typeof(<typeparamref name="TNominal"/>),
/// <paramref name="name"/>)</c> is unique across all objects.</typeparam>
/// <typeparam name="TActual">The concrete type of the object. This can be either same as <typeparamref name="TNominal"/>, or a type derived
/// from it. If the object already exists, it must have been created as an object of this type (or a derived type).</typeparam>
/// <param name="table">The name of the object to get or create.</param>
/// <returns>The new or pre-existing object described by <typeparamref name="TNominal"/> and <paramref name="name"/>.</returns>
private TActual GetObject<TNominal, TActual>(string name) where TNominal : FactorioObject where TActual : TNominal, new() {
var key = (typeof(TNominal), name);
if (registeredObjects.TryGetValue(key, out FactorioObject? existing)) {
Expand Down
52 changes: 27 additions & 25 deletions Yafc.Parser/Data/FactorioDataDeserializer_Entity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,14 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) {
// case "furnace":
// case "rocket-silo": // Out of order
case "accumulator":
var accumulator = GetObject<Entity, EntityAccumulator>(name);
var accumulator = GetObject<Entity, EntityAccumulator>(table);

if (table.Get("energy_source", out LuaTable? accumulatorEnergy) && accumulatorEnergy.Get("buffer_capacity", out string? capacity)) {
accumulator.baseAccumulatorCapacity = ParseEnergy(capacity);
}
break;
case "agricultural-tower":
var agriculturalTower = GetObject<Entity, EntityCrafter>(name);
var agriculturalTower = GetObject<Entity, EntityCrafter>(table);
_ = table.Get("energy_usage", out usesPower);
agriculturalTower.basePower = ParseEnergy(usesPower);
float radius = table.Get("radius", 1f);
Expand All @@ -194,7 +194,7 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) {
case "assembling-machine":
goto case "furnace";
case "asteroid":
Entity asteroid = GetObject<Entity>(name);
Entity asteroid = GetObject<Entity>(table);
if (table.Get("dying_trigger_effect", out LuaTable? death)) {
death.ReadObjectOrArray(trigger => {
switch (trigger.Get<string>("type")) {
Expand All @@ -207,7 +207,7 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) {
}
break;
case "asteroid-collector":
EntityCrafter collector = GetObject<Entity, EntityCrafter>(name);
EntityCrafter collector = GetObject<Entity, EntityCrafter>(table);
_ = table.Get("arm_energy_usage", out usesPower);
collector.basePower = ParseEnergy(usesPower) * 60;
_ = table.Get("passive_energy_usage", out usesPower);
Expand All @@ -216,15 +216,15 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) {
recipeCrafters.Add(collector, SpecialNames.AsteroidCapture);
break;
case "beacon":
var beacon = GetObject<Entity, EntityBeacon>(name);
var beacon = GetObject<Entity, EntityBeacon>(table);
beacon.baseBeaconEfficiency = table.Get("distribution_effectivity", 0f);
beacon.profile = table.Get("profile", out LuaTable? profile) ? profile.ArrayElements<double>().Select(x => (float)x).ToArray() : [1f];
_ = table.Get("energy_usage", out usesPower);
ParseModules(table, beacon, AllowedEffects.None);
beacon.basePower = ParseEnergy(usesPower);
break;
case "boiler":
var boiler = GetObject<Entity, EntityCrafter>(name);
var boiler = GetObject<Entity, EntityCrafter>(table);
_ = table.Get("energy_consumption", out usesPower);
boiler.basePower = ParseEnergy(usesPower);
boiler.fluidInputs = 1;
Expand All @@ -251,7 +251,7 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) {
boiler.baseCraftingSpeed = 1f;
break;
case "burner-generator":
var generator = GetObject<Entity, EntityCrafter>(name);
var generator = GetObject<Entity, EntityCrafter>(table);

// generator energy input config is strange
if (table.Get("max_power_output", out string? maxPowerOutput)) {
Expand All @@ -269,7 +269,7 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) {
recipeCrafters.Add(generator, SpecialNames.GeneratorRecipe);
break;
case "character":
var character = GetObject<Entity, EntityCrafter>(name);
var character = GetObject<Entity, EntityCrafter>(table);
character.itemInputs = 255;

if (table.Get("mining_categories", out LuaTable? resourceCategories)) {
Expand Down Expand Up @@ -300,7 +300,7 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) {
}
break;
case "container":
var container = GetObject<Entity, EntityContainer>(name);
var container = GetObject<Entity, EntityContainer>(table);
container.inventorySize = table.Get("inventory_size", 0);

if (factorioType == "logistic-container") {
Expand All @@ -312,7 +312,7 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) {
}
break;
case "electric-energy-interface":
var eei = GetObject<Entity, EntityCrafter>(name);
var eei = GetObject<Entity, EntityCrafter>(table);
eei.energy = voidEntityEnergy;

if (table.Get("energy_production", out string? interfaceProduction)) {
Expand All @@ -323,7 +323,7 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) {
}
break;
case "furnace":
var crafter = GetObject<Entity, EntityCrafter>(name);
var crafter = GetObject<Entity, EntityCrafter>(table);
_ = table.Get("energy_usage", out usesPower);
ParseModules(table, crafter, AllowedEffects.None);
crafter.basePower = ParseEnergy(usesPower);
Expand Down Expand Up @@ -380,12 +380,12 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) {
case "generator":
goto case "burner-generator";
case "inserter":
var inserter = GetObject<Entity, EntityInserter>(name);
var inserter = GetObject<Entity, EntityInserter>(table);
inserter.inserterSwingTime = 1f / (table.Get("rotation_speed", 1f) * 60);
inserter.isBulkInserter = table.Get("bulk", false);
break;
case "lab":
var lab = GetObject<Entity, EntityCrafter>(name);
var lab = GetObject<Entity, EntityCrafter>(table);
_ = table.Get("energy_usage", out usesPower);
ParseModules(table, lab, AllowedEffects.All ^ AllowedEffects.Quality);
lab.basePower = ParseEnergy(usesPower);
Expand All @@ -399,7 +399,7 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) {
case "logistic-container":
goto case "container";
case "mining-drill":
var drill = GetObject<Entity, EntityCrafter>(name);
var drill = GetObject<Entity, EntityCrafter>(table);
_ = table.Get("energy_usage", out usesPower);
drill.basePower = ParseEnergy(usesPower);
ParseModules(table, drill, AllowedEffects.All);
Expand All @@ -418,7 +418,7 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) {
}
break;
case "offshore-pump":
var pump = GetObject<Entity, EntityCrafter>(name);
var pump = GetObject<Entity, EntityCrafter>(table);
_ = table.Get("energy_usage", out usesPower);
pump.basePower = ParseEnergy(usesPower);
pump.baseCraftingSpeed = table.Get("pumping_speed", 20f) / 20f;
Expand All @@ -443,7 +443,7 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) {
}
break;
case "projectile":
var projectile = GetObject<Entity, EntityProjectile>(name);
var projectile = GetObject<Entity, EntityProjectile>(table);
if (table["action"] is LuaTable actions) {
actions.ReadObjectOrArray(parseAction);
}
Expand All @@ -465,7 +465,7 @@ void parseEffect(LuaTable effect) {
}
break;
case "reactor":
var reactor = GetObject<Entity, EntityReactor>(name);
var reactor = GetObject<Entity, EntityReactor>(table);
reactor.reactorNeighborBonus = table.Get("neighbour_bonus", 1f); // Keep UK spelling for Factorio/LUA data objects
_ = table.Get("consumption", out usesPower);
reactor.basePower = ParseEnergy(usesPower);
Expand All @@ -475,17 +475,17 @@ void parseEffect(LuaTable effect) {
case "rocket-silo":
goto case "furnace";
case "solar-panel":
var solarPanel = GetObject<Entity, EntityCrafter>(name);
var solarPanel = GetObject<Entity, EntityCrafter>(table);
solarPanel.energy = voidEntityEnergy;
_ = table.Get("production", out string? powerProduction);
recipeCrafters.Add(solarPanel, SpecialNames.GeneratorRecipe);
solarPanel.baseCraftingSpeed = ParseEnergy(powerProduction) * 0.7f; // 0.7f is a solar panel ratio on nauvis
break;
case "transport-belt":
GetObject<Entity, EntityBelt>(name).beltItemsPerSecond = table.Get("speed", 0f) * 480f;
GetObject<Entity, EntityBelt>(table).beltItemsPerSecond = table.Get("speed", 0f) * 480f;
break;
case "unit-spawner":
var spawner = GetObject<Entity, EntitySpawner>(name);
var spawner = GetObject<Entity, EntitySpawner>(table);
spawner.capturedEntityName = table.Get<string>("captured_spawner_entity");
break;
}
Expand Down Expand Up @@ -602,11 +602,13 @@ void readDeathEffect(LuaTable effect) {
private void DeserializeAsteroidChunk(LuaTable table, ErrorCollector errorCollector) {
Entity chunk = DeserializeCommon<Entity>(table, "asteroid-chunk");
Item asteroid = GetObject<Item>(chunk.name);
Recipe recipe = CreateSpecialRecipe(asteroid, SpecialNames.AsteroidCapture, "mining");
recipe.time = 1;
recipe.ingredients = [];
recipe.products = [new Product(asteroid, 1)];
recipe.sourceEntity = chunk;
if (asteroid.showInExplorers) { // don't create mining recipes for parameter chunks.
Recipe recipe = CreateSpecialRecipe(asteroid, SpecialNames.AsteroidCapture, "mining");
recipe.time = 1;
recipe.ingredients = [];
recipe.products = [new Product(asteroid, 1)];
recipe.sourceEntity = chunk;
}
}

private float EstimateArgument(LuaTable args, string name, float def = 0) => args.Get(name, out LuaTable? res) ? EstimateNoiseExpression(res) : def;
Expand Down
2 changes: 1 addition & 1 deletion Yafc/Windows/MilestonesEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public override void Build(ImGui gui) {
milestoneList.RebuildContents();
}
if (gui.BuildButton("Add milestone")) {
SelectMultiObjectPanel.Select(Database.objects.all.Except(Project.current.settings.milestones), "Add new milestone", AddMilestone);
SelectMultiObjectPanel.Select(Database.objects.explorable.Except(Project.current.settings.milestones), "Add new milestone", AddMilestone);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Yafc/Windows/NeverEnoughItemsPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ public override void Build(ImGui gui) {
}

if (gui.BuildFactorioObjectButtonBackground(gui.lastRect, current, SchemeColor.Grey) == Click.Left) {
SelectSingleObjectPanel.Select(Database.goods.all, "Select item", SetItem);
SelectSingleObjectPanel.Select(Database.goods.explorable, "Select item", SetItem);
}

using (var split = gui.EnterHorizontalSplit(2)) {
Expand Down
2 changes: 1 addition & 1 deletion Yafc/Workspace/AutoPlannerView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ void page1(ImGui gui, ref bool valid) {
}
grid.Next();
if (gui.BuildButton(Icon.Plus, SchemeColor.Primary, SchemeColor.PrimaryAlt, size: 2.5f)) {
SelectSingleObjectPanel.Select(Database.goods.all, "New production goal", x => {
SelectSingleObjectPanel.Select(Database.goods.explorable, "New production goal", x => {
goal.Add(new AutoPlannerGoal { amount = 1f, item = x });
gui.Rebuild();
});
Expand Down
2 changes: 1 addition & 1 deletion Yafc/Workspace/ProductionTable/ProductionTableView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ private static void BuildRecipeButton(ImGui gui, ProductionTable table) {
r => table.AddRecipe(r, DefaultVariantOrdering), checkMark: r => table.recipes.Any(rr => rr.recipe == r));
}
else {
SelectMultiObjectPanel.Select(Database.recipes.all, "Select raw recipe",
SelectMultiObjectPanel.Select(Database.recipes.explorable, "Select raw recipe",
r => table.AddRecipe(r, DefaultVariantOrdering), checkMark: r => table.recipes.Any(rr => rr.recipe == r));
}
}
Expand Down
Loading

0 comments on commit b107caa

Please sign in to comment.