Make the API less rigid.

Things that we aren't going to implement
ratchetfreak
Filter Inserter
Filter Inserter
Posts: 952
Joined: Sat May 23, 2015 12:10 pm
Contact:

Make the API less rigid.

Post by ratchetfreak »

In the current system the API is extremely rigid in what you are allowed to do.

You can't create a power generator without hacking a hidden boiler to magically get heated water. You can't create a lamp without having to give it power.

You can't read circuit input without a hack to binary search each signal separately. You can't output to a circuit without creating an invisible constant combinator. You can't create a filtered generic inventory.

Give modders enough modules that they can mix and match everything.

As a rule of thumb give modders enough information and utilities to fully emulate existing stuff without copying the built in entities.

Rseding91
Factorio Staff
Factorio Staff
Posts: 14152
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Make the API less rigid.

Post by Rseding91 »

ratchetfreak wrote:You can't create a power generator without hacking a hidden boiler to magically get heated water.
...
You can't create a lamp without having to give it power.
Already planned for 0.13.
ratchetfreak wrote:You can't read circuit input without a hack to binary search each signal separately.
Ready and waiting in 0.12.5.
ratchetfreak wrote:You can't output to a circuit without creating an invisible constant combinator.
This is how the circuit network works - in order to output a signal into a given network you need an entity connected to that network.
ratchetfreak wrote:You can't create a filtered generic inventory.
I'll see what Kovarex has to say about adding support for this.
ratchetfreak wrote:Give modders enough modules that they can mix and match everything.

As a rule of thumb give modders enough information and utilities to fully emulate existing stuff without copying the built in entities.
I don't understand this - you want to be able to emulate existing stuff but without copying existing stuff. The statement contradicts its self O.o

Object oriented C++ doesn't lend its self well to "mix and match any random piece of the code into one entity" - each entity supports the given coded behaviors and properties. Without re-writing the entity you can't just make it do something else.
If you want to get ahold of me I'm almost always on Discord.

ratchetfreak
Filter Inserter
Filter Inserter
Posts: 952
Joined: Sat May 23, 2015 12:10 pm
Contact:

Re: Make the API less rigid.

Post by ratchetfreak »

Rseding91 wrote:
ratchetfreak wrote:You can't create a power generator without hacking a hidden boiler to magically get heated water.
...
You can't create a lamp without having to give it power.
Already planned for 0.13.
ratchetfreak wrote:You can't read circuit input without a hack to binary search each signal separately.
Ready and waiting in 0.12.5.
great :)
Rseding91 wrote:
ratchetfreak wrote:You can't output to a circuit without creating an invisible constant combinator.
This is how the circuit network works - in order to output a signal into a given network you need an entity connected to that network.
but you are limited to 15 signals (last I checked) and you need to power it.
Rseding91 wrote:
ratchetfreak wrote:You can't create a filtered generic inventory.
I'll see what Kovarex has to say about adding support for this.
ratchetfreak wrote:Give modders enough modules that they can mix and match everything.

As a rule of thumb give modders enough information and utilities to fully emulate existing stuff without copying the built in entities.
I don't understand this - you want to be able to emulate existing stuff but without copying existing stuff. The statement contradicts its self O.o

Object oriented C++ doesn't lend its self well to "mix and match any random piece of the code into one entity" - each entity supports the given coded behaviors and properties. Without re-writing the entity you can't just make it do something else.

I meant make it more component based.

Like for an assembler lvl3 you have 3 inventories; a filtered input (based on the recipe), a output and module slots. (Additionally a liquid connection for blue belts and such)

It also has a power consumer with buffer and a gui that shows the state of it all and an animation.

A boiler has a power producer and a liquid connection.

A capacitor has a power consumer and a power producer.

Let modders mix and match those components.

GopherAtl
Fast Inserter
Fast Inserter
Posts: 177
Joined: Sat Jan 31, 2015 7:54 pm
Contact:

Re: Make the API less rigid.

Post by GopherAtl »

