Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Factorio 2.0 / Space Age #320

Merged
merged 31 commits into from
Oct 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
ebd2661
feat: use new Defines.lua
SWeini Oct 9, 2024
e2d8c8f
feat: add Quality to the AllowedEffect enum
SWeini Oct 10, 2024
526609d
feat: add new multipliers for Energy
SWeini Oct 10, 2024
650b16c
fix: prevent the crash on missing tech unit when there is a research …
SWeini Oct 10, 2024
9256d69
feat: tiles can now define the fluid that is pumped
SWeini Oct 10, 2024
0a71ce8
feat: triggered techs will be "crafted" by characters for now
SWeini Oct 10, 2024
dca64d4
feat: use space age by default, set Factorio version to 2.0
SWeini Oct 10, 2024
dac00bc
feat: don't create a 0°C fluid variant
SWeini Oct 10, 2024
9715025
feat: rename the catalyst to its new Factorio name
SWeini Oct 10, 2024
704657f
feat: correct the default for AllowedEffects
SWeini Oct 10, 2024
e6337b1
feat: restore some module functionality
SWeini Oct 10, 2024
5b4705b
feat: adjust rocket inventory size for the base game
SWeini Oct 10, 2024
02c2af9
feat: implement a new system for module limitations
SWeini Oct 10, 2024
ee2cdee
feat: remove the tick limit for recipes
SWeini Oct 10, 2024
2620681
feat: add new boiler logic. No support for input temperatures yet
SWeini Oct 12, 2024
cb4ae31
feat: stack inserter is now bulk inserter
SWeini Oct 12, 2024
2fd7129
feat: rocket launch can go to platform or to cargo-landing pad
SWeini Oct 13, 2024
681a336
feat: remove ItemProrotype::rocket_launch_product
SWeini Oct 13, 2024
d23ea4f
feat: remove BurnerEnergySource::fuel_category
SWeini Oct 13, 2024
e5c7762
feat: remove expensive mode
SWeini Oct 13, 2024
9878a27
feat: remove RecipePrototype::result/result_count
SWeini Oct 13, 2024
6ff9bf7
feat: add format requirements to Ingredient- and ProductPrototype
SWeini Oct 13, 2024
ca2ec72
feat: properly launch fish - also in space age
SWeini Oct 13, 2024
2d5bbc7
feat: update the logic of 'require'
SWeini Oct 16, 2024
39a4845
feat: allowed_effects only restrict positive effects
SWeini Oct 16, 2024
6204cf0
feat: use BeaconPrototype::profile
SWeini Oct 16, 2024
302719e
feat: rudimentary support for gleba - spoilage & agricultural tower
SWeini Oct 20, 2024
5998132
feat: Yafc can now read type-6 and type-7
SWeini Oct 20, 2024
d6c75cf
feat: use separate config/autosave files
SWeini Oct 20, 2024
b5e9e07
fix: update tests to pass and fix some edge cases
SWeini Oct 20, 2024
4369537
feat: set invariant culture before executing any test
SWeini Oct 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CommandLineToolExample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static void Main(string[] args) {
// Empty project path loads default project (with one empty page).
// Project is irrelevant if you just need data, but you need it to perform sheet calculations
// Set to not render any icons
project = FactorioDataSource.Parse(factorioPath, "", "", false, false, new ConsoleProgressReport(), errorCollector, "en", false);
project = FactorioDataSource.Parse(factorioPath, "", "", false, new ConsoleProgressReport(), errorCollector, "en", false);
}
catch (Exception ex) {
// Critical errors that make project un-loadable will be thrown as exceptions
Expand Down
3 changes: 0 additions & 3 deletions Yafc.Model.Tests/Data/DataUtils.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
using System;
using System.Globalization;
using System.Threading;
using Xunit;

namespace Yafc.Model.Data.Tests;

public class DataUtilsTests {
public DataUtilsTests() {
Project.current = new();
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
}

[Fact]
Expand Down
2 changes: 1 addition & 1 deletion Yafc.Model.Tests/LuaDependentTestHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ Could not find an embedded resource named "{targetStreamName}" or "{alternate}".
}
context.Exec(bytes, "*", "");

project = new FactorioDataDeserializer(false, new(1, 1)).LoadData(null, context.data, (LuaTable)context.defines["prototypes"]!, false, helper, new(), false);
project = new FactorioDataDeserializer(new(1, 1)).LoadData(null, context.data, (LuaTable)context.defines["prototypes"]!, false, helper, new(), false);
}