Rseding91 wrote:
ratchetfreak wrote: As a rule of thumb give modders enough information and utilities to fully emulate existing stuff without copying the built in entities.
I don't understand this - you want to be able to emulate existing stuff but without copying existing stuff. The statement contradicts its self O.o
Not really a contradiction. He wants the api to have the lower-level interface used to make the vanilla items, instead of a limited ability to tweak the vanilla end products. Hypothetical example, a "crafting-machine" prototype that could be extended by a mod to make any of the vanilla crafting machines - or any number of original machines combining aspects of those with novel functionality.
Rseding91 wrote: Object oriented C++ doesn't lend its self well to "mix and match any random piece of the code into one entity" - each entity supports the given coded behaviors and properties. Without re-writing the entity you can't just make it do something else.
This I grant is an entirely valid response. It's possible to do this sort of thing in c++, but the language wasn't designed for it, and the implementation details of trying to apply a pattern like mixins in c++ can get very nasty very quickly. So, giving any prototypes the potential to become "all the things" is an unrealistic request. That said, generic prototypes for families where underlying abstract base classes exist (probably - I can only guess here), like crafting machines (which share fundamentals like recipes, progress, etc, and so I'm betting derive from a common abstract class) could be extended into prototypeable non-abstract, but by themselves perhaps non-functional, classes that could be fully defined and implemented by mods. They would, obviously, result in machines that were less efficient than those hard-coded in c++, or derived from those by only a few property changes in lua, but they would be correspondingly more flexible and allow things that would be impossible, or unnecessarily convoluted, currently.
My Mods:
Nixie Tubes - numeric displays for your circuit networks!
Logistic Combinators - use logistics values in circuit logic! -
Autowire - automate red/green wire connections

ratchetfreak
Filter Inserter
Filter Inserter
Posts: 952
Joined: Sat May 23, 2015 12:10 pm
Contact:

Re: Make the API less rigid.

Post by ratchetfreak »

GopherAtl wrote:
Rseding91 wrote:
ratchetfreak wrote: As a rule of thumb give modders enough information and utilities to fully emulate existing stuff without copying the built in entities.
I don't understand this - you want to be able to emulate existing stuff but without copying existing stuff. The statement contradicts its self O.o
Not really a contradiction. He wants the api to have the lower-level interface used to make the vanilla items, instead of a limited ability to tweak the vanilla end products. Hypothetical example, a "crafting-machine" prototype that could be extended by a mod to make any of the vanilla crafting machines - or any number of original machines combining aspects of those with novel functionality.
exactly
GopherAtl wrote:
Rseding91 wrote: Object oriented C++ doesn't lend its self well to "mix and match any random piece of the code into one entity" - each entity supports the given coded behaviors and properties. Without re-writing the entity you can't just make it do something else.
This I grant is an entirely valid response. It's possible to do this sort of thing in c++, but the language wasn't designed for it, and the implementation details of trying to apply a pattern like mixins in c++ can get very nasty very quickly. So, giving any prototypes the potential to become "all the things" is an unrealistic request. That said, generic prototypes for families where underlying abstract base classes exist (probably - I can only guess here), like crafting machines (which share fundamentals like recipes, progress, etc, and so I'm betting derive from a common abstract class) could be extended into prototypeable non-abstract, but by themselves perhaps non-functional, classes that could be fully defined and implemented by mods. They would, obviously, result in machines that were less efficient than those hard-coded in c++, or derived from those by only a few property changes in lua, but they would be correspondingly more flexible and allow things that would be impossible, or unnecessarily convoluted, currently.
With Pimpl (Pointer to IMPLementation) it's less of a hassle (and customizable at runtime) though at the cost of a layer of indirection.

So each component has a implementation of the generic base it uses. A electric power module would connect to the nearby networks to fill its internal buffer and as the entity needs power it will pull it from its buffer (or from network directly). A infinite power module would have an infinitely full buffer. A burner power module would consume the fuel in the connected fuel inventory as needed. A solar module would only have power when the sun is out.

GopherAtl
Fast Inserter
Fast Inserter
Posts: 177
Joined: Sat Jan 31, 2015 7:54 pm
Contact:

Re: Make the API less rigid.

Post by GopherAtl »

ratchetfreak wrote: With Pimpl (Pointer to IMPLementation) it's less of a hassle (and customizable at runtime) though at the cost of a layer of indirection.

So each component has a implementation of the generic base it uses. A electric power module would connect to the nearby networks to fill its internal buffer and as the entity needs power it will pull it from its buffer (or from network directly). A infinite power module would have an infinitely full buffer. A burner power module would consume the fuel in the connected fuel inventory as needed. A solar module would only have power when the sun is out.
All of this is assuming a class structure that, from what rseding has said, just doesn't exist in the code base right now, though, and it also supposes a base class common to everything that has at least the rudimentary interface for every possible feature. By the sound of it the actual code is using a more traditional hierarchical inheritance model; changing that at this stage would be pretty major.
My Mods:
Nixie Tubes - numeric displays for your circuit networks!
Logistic Combinators - use logistics values in circuit logic! -
Autowire - automate red/green wire connections

ratchetfreak
Filter Inserter
Filter Inserter
Posts: 952
Joined: Sat May 23, 2015 12:10 pm
Contact:

Re: Make the API less rigid.

Post by ratchetfreak »

Looking at how the API works (and what help() returns) I wouldn't be surprised if there was a abstract Entity class that binds all the entities together.

All that's really needed on the engine side is letting each module act. Each would have a physical representation (bounding box for connecting with the power grid, or letting inserters interact with the inventory, a point where the circuit network will attach to etc.)

And then let the mod interact with the owner entity and query the modules it installed

User avatar
Afforess
Filter Inserter
Filter Inserter
Posts: 422
Joined: Tue May 05, 2015 6:07 pm
Contact:

Re: Make the API less rigid.

Post by Afforess »

I agree with the sort of general plea from the title, if not all the specific examples. I've noticed a lot of the time, the string in the prototype "type" field enables or disables "magic" properties. Turrets have to be of type "ammo turret" or else whatever code the game has for the turret AI does not execute. So there is this whole complex turret aiming / inventory system that is hidden from entities and only turned on if you set the type field to "ammo turret". This is the same sort of problem with logistics containers, you have to set their type to "logistics containers" or else your container is not part of the logistics system. Shouldn't there be a property to set the logistics type? Not a hard-coded type? Hardcoding these types makes it very difficult to mix and match two types together.

Rseding91
Factorio Staff
Factorio Staff
Posts: 14152
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Make the API less rigid.

Post by Rseding91 »

Afforess wrote:I agree with the sort of general plea from the title, if not all the specific examples. I've noticed a lot of the time, the string in the prototype "type" field enables or disables "magic" properties. Turrets have to be of type "ammo turret" or else whatever code the game has for the turret AI does not execute. So there is this whole complex turret aiming / inventory system that is hidden from entities and only turned on if you set the type field to "ammo turret". This is the same sort of problem with logistics containers, you have to set their type to "logistics containers" or else your container is not part of the logistics system. Shouldn't there be a property to set the logistics type? Not a hard-coded type? Hardcoding these types makes it very difficult to mix and match two types together.
When you define the type in the Lua prototype you're telling the game engine which C++ class of the entity to use. Each class has code for that given entity type and it's behaviors.

Nothing is "hidden" from other entity types they simply aren't coded to run with that logic.

A real world example:

"Cars" all do the same basic concept: drive. Most have 4 wheels and an engine. However, a minivan and a pickup truck have completely different internal components and you can't just "switch the engines" on them without massive structural changes to both cars. The same can be said about Factorio entities.

Regarding the "hard coded" comment: the way you set the chest to the logistic type is by defining the /type/ property in the prototype to that of the logistic-container.
If you want to get ahold of me I'm almost always on Discord.

User avatar
Afforess
Filter Inserter
Filter Inserter
Posts: 422
Joined: Tue May 05, 2015 6:07 pm
Contact:

Re: Make the API less rigid.

Post by Afforess »

Rseding91 wrote:
Afforess wrote:I agree with the sort of general plea from the title, if not all the specific examples. I've noticed a lot of the time, the string in the prototype "type" field enables or disables "magic" properties. Turrets have to be of type "ammo turret" or else whatever code the game has for the turret AI does not execute. So there is this whole complex turret aiming / inventory system that is hidden from entities and only turned on if you set the type field to "ammo turret". This is the same sort of problem with logistics containers, you have to set their type to "logistics containers" or else your container is not part of the logistics system. Shouldn't there be a property to set the logistics type? Not a hard-coded type? Hardcoding these types makes it very difficult to mix and match two types together.
When you define the type in the Lua prototype you're telling the game engine which C++ class of the entity to use. Each class has code for that given entity type and it's behaviors.

Nothing is "hidden" from other entity types they simply aren't coded to run with that logic.
Exactly. That is the very definition of hidden behavior.
Rseding91 wrote: Regarding the "hard coded" comment: the way you set the chest to the logistic type is by defining the /type/ property in the prototype to that of the logistic-container.
Er, that is exactly my complaint. Types should be defined by their own set of fields. If I want a car, I should have a prototype for a "car" that defines what a "car" is (has 4 wheels, moves, consumes fuel, can contain 1 passenger, etc). Right now, you specify a magic word (ex: type = "car") and your prototype is a car.

HOWEVER, I realize this is not going to happen. It is a huge change, and at this late stage, not worth it. It would be nice if the predefined magic types were a bit more flexible.

Rseding91
Factorio Staff
Factorio Staff
Posts: 14152
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Make the API less rigid.

Post by Rseding91 »

Afforess wrote:
Rseding91 wrote: Regarding the "hard coded" comment: the way you set the chest to the logistic type is by defining the /type/ property in the prototype to that of the logistic-container.
Er, that is exactly my complaint. Types should be defined by their own set of fields. If I want a car, I should have a prototype for a "car" that defines what a "car" is (has 4 wheels, moves, consumes fuel, can contain 1 passenger, etc). Right now, you specify a magic word (ex: type = "car") and your prototype is a car.

HOWEVER, I realize this is not going to happen. It is a huge change, and at this late stage, not worth it. It would be nice if the predefined magic types were a bit more flexible.
That's just not how any of this works in real-world programming. I don't know of one game or game engine that works the way you're talking about. In fact I'm not even sure a game could be implemented to work that way (since no one has done it on a game that has actually sold).

Even if it was feasible to implement the performance implications of making it work and the resulting code would be un-maintainable :\
If you want to get ahold of me I'm almost always on Discord.

ratchetfreak
Filter Inserter
Filter Inserter
Posts: 952
Joined: Sat May 23, 2015 12:10 pm
Contact:

Re: Make the API less rigid.

Post by ratchetfreak »

Rseding91 wrote: That's just not how any of this works in real-world programming. I don't know of one game or game engine that works the way you're talking about. In fact I'm not even sure a game could be implemented to work that way (since no one has done it on a game that has actually sold).

Even if it was feasible to implement the performance implications of making it work and the resulting code would be un-maintainable :\
ever heard of dependency injection?

There an object has a set of fields and on construction those fields get filled with objects depending on config/"circumstances".

User avatar
Afforess
Filter Inserter
Filter Inserter
Posts: 422
Joined: Tue May 05, 2015 6:07 pm
Contact:

Re: Make the API less rigid.

Post by Afforess »

ratchetfreak wrote:
Rseding91 wrote: That's just not how any of this works in real-world programming. I don't know of one game or game engine that works the way you're talking about. In fact I'm not even sure a game could be implemented to work that way (since no one has done it on a game that has actually sold).

Even if it was feasible to implement the performance implications of making it work and the resulting code would be un-maintainable :\
ever heard of dependency injection?

There an object has a set of fields and on construction those fields get filled with objects depending on config/"circumstances".
Basically this, yes. There are plenty of game engines & games that do similar things. See modding in Civilization 5 (XML / Lua based as well).

I will agree that if you don't plan the initial design this way, it is far too much effort to change later... As it is already too late, this debate is moot.

Rseding91
Factorio Staff
Factorio Staff
Posts: 14152
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Make the API less rigid.

Post by Rseding91 »

ratchetfreak wrote:
Rseding91 wrote: That's just not how any of this works in real-world programming. I don't know of one game or game engine that works the way you're talking about. In fact I'm not even sure a game could be implemented to work that way (since no one has done it on a game that has actually sold).

Even if it was feasible to implement the performance implications of making it work and the resulting code would be un-maintainable :\
ever heard of dependency injection?

There an object has a set of fields and on construction those fields get filled with objects depending on config/"circumstances".
I don't think that means what you think it means: https://en.wikipedia.org/wiki/Dependency_injection - that's basically how Factorio operates: prototypes define the instance properties and the game engine creates the corresponding entity with those instance properties.
If you want to get ahold of me I'm almost always on Discord.

ratchetfreak
Filter Inserter
Filter Inserter
Posts: 952
Joined: Sat May 23, 2015 12:10 pm
Contact:

Re: Make the API less rigid.

Post by ratchetfreak »

Rseding91 wrote:
I don't think that means what you think it means: https://en.wikipedia.org/wiki/Dependency_injection - that's basically how Factorio operates: prototypes define the instance properties and the game engine creates the corresponding entity with those instance properties.
Then give us more control over what those injected instance properties are.

Here's a challenge: each time you create a new entity type, first go on the modders side of the API and try to implement it. If you can't or you have to do it in a convoluted way then add the needed functionality to the modding API. After that you can hardcode the entity in the engine. Or take a look at the existing mods and see where they have to hack around the current API and go make life easier on them.

For example combinators, they need to read the input, do some math and write output. Writing output could be done by hiding a smart chest in there but that doesn't give access to the (new) special signals, the constant combinator is limited to a fixed number of signals. Reading the value needs a binary search on a hidden lamp.

GUI wise what's needed is a way to select an item/signal.

User avatar
Klonan
Factorio Staff
Factorio Staff
Posts: 5246
Joined: Sun Jan 11, 2015 2:09 pm
Contact:

Re: Make the API less rigid.

Post by Klonan »

Kerbal space program implemented a system called the part modules, which let any part, contain any number of modules, with each module having its own function.

Explanation on the KSP wiki

Im no expert or do i have much experience modding in KSP, but the part module does make it really simple to make custom parts, and picking and choosing what functions a specific part will have

vzybilly
Fast Inserter
Fast Inserter
Posts: 143
Joined: Thu May 14, 2015 6:10 pm
Contact:

Re: Make the API less rigid.

Post by vzybilly »

Alright, I was messing with trains and have found allot of stuff not in the lua API.
Good example: Electric trains that connect to the power network.

You can set the energy source to an electric consumer with no complaints, but it won't connect to anything.
The energy supply is reset on each tick. no value to access the buffer supply of energy, even for the burner source type (can't even access energy of assembly machines!).
Only way to make it work and connect to the electric network would be to put in an invisible accumulator that connects to the energy network, then EACH tick, pull 600 from it's buffer and put 1066.6 into the train so it can move at full power for a single tick. any more than 1066.6 will be lost! you also have to remove and place the invisible accumulator each tick if you want it to seem like the train gets power from the network.

Trains support running off of electric power but to get them to move, you have to hack allot per tick! no access to internal energy buffer!

And that's just for a lonely train.
Will code for Food. I also have 11+ mods!

Rseding91
Factorio Staff
Factorio Staff
Posts: 14152
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Make the API less rigid.

Post by Rseding91 »

vzybilly wrote:Alright, I was messing with trains and have found allot of stuff not in the lua API.
Good example: Electric trains that connect to the power network.

You can set the energy source to an electric consumer with no complaints, but it won't connect to anything.
The energy supply is reset on each tick. no value to access the buffer supply of energy, even for the burner source type (can't even access energy of assembly machines!).
Only way to make it work and connect to the electric network would be to put in an invisible accumulator that connects to the energy network, then EACH tick, pull 600 from it's buffer and put 1066.6 into the train so it can move at full power for a single tick. any more than 1066.6 will be lost! you also have to remove and place the invisible accumulator each tick if you want it to seem like the train gets power from the network.

Trains support running off of electric power but to get them to move, you have to hack allot per tick! no access to internal energy buffer!

And that's just for a lonely train.
You are accessing the internal energy buffer of the train every time you set entity.energy. If you couldn't se it then you can't access the buffer - but you can. You can also access the energy of an assembling machine using the default entity.energy.

The actual issue is electric buffer sizes are dynamically set to the idle power usage of the entity and resized as the entity starts to draw more power. Trains are not designed to run off electricity - neither are trees - that's why they don't work when you set them to run off electricity.

Because trains (and trees and most entities) don't use electricity they don't run the code to use electricity and don't eat up un-necessary CPU time doing stuff that they would 99.99% of the time not use.
If you want to get ahold of me I'm almost always on Discord.

ratchetfreak
Filter Inserter
Filter Inserter
Posts: 952
Joined: Sat May 23, 2015 12:10 pm
Contact:

Re: Make the API less rigid.

Post by ratchetfreak »

Rseding91 wrote:
You are accessing the internal energy buffer of the train every time you set entity.energy. If you couldn't se it then you can't access the buffer - but you can. You can also access the energy of an assembling machine using the default entity.energy.

The actual issue is electric buffer sizes are dynamically set to the idle power usage of the entity and resized as the entity starts to draw more power. Trains are not designed to run off electricity - neither are trees - that's why they don't work when you set them to run off electricity.

Because trains (and trees and most entities) don't use electricity they don't run the code to use electricity and don't eat up un-necessary CPU time doing stuff that they would 99.99% of the time not use.
But what he wants is to set the buffer size to some (higher) value and only refill once in a while instead of excess being lost

Besides that getting explicit control over trains would also be nice like setting a manual path and telling it to go instead of pathing to a station.

Letting us create a new type of rail signal (path signal for example or a circuit controlled signal) would also be nice. (fully controlled by the mod code)

vzybilly
Fast Inserter
Fast Inserter
Posts: 143
Joined: Thu May 14, 2015 6:10 pm
Contact:

Re: Make the API less rigid.

Post by vzybilly »

the trains show in the gui how much of their buffer is filled with energy. when setting it to the max, the gui still shows empty. also, when the gui shows full, the train can go a long distance but when I set it, even to an insane amount, it only goes about a tile... or less.

that's why I say that it doesn't change the buffer of energy, because it's changing a "per tick buffer".
Will code for Food. I also have 11+ mods!

Post Reply

Return to “Won't implement”