DataUtils.SetupForProject(project);
Expand Down
14 changes: 7 additions & 7 deletions Yafc.Model.Tests/Model/ProductionTableContentTests.lua
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ data = {
crafting_speed = 0.5,
energy_source = {
type = "burner",
fuel_category = "chemical",
fuel_categories = { "chemical" },
},
energy_usage = "75kW",
crafting_categories = { "crafting" },
Expand All @@ -62,7 +62,7 @@ data = {
crafting_speed = 0.75,
energy_source = {
type = "burner",
fuel_category = "chemical",
fuel_categories = { "chemical" },
},
energy_usage = "150kW",
module_specification = {
Expand All @@ -82,7 +82,7 @@ data = {
crafting_speed = 1.25,
energy_source = {
type = "burner",
fuel_category = "chemical",
fuel_categories = { "chemical" },
},
energy_usage = "250kW",
module_specification = {
Expand Down Expand Up @@ -294,13 +294,13 @@ data = {
type = "recipe",
name = "recipe",
ingredients = {
{ "dummy_1", 5 },
{ "dummy_2", 10 },
{ type = "item", name = "dummy_1", amount = 5 },
{ type = "item", name = "dummy_2", amount = 10 },
},
energy_required = 5,
results = {
{ "dummy_3", 5 },
{ "ash", 3 },
{ type = "item", name = "dummy_3", amount = 5 },
{ type = "item", name = "ash", amount = 3 },
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ data = {
name = "water",
default_temperature = 15,
max_temperature = 1000,
heat_capacity = "0.2KJ",
heat_capacity = "0.2kJ",
icon = "",
},
steam = {
type = "fluid",
name = "steam",
default_temperature = 15,
max_temperature = 1000,
heat_capacity = "0.2KJ",
heat_capacity = "0.2kJ",
gas_temperature = 15,
auto_barrel = False,
icon = "",
Expand All @@ -88,7 +88,7 @@ data = {
energy_consumption = "1.8MW",
energy_source = {
type = "burner",
fuel_category = "chemical",
fuel_categories = { "chemical" },
},
},
["heat-exchanger"] = {
Expand Down
4 changes: 4 additions & 0 deletions Yafc.Model.Tests/Model/RecipeParametersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ public void FluidBoilingRecipes_HaveCorrectConsumption() {
table.Solve((ProjectPage)table.owner).Wait(); // Initial Solve to set RecipeRow.Ingredients

for (int i = 0; i < 3; i++) {
if (i != 0) {
// boiler has changed in 2.0 and doesn't work yet
continue;
}
boiler.ChangeVariant(boiler.Ingredients.Single().Goods, water[i]);
heatExchanger.ChangeVariant(boiler.Ingredients.Single().Goods, water[i]);

Expand Down
4 changes: 2 additions & 2 deletions Yafc.Model.Tests/Model/SelectableVariantsTests.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ data = {
name = "steam",
default_temperature = 15,
max_temperature = 1000,
heat_capacity = "0.2KJ",
heat_capacity = "0.2kJ",
gas_temperature = 15,
auto_barrel = False,
icon = "",
Expand All @@ -39,7 +39,7 @@ data = {
energy_consumption = "1.8MW",
energy_source = {
type = "burner",
fuel_category = "chemical",
fuel_categories = { "chemical" },
},
},
["heat-exchanger"] = {
Expand Down
16 changes: 16 additions & 0 deletions Yafc.Model.Tests/PrepareForTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Globalization;
using System.Threading;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
using Yafc.Model.Tests;

[assembly: TestFramework("Yafc.Model.Tests." + nameof(PrepareForTests), "Yafc.Model.Tests")]

namespace Yafc.Model.Tests;
public class PrepareForTests : XunitTestFramework {
public PrepareForTests(IMessageSink messageSink)
: base(messageSink) {
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
}
}
89 changes: 56 additions & 33 deletions Yafc.Model/Data/DataClasses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ internal enum FactorioObjectSortOrder {
Recipes,
Mechanics,
Technologies,
Entities
Entities,
Tiles
}

public enum FactorioId { }
Expand Down Expand Up @@ -82,14 +83,12 @@ public enum RecipeFlags {
UsesMiningProductivity = 1 << 0,
UsesFluidTemperature = 1 << 2,
ScaleProductionWithPower = 1 << 3,
LimitedByTickRate = 1 << 4,
}

public abstract class RecipeOrTechnology : FactorioObject {
public EntityCrafter[] crafters { get; internal set; } = null!; // null-forgiving: Initialized by CalculateMaps
public Ingredient[] ingredients { get; internal set; } = null!; // null-forgiving: Initialized by LoadRecipeData, LoadTechnologyData, and after all calls to CreateSpecialRecipe
public Product[] products { get; internal set; } = null!; // null-forgiving: Initialized by LoadRecipeData, LoadTechnologyData, and after all calls to CreateSpecialRecipe
public Module[] modules { get; internal set; } = [];
public Entity? sourceEntity { get; internal set; }
public Goods? mainProduct { get; internal set; }
public float time { get; internal set; }
Expand Down Expand Up @@ -151,6 +150,8 @@ public enum FactorioObjectSpecialType {
}

public class Recipe : RecipeOrTechnology {
public AllowedEffects allowedEffects { get; internal set; }
public string[]? allowedModuleCategories { get; internal set; }
public Technology[] technologyUnlock { get; internal set; } = [];
public bool HasIngredientVariants() {
foreach (var ingredient in ingredients) {
Expand All @@ -170,17 +171,7 @@ public override void GetDependencies(IDependencyCollector collector, List<Factor
}
}

public bool IsProductivityAllowed() {
foreach (var module in modules) {
if (module.moduleSpecification.productivity != 0f) {
return true;
}
}

return false;
}

public override bool CanAcceptModule(Item module) => modules.Contains(module);
public override bool CanAcceptModule(Item module) => EntityWithModules.CanAcceptModule(((Module)module).moduleSpecification, allowedEffects, allowedModuleCategories);
}

public class Mechanics : Recipe {
Expand Down Expand Up @@ -323,6 +314,7 @@ public class Item : Goods {
public Item? fuelResult { get; internal set; }
public int stackSize { get; internal set; }
public Entity? placeResult { get; internal set; }
public Entity? plantResult { get; internal set; }
public override bool isPower => false;
public override string type => "Item";
internal override FactorioObjectSortOrder sortingOrder => FactorioObjectSortOrder.Items;
Expand Down Expand Up @@ -383,11 +375,22 @@ public enum AllowedEffects {
Productivity = 1 << 1,
Consumption = 1 << 2,
Pollution = 1 << 3,
Quality = 1 << 4,

All = Speed | Productivity | Consumption | Pollution,
All = Speed | Productivity | Consumption | Pollution | Quality,
None = 0
}

public class Tile : FactorioObject {
public Fluid? Fluid { get; internal set; }

internal override FactorioObjectSortOrder sortingOrder => FactorioObjectSortOrder.Tiles;
public override string type => "Tile";

public override void GetDependencies(IDependencyCollector collector, List<FactorioObject> temp) {
}
}

public class Entity : FactorioObject {
public Product[] loot { get; internal set; } = [];
public bool mapGenerated { get; internal set; }
Expand All @@ -414,42 +417,38 @@ public override void GetDependencies(IDependencyCollector collector, List<Factor

public abstract class EntityWithModules : Entity {
public AllowedEffects allowedEffects { get; internal set; } = AllowedEffects.None;
public string[]? allowedModuleCategories { get; internal set; }
public int moduleSlots { get; internal set; }

public static bool CanAcceptModule(ModuleSpecification module, AllowedEffects effects) {
// Check most common cases first
if (effects == AllowedEffects.All) {
return true;
}

if (effects == (AllowedEffects.Consumption | AllowedEffects.Pollution | AllowedEffects.Speed)) {
return module.productivity == 0f;
public static bool CanAcceptModule(ModuleSpecification module, AllowedEffects effects, string[]? allowedModuleCategories) {
if (module.productivity > 0f && (effects & AllowedEffects.Productivity) == 0) {
return false;
}

if (effects == AllowedEffects.None) {
if (module.consumption < 0f && (effects & AllowedEffects.Consumption) == 0) {
return false;
}
// Check the rest
if (module.productivity != 0f && (effects & AllowedEffects.Productivity) == 0) {

if (module.pollution < 0f && (effects & AllowedEffects.Pollution) == 0) {
return false;
}

if (module.consumption != 0f && (effects & AllowedEffects.Consumption) == 0) {
if (module.speed > 0f && (effects & AllowedEffects.Speed) == 0) {
return false;
}

if (module.pollution != 0f && (effects & AllowedEffects.Pollution) == 0) {
if (module.quality > 0f && (effects & AllowedEffects.Quality) == 0) {
return false;
}

if (module.speed != 0f && (effects & AllowedEffects.Speed) == 0) {
if (allowedModuleCategories?.Contains(module.category) == false) {
return false;
}

return true;
}

public bool CanAcceptModule(ModuleSpecification module) => CanAcceptModule(module, allowedEffects);
public bool CanAcceptModule(ModuleSpecification module) => CanAcceptModule(module, allowedEffects, allowedModuleCategories);
}

public class EntityCrafter : EntityWithModules {
Expand All @@ -463,11 +462,26 @@ public float craftingSpeed {
get => _craftingSpeed * (1 + (factorioType == "lab" ? Project.current.settings.researchSpeedBonus : 0));
internal set => _craftingSpeed = value;
}
public EffectReceiver? effectReceiver { get; internal set; } = null!;
}

public class Effect {
public float consumption { get; internal set; }
public float speed { get; internal set; }
public float productivity { get; internal set; }
public float pollution { get; internal set; }
public float quality { get; internal set; }
}

public class EffectReceiver {
public Effect baseEffect { get; internal set; } = null!;
public bool usesModuleEffects { get; internal set; }
public bool usesBeaconEffects { get; internal set; }
public bool usesSurfaceEffects { get; internal set; }
}

public class EntityInserter : Entity {
public bool isStackInserter { get; internal set; }
public bool isBulkInserter { get; internal set; }
public float inserterSwingTime { get; internal set; }
}

Expand All @@ -485,6 +499,15 @@ public class EntityReactor : EntityCrafter {

public class EntityBeacon : EntityWithModules {
public float beaconEfficiency { get; internal set; }
public float[] profile { get; internal set; } = null!;

public float GetProfile(int numberOfBeacons) {
if (numberOfBeacons == 0) {
return 1f;
}

return profile[Math.Min(numberOfBeacons, profile.Length) - 1];
}
}

public class EntityContainer : Entity {
Expand Down Expand Up @@ -534,12 +557,12 @@ public class EntityEnergy {
}

public class ModuleSpecification {
public string category { get; internal set; } = null!;
public float consumption { get; internal set; }
public float speed { get; internal set; }
public float productivity { get; internal set; }
public float pollution { get; internal set; }
public Recipe[]? limitation { get; internal set; }
public Recipe[]? limitation_blacklist { get; internal set; }
public float quality { get; internal set; }
}

public struct TemperatureRange(int min, int max) {
Expand Down
1 change: 0 additions & 1 deletion Yafc.Model/Data/DataUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ public static Bits GetMilestoneOrder(FactorioId id) {

public static string dataPath { get; internal set; } = "";
public static string modsPath { get; internal set; } = "";
public static bool expensiveRecipes { get; internal set; }

/// <summary>
/// If <see langword="true"/>, recipe selection windows will only display recipes that provide net production or consumption of the <see cref="Goods"/> in question.
Expand Down
2 changes: 1 addition & 1 deletion Yafc.Model/Data/Database.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public static class Database {
/// <param name="module">A module that can be placed in that beacon, if such a module exists.</param>
/// <returns><see langword="true"/> if a module could be found, or <see langword="false"/> if the supplied beacon does not accept any modules or was <see langword="null"/>.</returns>
public static bool GetDefaultModuleFor(EntityBeacon? beacon, [NotNullWhen(true)] out Module? module) {
module = allModules.FirstOrDefault(m => EntityWithModules.CanAcceptModule(m.moduleSpecification, beacon?.allowedEffects ?? AllowedEffects.None));
module = allModules.FirstOrDefault(m => EntityWithModules.CanAcceptModule(m.moduleSpecification, beacon?.allowedEffects ?? AllowedEffects.None, null));
return module != null;
}

Expand Down
6 changes: 3 additions & 3 deletions Yafc.Model/Model/ModuleFillerParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public BeaconConfiguration GetBeaconsForCrafter(EntityCrafter? crafter) {
internal void AutoFillBeacons(RecipeOrTechnology recipe, EntityCrafter entity, ref ModuleEffects effects, ref UsedModule used) {
BeaconConfiguration beaconsToUse = GetBeaconsForCrafter(entity);
if (!recipe.flags.HasFlags(RecipeFlags.UsesMiningProductivity) && beaconsToUse.beacon is EntityBeacon beacon && beaconsToUse.beaconModule != null) {
effects.AddModules(beaconsToUse.beaconModule.moduleSpecification, beaconsToUse.beaconCount * beacon.beaconEfficiency * beacon.moduleSlots, entity.allowedEffects);
effects.AddModules(beaconsToUse.beaconModule.moduleSpecification, beaconsToUse.beaconCount * beacon.beaconEfficiency * beacon.GetProfile(beaconsToUse.beaconCount) * beacon.moduleSlots, entity.allowedEffects);
used.beacon = beacon;
used.beaconCount = beaconsToUse.beaconCount;
}
Expand Down Expand Up @@ -161,8 +161,8 @@ The payback time is calculated as the module cost divided by the economy gain pe
float bestEconomy = 0f;
Module? usedModule = null;

foreach (var module in recipe.modules) {
if (module.IsAccessibleWithCurrentMilestones() && entity.CanAcceptModule(module.moduleSpecification)) {
foreach (var module in Database.allModules) {
if (module.IsAccessibleWithCurrentMilestones() && entity.CanAcceptModule(module.moduleSpecification) && recipe.CanAcceptModule(module)) {
float economy = module.moduleSpecification.productivity * productivityEconomy
+ module.moduleSpecification.speed * speedEconomy
- module.moduleSpecification.consumption * effectivityEconomy;
Expand Down
Loading